简单 I/O
模型对简单的需求而言还算适用,但对于诸如同时读写多个文件等更高级的文件操作来说就不够了。对于这些文件的操作,我们需要用到完整 I/O
模型。
io.open
可以适用函数 io.open
来打开一个文件,该函数仿造了 C
语言中的函数 fopen
。这个函数有两个参数,一个参数是待打开文件的文件名,另一个参数是一个模式字符串。模式字符串包括表示只读的 r
、表示只写的 w
(也可以用来删除文件中原有的内容),表示追加的 a
,以及另一个可选的表示打开二进制文件的 b
。函数 io.open
返回对应文件的流。当发生错误时,该函数会在返回 nil
的同时返回一条错误信息及一个系统相关的错误码:
print(io.open("non-existent-file", "r")) --> nil non-existent-file: No such file or directory 2 print(io.open("/etc/password", "w")) --> nil /etc/password: Permission denied 13点击复制复制失败已复制
assert
检查错误的一种典型方法是使用函数 assert
:
local f = assert(io.open(filename, mode))
如果函数 io.open
执行失败,错误信息会作为函数 assert
的第二个参数被传入,之后函数 assert
会将错误信息展示出来。
在打开文件后,可以使用方法 read
和 write
从流中读取和向流中写入。他们与函数 read
和 write
类似,但需要使用冒号运算符将他们当做流对象的方法来调用。例如,可以使用如下的代码打开一个文件并读取其中所有内容:
local f = assert(io.open(filename, "r")) local t = f:read("a") f:close()
句柄
I/O
库提供了三个预定义的 C
语言流的句柄: io.stdin
、 io.stdout
和 io.stderr
。例如,可以使用如下的代码将信息直接写到标准错误流中:
io.stderr:write(message)
函数 io.input
和 io.output
允许混用完整 I/O
模型和简单 I/O
模型。调用无参数的 io.input()
可以获得当前输入流,调用 io.input(handle)
可以设置当前输入流(类似的调用同样适用于函数 io.output
)。例如,如果想要临时改变当前输入流,可以像这样:
local temp = io.input() -- 保存当前输入流 io.input("newinput") -- 打开一个新的当前输入流 -- 对新的输入流进行某些操作 io.input():close() -- 关闭当前流 io.input(temp) -- 恢复此前的当前输入流
注意
io.read(args)
实际上是 io.input():read(args)
的简写,即函数 read
是用在当前输入流上的。同样, io.write(args)
是 io.output():write(args)
的简写。
io.lines
除了函数 io.read
外,还可以用函数 io.lines
从流中读取内容。正如之前示例中展示的那样,函数 io.lines
返回一个可以从流中不断读取内容的迭代器。给函数 io.line
提供一个文件名,它就会以只读方式打开对应文件的输入流,并在到达文件末尾后关闭该输入流。若调用时不带参数,函数 io.lines
就从当前输入流读取。我们也可以把函数 lines
当做句柄的一个方法。此外,从 Lua5.2
开始,函数 io.lines
可以接受和函数 io.read
一样的参数。例如,下面的代码会以 8KB
为块迭代,将当前输入流中的内容复制到当前输出流中:
for block in io.input():lines(2^13) do io.write(block) end