buffer
库提供了便于使用的IO流。本库提供的流更像是io
库提供的,由io.open
返回的流,不像filesystem.open
返回的原始流,后者支持的方法没有前者那么多。下文实例方法板块列出的方法也可用于从io.open
函数获取的文件句柄,因此就算你没打算构建自定义带缓冲流,此API文档也会大有裨益。
此外,该API还能让你创建带缓冲流。你需要提供后端的流式读取和流式写入,buffer库提供数据缓冲与格式化。一般而言,用户无需构建自己的带缓冲流。以备参考,io库就使用了带缓冲流(包含文件io和控制台io)。
下列方法从buffer
库自身调用。
buffer.new([mode: string], stream: table)
将传入的流(stream
)封装上读写模式(mode
),以创建一个带缓冲IO流。模式(mode
)可以为只读(r或nil
)、读写(rw)或仅写入(w)。请查看stream
对象所需流的实例方法有关内容。
下列方法只能在buffer.new
创建的实例上调用(注意:io.open
返回的文件句柄也是buffer.new
创建的带缓冲流)。这些方法均为实例方法,需要实例调用符号:
。为了有助于区分这些实例方法与静态方法(例如buffer.new
),这些方法名将会加上b:
作为前缀。
b:flush()
b:close()
b:setvbuf([mode: string], [size: number]) mode, size
mode
)和大小(size
),并返回修改后的模式(mode
)和大小(size
)。size
指定了缓冲的数据量,默认范围为[512, 8192]字节,根据可用系统内存而变化。mode
和size
可以为nil,此时将会沿用先前的值。size
还被用于对流的read(n)
调用。write
方法,可用值包括:no
:写入数据被立即推送进IO流。full
:写入数据会被缓存,直到尺寸到达size
字节。这是默认模式。line
:写入数据会被缓存,直到出现换行或达到size
上限。
b:write([values...])
value
写入到IO流,首先会依据缓冲模式和缓冲区大小(参见setvbuf
)进行缓存。请注意要写入文件的话,需要将文件以可写入模式打开。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
nil
。每次读取时,都会将参数列表line_formmats
传递给stream:read(...)
。绝大多数使用情况下都不需要定义line_format
,也就是不给line()
传参。迭代器的默认行为(即没有line_format
时)是每次从流中读取一行内容。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
调用,即参数列表留空,它会从流中读取下一行,等价于read("*l")
。format
值都会先从IO流中读出,再一次性以多个返回值的形式返回。请注意格式字符串都有 * 前缀,而且只有字符串的第一个字符有意义,其余字符将会被忽略。10
local chars = b:read(10)
*n
或者*number
local number = b:read("*n")
*l
或者*line
local line = b:read("*l")
*L
或者*Line
*line
,但是在结果中保留换行标记。local whole_line = b:read("*L")
*a
或者*all
local the_whole_file = b:read("*a")
b:getTimeout() number
math.huge
。参阅setTimeout
以获取有关于带缓冲流超时时间影响的更多信息。b:setTimeout(timeout)
设定带缓冲流限制read
操作的时长,单位为秒。请注意此超时值无法被严格遵守。只需一次readChunk
(实际调用read
方法的内部方法)即可完成的读取操作中不会检查timeout
的限制。只有在流读取操作的间隔才会检查是否超时(下附一份样例)。因此,如果一次读取操作中需要多次块读取,并且首次块读取开始和最后一次块读取开始之间的时长大于等于超时时间,IO流会出错。再次强调,超时时间默认为math.huge
。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
值:
下列方法应当在打算传给buffer.new
的带缓冲IO流上实现。
close() ok, reason
write(arg: string) ok, reason
arg
,假定提供的是不加修饰的未格式化字符。失败时返回假值和原因。read(n: number) ok, reason
n
个字节,而不是n
个考虑Unicode的字符。我们假设你的数据为二进制数据,并且让buffer库管理IO模式与Unicode字符串打包(如果可用)。请注意这就是filesystem库的工作方式。直到返回nil
前,此方法的调用者都会假定还有更多数据可读取。空字符串或长度短于n
的字符串也是合法返回值,但调用者可能假定在返回nil
前仍可请求更多数据。seek([whence: string], [offset: number]) [offset from start] or falsey, reason
b:seek()
以获取细节。简而言之,从whence
起将IO流位置移动offset
,并返回从IO流开始位置到seek操作结束后的位置之间的offset
值。请注意,seek("cur", 0)
也是合法请求,被用于调用者想获取IO流当前位置的情况下。你的自定义IO流不需要一定支持seek
,这种情况下(以及任何失败情况下)你需要返回nil和失败原因(以字符串形式)。