Skip to content

6.8 - I/O操作

I/O库提供了两种不同风格的文件操作。第一种使用隐式的文件句柄;即有些操作可以设置默认的输入文件和输出文件,并且所有的I/O操作都会使用这些默认文件来执行。第二种就是使用显式的文件句柄了。

当使用隐式的文件句柄时,其所有的操作都由表 io 提供。使用显式的文件句柄时,io.open操作会返回一个文件句柄,该文件句柄中的方法提供了相关操作。

当文件句柄关闭时,会尝试调用其元表中的 __gc 和 __close 元方法。

io 表中还提供了三个预定义的文件句柄:io.stdin、io.stdout、和 io.stderr,其和C代码中的用法含义相同。I/O库永远不会关闭这几个文件。

除非另有说明,所有的I/O函数都会在失败的时候返回fail,再加上一个错误信息作为第二个返回值以及系统相关的错误码作为第三个返回值。在非POSIX系统中,在发生错误的时对错误消息和错误码的计算可能不是线程安全的,因为其由C代码中的全局变量 errno 而来。

io.close ([file])

等效于 file:close() 。如果参数 file 缺省,则会关闭默认的输出文件。

io.flush ()

等效于 io.output():flush() 。

io.input ([file])

当传入文件名来调用,会(以文本模式)打开对应的文件,并将该文件句柄作为默认输入文件。当传入文件句柄来调用时,会直接将其设为默认输入文件。不带参数调用则会返回当前的默认输入文件。

发生错误的情况下会抛出错误,而不是返回错误码。

io.lines ([filename, ···])

以读模式打开相应的文件,并返回一个迭代器函数,用以像 file:lines(···) 一样遍历文件内容。当这个迭代器函数读取失败,其会自动关闭该文件。除了返回迭代器函数,io.lines 还会额外返回三个值:两个作为占位符的nil值,加上所创建的文件句柄。因此,当将其放在for循环中时,循环被错误或break语句打断后,该文件也会关闭。

缺省文件名调用 io.lines() 等效于 io.input():lines("l") ;即迭代默认输入文件的行。在这种情况下,迭代器不会在循环结束时关闭文件。

打开文件错误的情况下,该函数会抛出错误,而不是返回错误码。

io.open (filename [, mode])

该函数会以字符串参数 mode 所指定的模式打开参数 filename 所对应的文件。成功的情况下,其会返回一个新的文件句柄。

参数 mode 可以是以下内容:

  • r: 读模式(默认模式)。
  • w: 写模式。
  • a: 追加模式。
  • r+: 更新模式,保留之前的数据。
  • w+: 更新模式,删除之前的数据。
  • a+: 追加更新模式,保留之前的数据,只允许在文件末尾写入。

字符串参数 mode 可以用一个 'b' 做结尾,在某些系统系统中以二进制模式打开文件是必须的。

io.output ([file])

类似于io.input,但操作的是默认输出文件。

io.popen (prog [, mode])

该函数依赖于系统,其不是在所有系统上都可用的。

在单独的进程中启动 prog 程序,并返回一个文件句柄,你可以使用该句柄来从这个程序中读取数据(如果参数 mode 为 "r" ,这也是默认值),或写入数据(如果参数 mode 为 "w")。

io.read (···)

等效于 io.input():read(···) 。

io.tmpfile ()

成功的情况下,会返回临时文件的句柄。该文件是以更新模式打开并且会在程序结束时自动删除掉。

io.type (obj)

检查对象 obj 是否为一个有效的文件句柄。如果 obj 是一个打开的文件句柄,则返回字符串 "file"。如果是一个关闭的文件句柄,则返回 "closed file" 。或者不是文件句柄则返回fail

io.write (···)

等效于 io.output():write(···) 。

file:close ()

关闭文件 file 。注意文件会在其句柄被GC后自动关闭,但其关闭的时刻是不确定的。

当关闭一个由io.popen创建的文件句柄时,file:close会使用os.execute的返回值。

file:flush ()

将数据保存到文件 file 中。

file:lines (···)

返回一个迭代器函数,其每次调用都会按照给出的格式来读文件。如果没有给出格式,则默认使用 "l" 。例如:

for c in file:lines(1) do body end

这样的代码将会从当前位置遍历文件的所有字符。与io.lines不同,该函数不会在循环结束后关闭文件。

file:read (···)

按照给出的格式读取文件 file 的指定内容。对于每种格式,该函数会返回所读取的字符串或数字,或者不能按照指定格式读取数据时返回fail。(在后边的情况中,该函数不会读取后续的格式。)当不传入参数调用时,会使用默认的格式来读取下一行(如下所示)。

可用的格式有:

  • "n": 读取一个数字并作为整数或浮点数返回,其遵循Lua的词法规则。(数字前边可能有空格和符号。)该模式总是读取尽可能长的数字序列;如果没有有效的数字前缀(如,空字符串、"0x"、或者"3.4e-")或者实在太长(超过200个字符),则会放弃读取并返回fail
  • "a": 从当前位置读取整个文件。如果当前位置在文件末尾,则会返回一个空字符串,该格式永远不会失败。
  • "l": 读取下一行并忽略换行符,到达文件末尾时会返回fail。这是默认的读取格式。
  • "L": 读取下一行并保留换行符(如果有的话),到达文件末尾时会返回fail
  • number 读取若干字节的字符串,到达文件末尾时会返回fail。如果 number 为零,则什么都不会读取并返回空字符串,或者刚好在文件末尾时返回fail

"l" 和 "L" 格式只能对文本文件使用。

file:seek ([whence [, offset]])

设置并获取文件位置,所返回的位置表示为相对于文件开头偏移,而给出的位置由基于字符串参数 whence 所指的的位置的偏移 offset ,whence 字符串内容可选:

  • "set": 基于零点位置(文件开头)。
  • "cur": 基于当前位置。
  • "end": 基于文件末尾。

成功的情况下,seek 会返回最终的文件位置,其表示为为相对于文件开头的字节偏移量。如果 seek 失败了,则返回fail,以及描述错误的字符串。

参数 whence 默认为 "cur",offset 默认为0。因此,执行 file:seek() 会返回当前的文件位置而不会改变它;执行 file:seek("set") 会将当前位置设置到文件开头(并返回0);执行 file:seek("end") 会将当前位置设置到文件末尾并返回文件的大小。

file:setvbuf (mode [, size])

设置文件的缓冲模式。有三种可用模式:

  • "no": 无缓冲。
  • "full": 全缓冲。
  • "line": 行缓冲。

对于后两种情况,size 用于指定缓冲区字节大小。其默认是个适当的大小(目前源码中是一个预定义的值,其为 16 X 所处平台的指针大小 X lua_Number大小,一般为1024,即1KB)。

每种模式所指的具体行为是不可移植的,更多细节请查看所处平台的ISO标准C中的 setvbuf 函数。

file:write (···)

将接收到的每个参数都写入到文件 file 中。所传参数必须是字符串或数字。

成功的情况下,该函数返回 file 本身。