lua中的io分为两种模式:
- 简单模式(simple model)拥有一个当前输入文件和一个当前输出文件,并且提供针对这些文件相关的操作。
- 完全模式(complete model) 使用外部的文件句柄来实现。它以一种面对对象的形式,将所有的文件操作定义为文件句柄的方法
模式 | 描述 |
---|---|
r | 以只读方式打开文件,该文件必须存在。 |
w | 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。 |
a | 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(EOF符保留) |
r+ | 以可读写方式打开文件,该文件必须存在。 |
w+ | 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。 |
a+ | 与a类似,但此文件可读可写 |
b | 二进制模式,如果文件是二进制文件,可以加上b |
+ | 号表示对文件既可以读也可以写 |
简单模式:需要像下面一定定义一个输出和输出文件。
-- 以只读方式打开文件
file = io.open("test.lua", "r")
-- 设置默认输入文件为 test.lua
io.input(file)
-- 输出文件第一行
print(io.read())
-- 关闭打开的文件
io.close(file)
-- 以附加的方式打开只写文件
file = io.open("test.lua", "a")
-- 设置默认输出文件为 test.lua
io.output(file)
-- 在文件最后一行添加 Lua 注释
io.write("-- test.lua 文件末尾注释")
-- 关闭打开的文件
io.close(file)
模式 | 描述 |
---|---|
"*n"或者*number | 读取一个数字并返回它。例:file.read("*n") |
"*a" 或者*all | 从当前位置读取整个文件。例:file.read("*a") |
"*l"(默认)或者*line | 读取下一行,在文件尾 (EOF) 处返回 nil。例:file.read("*l") |
number或者num | 返回一个指定字符个数的字符串,或在 EOF 时返回 nil。例:file.read(5) |
其他的 io 方法有:
io.tmpfile():返回一个临时文件句柄,该文件以更新模式打开,程序结束时自动删除
io.type(file): 检测obj是否一个可用的文件句柄
io.flush(): 向文件写入缓冲中的所有数据
io.lines(optional file name): 返回一个迭代函数,每次调用将获得文件中的一行内容,当到文件尾时,将返回nil,但不关闭文件。
完全模式:就是用file对象来操作文件。
-- 以只读方式打开文件
file = io.open("test.lua", "r")
-- 输出文件第一行
print(file:read())
-- 关闭打开的文件
file:close()
-- 以附加的方式打开只写文件
file = io.open("test.lua", "a")
-- 在文件最后一行添加 Lua 注释
file:write("--test")
-- 关闭打开的文件
file:close()
读取二进制文件:默认的简单模式总是以文本模式打开。在 Unix 中二进制文件和文本文件并没有区 别,但是在如 Windows 这样的系统中,二进制文件必须以显式的标记来打开文件。控制 这样的二进制文件,你必须将“b”标记添加在 io.open 函数的格式字符串参数中。
如:local inp = assert(io.open(arg[1], "rb")) local out = assert(io.open(arg[2], "wb"))
设置读取坐标:
file:seek(optional whence, optional offset): 设置和获取当前文件位置,成功则返回最终的文件位置(按字节),失败则返回nil加错误信息。参数 whence 值可以是:
不带参数file:seek()则返回当前位置,file:seek("set")则定位到文件头,file:seek("end")则定位到文件尾并返回文件大小
"set": 从文件头开始
"cur": 从当前位置开始[默认]
"end": 从文件尾开始
offset:默认为0
file:flush(): 向文件写入缓冲中的所有数据
io.lines(optional file name): 打开指定的文件filename为读模式并返回一个迭代函数,每次调用将获得文件中的一行内容,当到文件尾时,将返回nil,并自动关闭文件。
若不带参数时io.lines() <=> io.input():lines(); 读取默认输入设备的内容,但结束时不关闭文件,
for line in io.lines("main.lua") do
print(line)
end
以下实例使用了 seek 方法,定位到文件倒数第 25 个位置并使用 read 方法的 *a 参数,即从当期位置(倒数第 25 个位置)读取整个文件。
-- 以只读方式打开文件
file = io.open("test.lua", "r")
file:seek("end",-25)
print(file:read("*a"))
-- 关闭打开的文件
file:close()
注意:由于通常 Lua 中读取整个文件要比一行一行的读取一个文件快的多。尽管我们有时 候针对较大的文件(几十,几百兆),不可能把一次把它们读取出来。要处理这样的文件 我们仍然可以一段一段(例如 8kb 一段)的读取它们。同时为了避免切割文件中的行, 还要在每段后加上一行: local lines, rest = f:read(BUFSIZE, "*line") 以上代码中的 rest 就保存了任何可能被段划分切断的行。然后再将段(chunk)和行 接起来。这样每个段就是以一个完整的行结尾的了。以下代码就较为典型的使用了这一 技巧。该段程序实现对输入文件的字符,单词,行数的计数。
local BUFSIZE = 2^13 -- 8K --BUFSIZE代表字节数 read返回的第二个参数是读取完该行字节数后剩余的部分
local f = io.input(arg[1]) -- open input file
local cc, lc, wc = 0, 0, 0 -- char, line, and word counts
while true do
local lines, rest = f:read(BUFSIZE, "*line")
if not lines then break end
if rest then lines = lines .. rest .. '\n' end
cc = cc + string.len(lines) -- count words in the chunk Programming ,
local _,t = string.gsub(lines, "%S+", "")
wc = wc + t -- count newlines in the chunk
_,t = string.gsub(lines, "\n", "\n")
lc = lc + t
end
print(lc, wc, cc)