读写二进制文件

8

我只是想从一个二进制文件中读取/写入数据。我一直在按照这个教程进行操作,它也能正常工作……但似乎将数据写入了一个txt文件中。我在测试时给文件命名为test.bin,但记事本可以打开并正确显示它,所以我认为它实际上不是一个二进制文件。我已经使用了"wb"和"rb"来告诉它这是一个二进制文件,对吗?

if arg[1] == "write" then
    local output = assert(io.open(arg[2], "wb"))

    output:write(arg[3]) --3rd argument is written to the file.

    assert(output:close())
elseif arg[1] == "read" then
    local input = assert(io.open(arg[2], "rb"))

    print(input:read(1)) --Should read one byte, not one char/int. Right?
end

3
文本文件是一种二进制文件类型。 - greatwolf
1
可能会在未使用“b”选项打开的文本文件中遇到“'\x1A'”字符而停止读写。为了避免这种情况,引入了“b”选项。 - Egor Skriptunoff
这个帖子的第二篇回复为我澄清了一些事情。在我的C++课程中,我们被教导二进制文件是完全独立的东西,意味着它们无法被人类阅读,所以当我用记事本正确地读取它时,我感到相当困惑。话虽如此,如果你打开大多数游戏的二进制保存文件,它会显示为完全无法识别的垃圾,所以我不禁感觉自己缺少了什么。 - Lemony Lime
2个回答

15

如果您只向文件写入ASCII字符,则可以在记事本或其他任何文本编辑器中轻松打开它:

local out = io.open("file.bin", "wb")
local str = string.char(72,101,108,108,111,10) -- "Hello\n"
out:write(str)
out:close()

生成的文件将包含以下内容:
Hello

另一方面,如果您编写真正的二进制数据(例如随机字节),则会得到垃圾:

local out = io.open("file.bin", "wb")
local t = {}
for i=1,1000 do t[i] = math.random(0,255) end
local str = string.char(unpack(t))
out:write(str)
out:close()

这类似于你可能见过的视频游戏存档文件。

如果你仍然不明白,试着把所有可能的八位字节写入文件:

local out = io.open("file.bin", "wb")
local t = {}
for i=0,255 do t[i+1] = i end
local str = string.char(unpack(t))
out:write(str)
out:close()

然后使用十六进制编辑器(我在Mac OS上使用了Hex Fiend)打开它,以查看对应关系:

hex

在这里,左边是十六进制字节,右边是它们的文本表示。我选择了大写的 H,如你在左边所见,对应着 0x48。 0x48 在十进制中为 4*16 + 8 = 72(查看屏幕截图底部的条形图可以知道)。

现在看看我的第一个代码示例,并猜测小写 e 的代码是什么...

最后看一下屏幕截图的最后4行(字节128至255)。 这就是你看到的垃圾。


-1

我不明白如何编写二进制文件。

我的关卡是在旧电脑上创建的,我的新游戏可以读取每个关卡129个2200字节。

我仍然不明白如何将xdata(关卡数据)表写入文件。

     function xdatatoline (levelnumber,xdata)
        local out = io.open("file.bin", "wb")
        local t = xdata
        --for i=1,1000 do t[i] = math.random(0,255) end
        local str = string.char(unpack(t))
        out:write(str)
        out:close()
     end 

BAD ARGUMENT #1 to CHAR 期望是数字,但得到了字符串)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接