快速掌握Lua 5.3 —— I/O库 (2)
2016-03-04 00:04
351 查看
Q:什么是”Complete Model”?
A:所有的文件操作都基于明确指定的文件句柄,可以同时打开多个文件句柄。这就意味着同一时间可以操作多个文件,对于每一个文件读或写均可。文件句柄等同于C语言中的”FILE*”,它代表一个被打开文件的当前读取位置。io.open()可以指定打开的文件,并返回其文件句柄,
[code]--[[ io.open(filename [, mode]) 以"mode"模式打开文件"filename",返回其文件句柄。 "mode"有以下选项,功能与C语言中的"fopen()"的"mode"参数功能相同: "r": 以只读方式打开,文件不存在时报错(不指定时,默认使用此选项); "w": 以只写方式打开,若文件存在则清空文件,否则创建文件; "a": 以附加只写的方式打开,若文件不存在,则会创建文件,如果文件存在, 写入的数据会被加到文件尾,即文件原先的内容会被保留(原来的EOF符保留); "r+": 以可读写方式打开,文件不存在时报错; "w+": 以可读写方式打开,若文件存在则清空文件,否则创建文件; "a+": 以附加可读写的方式打开,若文件不存在,则会创建文件,如果文件存在, 写入的数据会被加到文件尾后,即文件原先的内容会被保留(原来的EOF符不保留); 当出错时返回"nil"+错误信息+错误码。]] print(io.open("file", "r")) -- "file"文件不存在。 --> nil file: No such file or directory 2 local f = io.open("file", "w+") -- 创建"file"文件。 f:write("Hello World!") f:close() --[[ "file"文件中: Hello World!]] print(io.open("/etc/passwd", "w")) --> nil /etc/passwd: Permission denied 13
Q:如何操作文件句柄?
A:之前的例子已有涉及,我们可以通过文件句柄直接调用”read”,”write”等函数,他们的功能对应各自的io.*()形式的函数,因为
io.*()形式的函数实际上调用的是
io.input():*(),
[code]local f = io.open("file", "w+") --[[ 其功能等价于"io.input("file"); io.read()"。 因为"io.read()"实际上调用的是"io.input():read()"。]] f:read() for l in f:lines() do -- "file:lines()"不同于"io.lines()",在循环结束时不会关闭文件句柄。 -- do something end f:write("something") f:flush() -- 强制将写入缓存保存到文件中。 --[[ file:setvbuf(mode [, size]) 设置写入文件的数据的缓冲模式。"mode"可以设置为以下值: "no": 不缓冲。写入数据直接存储到文件中。 "full": 全缓冲。只有在缓存满或是显式的对文件调用"flush()"时,数据才写入到文件。 "line": 行缓冲。当遇到换行时将数据写入文件(对于某些特殊文件,例如终端设备,是遇到任何输入前)。 对于后两种模式,"size"以字节为单位指定缓冲区的大小。]] --[[ file:seek([whence [, offset]]) 根据"whence"指定的模式,将文件当前读取位置偏移"offset"个字节。"whence"可指定的模式如下: "set": 将文件当前读取位置定位到文件开头。 "cur": 将文件当前读取位置定位到当前位置。 "end": 将文件当前读取位置定位到文件结尾。 "whence"默认为"cur";"offset"默认为0。函数返回文件当前读取位置距文件开头的偏移。 此函数没有对应的"io.seek()"。]] -- 在不改变文件读取位置的情况下获取文件的大小。 function fsize(file) local current = file:seek() -- get current position local size = file:seek("end") -- get file size file:seek("set", current) -- restore position return size end f:close()
Q:如何将一个文件的内容按照十六进制编辑器的样式输出?
A:[code]-- "a.lua"文件中的内容: local f = assert(io.open(arg[1], "r")) local block = 10 -- 每次转换10个字符,作为一行显示。 while true do local bytes = f:read(block) if not bytes then break end for b in string.gmatch(bytes, ".") do -- 匹配任意字符。 -- 将字符转换为十六进制的形式。 io.write(string.format("%02X ", string.byte(b))) end --[[ 十六进制与正常的字符之间的空格("+1"为的就是这些空格)。 "%02X "的模式正好占3个字符的位置,所以最后一行如果不足10个字符, 每个不够的字符位置使用3个空格代替。]] io.write(string.rep(" ", block - string.len(bytes) + 1)) -- 控制字符都转换为了"."输出。 io.write(string.gsub(bytes, "%c", "."), "\n") end -- 以脚本本身作为输入文件。 --[[ result: > lua a.lua a.lua 6C 6F 63 61 6C 20 66 20 3D 20 local f = 61 73 73 65 72 74 28 69 6F 2E assert(io. 6F 70 65 6E 28 61 72 67 5B 31 open(arg[1 ... 79 74 65 73 2C 20 22 25 63 22 ytes, "%c" 2C 20 22 2E 22 29 2C 20 22 5C , "."), "\ 6E 22 29 0A 65 6E 64 0A n").end. ]]
附加:
1、当文件为空,或者文件当前的读取位置在文件尾时,file:read()与
io.read()的行为相同。
file:read("a")会返回空字符串,而
file:read("l")和io.read(“*number”)都会返回nil。
2、
[code]local f = io.open("file", "r") ... -- 执行若干次"f:read()"。 print(f:seek()) -- 打印文件当前的读取位置。 print(f:seek("end", 0)) -- 打印文件大小。
3、I/O库还提供了3个预定义的标准文件句柄,
io.stdin,
io.stdout和
io.stderr。你可以使用他们直接对标准输入、标准输出和标准错误输出读或写。
[code]print(io.stdin:read()) -- 输入什么,打印什么。 print(io.stdout:write("123")) -- 123 print(io.stderr:write("123")) -- 123
4、通常在Lua中,将文件作为一个整体读取会比逐行读取要快。但有些时候,我们会面对不适合我们一次性读取的巨大的文件(比如10M或100M的文件),如果你想要在读取这类文件时达到最佳性能,你可以使用一个”chunk”大小的方式读取(例如8KB)。为了防止原文件中的一行被截断,还要在
io.read()中多增加一个参数
*l,
[code]--[[ "file"文件中内容: line1 abc line2 line3 def]] -- "a.lua"文件中内容: local BUFSIZE = 2^13 -- 8K local f = io.input(arg[1]) -- open input file local cc, lc, wc = 0, 0, 0 -- char, line, and word counts while true do -- 首先读取一个"chunk"的大小。为了防止一行被截断,将本行中剩余部分读完。 local lines, rest = f:read(BUFSIZE, "*L") if not lines then break end if rest then lines = lines .. rest end -- 把被截断的一行重新拼接起来。 cc = cc + string.len(lines) -- 共包含多少个字符。 local _, t = string.gsub(lines, "%S+", "") -- 共包含多少个单词。 wc = wc + t _, t = string.gsub(lines, "\n", "\n") -- 共包含多少行。 lc = lc + t end print(lc, wc, cc) -- 其打印结果与"wc"命令的结果相同。 --[[ result: > lua a.lua file 3 5 26 > wc file 3 5 26 file]]
5、在类Unix的操作系统中,文本模式的文件与二进制模式的文件没有什么区别。但在Windows操作系统中可就不一样了,需要特定的标志才能正确的打开二进制文件。所以如果你的程序需要考虑跨平台的话,最好在打开二进制文件时指定”b”标志。
[code]--[[ 一个比较实用的例子是转换Windows中的换行符"\r\n"到Unix中的换行符"\n"。 我们不使用标准输入和标准输出,因为他们是以文本模式读取和写出数据的, 取而代之的是使用参数指定输入输出文件。]] local inp = assert(io.open(arg[1], "rb")) local out = assert(io.open(arg[2], "wb")) local data = inp:read("*a") data = string.gsub(data, "\r\n", "\n") out:write(data) assert(out:close())
相关文章推荐
- Java中使用Lua脚本语言(转)
- lua、groovy嵌入到java中的性能对比(转)
- c++调用lua的基本操作
- mac 安装lua命令
- lua中获取系统当前的时间
- lua调用的c函数模块命名规则
- Lua学习笔记5:类及继承的实现
- Lua 的简单介绍
- 使用Lua的扩展库LuaSocket用例
- lua ffi简介
- lua userdata
- Lua Development Tools (LDT)
- MAC上搭建lua开发环境
- Windows环境下编译lua
- Lua开发
- lua具名实参
- SLua 优化初始化速度
- lua.c:80:31: fatal error: readline/readline.h: No such file or directory
- 78.Evaluate the following query:
- lua html式解析