萝卜L

导航

Lua io.open read write seek flush setvbuf append

  • 读写操作会设置同一个指针, 指针移动的距离为读写内容的长度。
p=f:seek()
f:read(num)--假设文件内容够长
assert(f:seek()==p+num)
f:write(str)
assert(f:seek()==p+num+string.len(str))
  • f:seek() (获取指针值)有f:flush() (将缓存写入文件)的功效。 
  • f:write() (文件写内容)后f:flush() (将缓存写入文件),再f:read() (文件读内容)。否则,f:write()-f:read() 可能读取到意外数据(额外分配的缓存或溢出)。
  • f:setvbuf() 会有未明确的影响,参考如下的 testcaseB==2 。
local f=io.tmpfile()
--    可能需要管理员权限
local fn
if not f then
    fn='.'..os.tmpname()
    f=assert(io.open(fn,'w+'))
end
local s=0x1000--buffer size(缓存大小)
local testcaseB=1
--    and 2
if testcaseB==2 then
    f:setvbuf('full',s)
    --    memory leak? 会导致内存泄露,f:read()将读取到意外的内容(require的其他脚本)
end
local c='abc'--content(内容),假设长度小于缓存大小
local l=string.len(c)--length(长度)
assert(l<=s)
f:write(c)
local testcase=1
--uncomment to test
--    and 2
--    and 3
local ec=string.rep('\0',s-l)--extra cache  content(额外的缓存内容)
if testcase==1 then
    local r=f:read'a'
    if testcaseB==1 then
        assert(r==ec)
        assert(f:seek()==s)
    else
        assert(f:seek()>=s)
    end
else
    if testcase==2 then
        assert(f:seek()==l)
    elseif testcase==3 then
        f:flush()
    end
    assert(f:read'a'=='')
    assert(f:seek()==l)
end
f:seek'set'
local r=f:read'a'
if testcase==1 then
    if testcaseB==1 then
        assert(r==c..ec)
    else
    end
else
    assert(r==c)
end
f:flush()
f:seek'set'
r=f:read'a'
if testcase==1 then
    if testcaseB==1 then
        assert(r==c..ec)
    else
    end
else
    assert(r==c)
end
f:close()
if fn then
    os.remove(fn)
end
View Code
  •  在 io.open(..,'a[+]') append(追加)模式中,即便(通过 f:seek() )手动设置指针位置(到非末尾,如 f:seek'set' ),即便文件内容被其他过程改变,追加操作仍会在末尾。
local fn='.'..os.tmpname()
local f=assert(io.open(fn,'a+'))
f:write'123';f:flush()
f:seek'set'
f:write'456';f:flush()
f:seek'set'
assert(f:read'a'=='123456')--not '456'
--
local f2=assert(io.open(fn,'r+'))
assert(f2:seek()==0)
f2:seek'end'
f2:write'abc';f2:flush()
f2:seek'set'
assert(f2:read'a'=='123456abc')
f:write'789';f:flush()
f2:seek'set'
assert(f2:read'a'=='123456abc789')--not '123456789'
f:close()
os.remove(fn)
View Code
  • 以上,即便文件被其他过程( io.open(filename,'w[+]') )截断(truncate)重置,追加操作仍会在末尾。
local fn='.'..os.tmpname()
local f=assert(io.open(fn,'a+'))
f:write'123456';f:flush()
f:seek'set'
assert(f:read'a'=='123456')--not '456'
--
local f2=assert(io.open(fn,'w+'))
f2:seek'end'
assert(f2:seek()==0)--file is truncated
f2:write'abc';f2:flush()
f2:seek'set'
assert(f2:read'a'=='abc')
f:write'789';f:flush()
f2:seek'set'
assert(f2:read'a'=='abc789')--not 'abc456789'
f2:close()
f:close()
os.remove(fn)
View Code

posted on 2020-12-26 11:40  萝卜L  阅读(383)  评论(0编辑  收藏  举报