Lua 教程 在线

2073Lua 文件 I/O

文件操作中的绝对地址,从资源管理器复制的话,需要反斜杠前面再加一个,因为反斜杠本身是转义字符,下面的文件路径:

D:\Lua\5.1\SciTE\codes\txts\a1.txt

应该是:

t = io.open("D:\\Lua\\5.1\\SciTE\\codes\\txts\\a1.txt", "r+")

2072Lua 文件 I/O

感觉二楼说法有误: io.read() 不能放在 io.write() 后面,否则,虽然不会报错,但会打印出奇怪的字符,打开文件看,会发现多了一串乱码。

我的分析如下:

1. 这是因为执行 io.write 后,写入的数据只是在缓冲区中,并未真正写入到文件中,当执行 io.flush 后,缓冲区的数据才会真正写入文件中,或者执行 io.close 方法时,在关闭文件前,也会先将缓冲区数据写入文件。

2. 当执行 io.open 方法时,会有一个类似 C/C++ 的指针的文件位置指向,会将当前要读取或写入的数据写入到指向的位置,然后指向的位置进行偏移。例如:

  • ① 执行 io.open("t.lua", "r+") 时,当前文件位置指向的是文件头部,执行读取和写入都是从头部开始的,读取完一部分数据后,位置指向会向后偏移,偏移的长度就是读取的位置长度,同理写入数据也是一样;
  • ② 执行 io.open("t.lua", "a+") 时,当前文件位置指向的是文件尾部,执行读取操作时是从尾部开始的,这样读取的数据为nil,而写入也是从尾部开始的,因此写入的数据会以追加的形式写入到当前文件的末尾,然后指向位置也会向后偏移到尾部。

3.所以才会有一个 file:seek() 的方法,可以让你修改当前文件流操作的指向位置。希望大家能理解文件流操作的位置概念(其实可以理解为指针)

2071Lua 文件 I/O

1.若使用LuaStudio,其中io.open()的默认查找路径是LuaStudio软件的根目录下,若需要open其他路径的文件,使用绝对路径即可;

2.需要注意的是,简单模式下,io.read()不能放在io.write()后面,否则,虽然不会报错,但会打印出奇怪的字符,打开文件看,会发现多了一串乱码。

t=io.open("t.lua","a+")
io.input(t)
io.output(t)
io.write("test")  --test
print(io.read())  --?(或者其他符号)

3.若需要io.write后io.read,则需要先关闭文件,然后再打开文件查看

t=io.open("t.lua","a+")
io.output(t)
io.write("test")   --test
io.close(t)
t=io.open("t.lua","a+")
io.input(t)
print(io.read())    --test

4.简单模式下,当使用io.close()关闭文件的时候,之前设置默认输入文件和默认输出文件会失效,当你使用io.open()重新打开文件时,则需要重新设置

5.关于 *n ,还有一点需要注意,若数字中有非数字的字符的话,会返回该字符前的数字,如:

t=io.open("t.lua","a+")
io.input(t)
print(io.read("*n"))

t.lua文件内容是:

123456test789

输出:

123456

2070Lua 文件 I/O

使用 *n 作为参数读取文件中的数字的时候,只有文件中第一个字符是数字(或者空格加数字)的情况下才能读取到并返回这个数字:

file = io.open("test.txt","r")
io.input(file)
print(io.read("*n"))
io.close(file)

test.txt 文件内容:

 321
aaa

输出:

321

2069Lua 协同程序(coroutine)

正文中的例子分析:

第一次调用(第一次调用的时候,协同程序是一个挂起的状态),resume 的参数 1,10 传入主体函数,打印得出 1,10,之后调用 foo 打印得出 2,程序挂起,之后返回这个值到 resume,作为第二个参数值为 4。

第二次调用 resume 参数为 r ,从主函数中 print("第二次协同程序执行输出", r) 开始运行,因为此时的状态是挂起的状态,resume 的参数传入 yield,作为挂起点的返回值为 r。

所以打印得出 r ,之后继续运行,执行 local r, s = coroutine.yield(a + b, a - b),因为此时,并非 resume 直接调用的情况,所以 yield 函数 使用主函数传入的 a,b 参数 作为参数,得出结果为 11, -9,之后 再次挂起。

结果: r 11 -9

第三次调用 resume 参数为 x, y ,从程序挂起点运行,并参数传入 yield 中,yield 此时作为返回值点,所以得出 r,s 结果为 x , y,之后继续运行 return b, "结束协同程序" , 返回 b, 为 10。

结果: x,y true, 10

总结: resume 执行的情况如果(排除第一次执行情况)是挂起的状态,那么 resume 的参数传递给 yield,yield 不论参数表达式形式,返回的值 resume 传递的所有参数。

特别的,注意如果运行之后,再次挂起,那么此时传入的 yield 值,就是主函数的参数值,如果使用的话。

如果 resume 的执行是第一次(上面讲到排除第一次挂起的特殊情况)的情况或者是挂起之后再次运行,那么 resume 的参数 作为主函数的参数。