Lua中的I/O库

来源:互联网 发布:js代码重复度检查 编辑:程序博客网 时间:2024/06/01 18:56

I/O库为文件操作提供了两种不同的模型,简单模型(simple model)和完整模型(complete model)。简单模型假设有一个当前输入文件和一个当前输出文件,它的I/O操作均作用于这些文件,完整模型则使用显式的文件句柄。

1.简单I/O模型

简单I/O模型的所有操作都作用于当前两个文件。I/O库将当前输入文件初始化为进程标准输入(stdin)文件,将当前输出文件初始化为进程标准输出(stdout)文件,在执行io.read()操作时就会从标准输入中读取一行。

函数io.input和io.output可以改变这两个当前文件。io.input(filename)调用会以只读的方式打开指定的文件,并将其设为当前输入文件。以后除非再次调用io.input,否则以后所有的输入都将来源于这个文件。在输出方面,io.output也可以完成类似地工作。要想用完整模式必须使用完整模式中的io.open。

以后无论使用print还是io.write都有一个原则。即在随意编写(quick-and-dirty)的程序中,或者为调试目的而编写的代码中,提倡使用print;而在其他需要完全控制输出的地方使用io.write
print("hello","Lua"); print("Hi")-->hello Lua-->Hiio.write("hello","Lua");  io.write("Hi","\n")-->helloLuaHi
write和print有几点不同。首先,write在输出时不会添加像制表符或回车这样的额外字符。其次,write使用当前输出文件,而print总是使用标准输出文件。最后print会自动调用其参数的tostring()方法,因此它还能显示table、函数和nil。

函数io.read从当前输入文件中读取字符串,它的参数决定了要读取的数据:
"*all"读取整个文件"*line"读取下一行"*number"读取一个数字<num>读取一个不超过<num>个字符的字符串调用io.read("*all")会读取当前输入文件的所有内容,以当前位置作为开始。如果当前位置处于文件的末尾,或者文件为空,那么调用该调用会返回一个空字符串。
由于Lua可以高效地处理长字符串,因此在Lua中一种简单的、编写过滤器的技术就可以将整个文件读取到一个字符串中,然后处理这个字符串(通常是gsub),最后把这个字符串写到输出:
t=io.read("*all")t=string.gsub(t,...)-->做相关的处理io.write(t)

gsub中使用的模式可以捕获所有编码为128~255的字符及等号字符。
调用io.read("*line")会返回当前文件的下一行,但不包括换行字符,当到达文件末尾时,该调用回返回nil,以表示无后续行可返回。
在io.read的参数里面,还可以用一个数字n作为read的参数。此时,read会试着从输入文件中读取n个字符。如果读不到任何字符,它会返回nil。否则会返回一个最多n个字符的字符串。下面这个示例演示了这种读取模式,它是一种将数据从stdin复制到stdout的高效方法:
while true dolocal block=io.read(2^13)   -->缓冲区大小为8Kif not block then break endio.write(block)end

io.read(0)是一个特殊情况,它用于检查是否到达了文件末尾。如果还有数据可以读取,它会返回一个空字符串,否则返回nil。

2.完整I/O模型

如果需要对I/O作进一步的控制,就要用到完整I/O模型。这个模型是基于文件句柄的,它等价于C语言中的流(FILE*),表示一个具有当前位置的打开文件。
打开一个文件,可以使用io.open函数,可寻参数中r代表读取,w代表写入,a代表追加,另外还有一个可选参数b代表二进制。open函数会返回表示文件的新句柄。若发生错误,则返回nil,以及一条错误消息和一个错误代码。
当打开一个文件后就可以用read/write方法进行读写了。这与read/write函数相似,但是需要用冒号语法,将它们作为文件句柄的方法来调用。如下,要打开一个文件,并读取其所有内容,可以这么做:
local f=assert(io.open(filename,"r"))local t=f:read("*all")f:close()
I/O库提供了3个预定义C语言流的句柄:io.stdin、io.stdout和io.stderr。这样就可以将信息写到错误流
io.stderr:write(message)
通过不指定参数调用io.input(),可以得到当前输入文件的句柄。而通过io.input(handle),可以设置当前输入文件的句柄。例如:要临时改变当前输入文件,可以这么做:
local temp=io.input()   -->保存当前文件io.input("newinput")    -->打开一个新的当前文件<对新的输入文件做一些操作>io.input():close()      -->关闭当前文件io.input(temp)          -->恢复原来的输入文件


3.其他文件操作

函数tmpfile返回一个临时文件的句柄,这个句柄是以读写方式打开。这个文件会在程序结束时自动删除。函数flush会将缓冲中的数据写入文件。它与write函数一样,将其作为一个函数调用时,io.flush()会刷新当前输出文件。而将其作为一个方法调用时,f:flush()会刷新某个特定的文件f.
函数seek可以获取和设置一个文件的当前位置。它的一般形式是f:seek(whence,offset),其中whence参数是一个字符串
,指定了如何解释offset参数,它的有效值包括“set”,offset解释为相对于文件起始的偏移量,”cur”,offset解释为相对于当前位置的偏移量。“end”,offset解释为相对于文件末尾的偏移量。
whence的默认值是“cur”,offset的默认值是0.因此调用file:seek()不会改变文件的当前位置,并会返回当前的文件位置。调用file:seek("set")会将当前位置重置为文件的起始处并返回0.调用file:seek(“end”)会将当前位置设置到文件的末尾,并返回文件的大小。下面这个函数可以不改变文件的当前位置而获取文件的大小:

function fsize(file)local current=file:seek()     --获取当前位置local size=file:seek("end")   --获取文件大小file:seek("set",current)      --恢复位置return sizeend-->如果有错误发生,所有这些函数都会返回nil和一条错误消息


0 0
原创粉丝点击