Lua 5.3.4全缓冲模式下文件写入差异原因咨询
为什么两段Lua代码的写入结果不同?
这背后的核心原因是Lua全缓冲模式下的缓冲区处理逻辑,以及两次写入和单次写入的行为差异:
1. 全缓冲的基本规则
全缓冲(full buffering)意味着只有在以下三种情况时,缓冲区的内容才会被写入磁盘:
- 缓冲区被填满
- 显式调用
flush()方法 - 文件句柄被关闭(包括程序正常结束时自动关闭)
2. Lua对setvbuf("full", size)的处理细节
在Lua 5.3.4中,当使用全缓冲模式并指定缓冲区大小后,存在一个关键的优化逻辑:
- 如果单次写入的数据长度大于或等于缓冲区大小,Lua会直接绕过用户空间缓冲区,将数据直接写入底层文件系统,不需要等待缓冲区填满或显式刷新。
- 如果单次写入的数据长度小于缓冲区大小,数据会被暂存到用户空间缓冲区中,只有当缓冲区被填满、显式刷新或文件关闭时,才会写入磁盘。
3. 两段代码的行为差异分析
片段1:分两次写入89+1个"A"
out = io.open("E:\\file","w") out:setvbuf("full",90) out:write(string.rep("A",89)) -- 89 < 90,数据存入缓冲区 out:write("A") -- 1 < 90,数据存入缓冲区,此时缓冲区刚好填满90个字符
这里两次写入的数据都小于缓冲区大小,最终数据都暂存在用户空间缓冲区中。如果程序此时直接结束(没有显式调用out:close()或out:flush()),Lua的垃圾回收机制可能在程序退出前没有及时触发文件句柄的关闭逻辑,导致缓冲区内容未被写入磁盘。
片段2:单次写入90个"A"
out = io.open("E:\\file","w") out:setvbuf("full",90) out:write(string.rep("A",90)) -- 90 == 缓冲区大小,直接写入磁盘
由于单次写入的数据长度等于缓冲区大小,Lua直接跳过缓冲区,将数据写入底层文件系统,因此无论程序是否立即结束,内容都会出现在文件中。
验证与解决方法
如果在片段1的末尾添加out:close()或out:flush(),你会发现文件也会成功写入内容:
out = io.open("E:\\file","w") out:setvbuf("full",90) out:write(string.rep("A",89)) out:write("A") out:close() -- 显式关闭文件,触发缓冲区刷新
内容的提问来源于stack exchange,提问作者eye science international
相关产品推荐
相关产品推荐

