**This is an old revision of the document!**

Buffer(缓冲) API

buffer库提供了便于使用的IO流。本库提供的流更像是io库提供的,由io.open返回的流,不像filesystem.open返回的原始流,后者支持的方法没有前者那么多。下文的实例方法板块列出的方法可被用于从io.open函数获取的文件句柄。因此就算你没打算构建自定义带缓冲IO流,此API文档也会大有裨益。

此外,该API还允许你创建带缓冲IO流。你需要提供后端的流式读取和流式写入,buffer库提供数据缓冲与格式化。一般而言,用户无需构建自己的带缓冲输入输出流。以备参考,io库就使用了带缓冲IO流(包含文件io和控制台io)。

静态方法

下列方法从buffer库自身调用。

  • buffer.new([mode: string], stream: table)

用读写模式(mode)来修饰传入的流(stream),以创建一个带缓冲IO流。模式(mode)可以为只读(r或nil)、读写(rw)或仅写入(w)。请查看stream对象所需的流实例方法有关内容。

实例方法

下列方法只能从buffer.new创建的实例处调用(注意:io.open返回的文件句柄也是buffer.new创建的带缓冲IO流)这些方法均为实例方法,需要实例调用符号:。为了有助于区分这些实例方法与静态方法(例如buffer.new),这些方法名将会加上b:作为前缀。

  • b:flush() 如果缓冲区存在任何数据,立即将其写入到IO流并释放。
  • b:close() 清空缓冲区并关闭修饰的流。
  • b:setvbuf([mode: string], [size: number]) mode, size 设定缓冲区的模式(mode)和大小(size),并返回修改后的模式(mode)和大小(size)。size指定了缓冲的数据量,默认范围为[512,8192]字节,根据可用系统内存而变化。modesize可以为nil,此时将会沿用先前的值。size还被用于对流的read(n)调用。
    模式只影响write方法,可用值包括:
    • “no” 写入数据被立即推送进IO流。
    • “full” 写入数据会被缓存,直到尺寸到达size字节。这是默认模式。
    • “line” 写入数据会被缓存,直到出现换行或达到size上限。
  • b:write([values...]) 将所有的value写入到IO流,首先依据缓冲模式和缓冲区大小(参见setvbuf)。请注意要写入文件的话,需要将文件以可写入模式打开。
snippet.lua
local file = io.open("/tmp/foo.txt", "w")
file:write("abc", "def", "\n")
file:close()
-- foo.txt中现在的内容为"abcdef\n"
  • b:lines([line_formats...]) string array 返回一个迭代器,其会从IO流进行读取,直到读取到nil。每次读取时,都会将参数列表line_formmats传递给stream:read(...)。绝大多数使用情况下都不需要定义line_format,也就是不给line()传参。迭代器的默认行为(即没有line_format时)是每次从IO流中读取一行内容。
snippet.lua
local file = io.open("/tmp/foobar.txt")
for line in file:lines() do
  process_next_line(line)
end
file:close()
  • b:read([formats...]) string... 相当先进的读取器,可支持多种格式。首先,如果不指定format调用,即参数列表留空,它会从IO流中读取下一行,等价于read("*l")format指定的每个值都会先从IO流中读出,结果一次性以多个返回值的形式返回。请注意格式字符串都有 * 前缀,而且只有字符串的第一个字符有意义,其余字符将会被忽略。下列是支持的格式:
    • 一个数字值,例如10 从IO流读取n个字节(以二进制模式)或字符(以文本模式),结果将以字符串形式返回。参见io.open以获取有关如何以不同模式打开文件的更多信息。

      local chars = b:read(10)

    • “*n” 或 “*number”

从IO流中读取下一组可被解释为数字的字节。请注意读取到的数字会受到打开模式为二进制还是文本的影响。参见io.open以获取有关如何以不同模式打开文件的更多信息。

`local number = b:read("*n")`

* "\*l" or "\*line"

从IO流中读取下一行,截掉换行标记(可能是 \n,、\r或\r\n)。

`local line = b:read("*l")`

* "\*L" or "\*Line"

从IO流中读取下一行,类似“*line”,但是在结果中保留换行标记。

`local whole_line = b:read("*L")`

* "\*a" or "\*all"

从IO流中读取所有剩余内容,直到遇到nil。在此读取格式后再指定其他格式没有意义。

  `local the_whole_file = b:read("*a")`

- b:getTimeout() number 返回当前带缓冲IO流设定的超时时间(单位为秒)。默认超时时间为math.huge。参阅setTimeout以获取有关于带缓冲IO流超时时间影响的更多信息。 - b:setTimeout(timeout) 设定带缓冲IO流限制read操作的时长,单位为秒。请注意此超时值无法被严格遵守。只需一次readChunk(支持read方法的内部方法)即可完成的读取操作中不会检查timeout的限制。只有在流读取操作的间隔才会检查是否超时(下附一份样例)。因此,如果一次读取操作中需要多次块读取,并且首次块读取开始和最后一次块读取开始之间的时长大于等于超时时间,IO流会出错。再次强调,超时时间默认为math.huge

snippet.lua
local file = buffer.new("r", { read = function() os.sleep(5) return "a" end })
file:setvbuf("full", 1) -- 将缓冲区大小设定为1字符
file:setTimeout(1) -- 将缓冲超时时间设定为1秒
-- 在尝试读取第二个字符之前就会超时
local a, b = file:read(1, 1) --读取一个字符,紧接着再读取一个字符
  • b:seek([whence:string], [offset:number])

whence开始移动IO流位置,共移动offset字节,两个参数都是可选的。whence默认为“cur”,'offset'默认为0。 可用的whence值:

  1. “cur” 从当前位置开始。
  2. “set” 从IO流的开始位置。
  3. “end” 从IO流的结束位置。

返回在IO流中查找操作的结果(可能为失败)。

Interface Methods

The following methods are expected to be implemented on the buffered streams passed to buffer.new.

  • close() ok, reason

    Close handles, release resources, disconnect – and return success

  • write(arg: string) ok, reason

    Write arg as bytes, assume a string of plain unformatted chars. Return falsey and reason on failure.

  • read(n: number) ok, reason

    Return n bytes, and not n unicode-aware chars. Assume your data is binary data and let the buffer library manage the mode and the unicode string packaging (if applicable). Note that this is exactly how the filesystem library operates.The caller assumes there is more data to read until nil is returned. A empty string or a string shorter than n chars long is a valid return, but the caller may assume there is more data to request until nil is returned.

  • seek([whence: string], [offset: number]) [offset from start] or falsey, reason

    Refer to b:seek() for details. In short, move the stream position to offset from whence, and return the offset from the start of the stream of the position after the seek operation. Note that seek("cur", 0) is a valid request, typical of the caller wanting to determine the current position of the stream. Your stream is not required to support seek, in such case (or in any case of failure) you should return nil, and the reason (as a string) for the failure.

Examples

目录