8

I'm just trying to read/write from a binary file. I've been following this tutorial, and it works... except it seems to be writing things to a txt file. I named the file test.bin when testing it, but notepad can open it and display it properly, so I don't think it's actually a binary file. I've told it that it's a binary file with "wb" and "rb" right?

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
greatwolf
  • 20,287
  • 13
  • 71
  • 105
Lemony Lime
  • 1,113
  • 3
  • 11
  • 12
  • 3
    A text file *is* a type of binary file. – greatwolf Jul 04 '13 at 06:13
  • 1
    Probably, reading/writing text file opened without `b` option can stop at `'\x1A'` char. To avoid this, option `b` was introduced. – Egor Skriptunoff Jul 04 '13 at 06:26
  • http://www.cplusplus.com/forum/general/33808/ The second post in this clarified things for me. In my C++ class, we were taught that binary files were completely separate things, meant to be unreadable to humans, so I was rather confused when I could read it properly with notepad. That said, if you open the binary save files of most games, it'll show up as complete unrecognizable garbage, so I can't help but feel like there's something I'm missing. – Lemony Lime Jul 04 '13 at 07:47

2 Answers2

15

If you only write ASCII characters to a file, it will be possible to open it in Notepad or any other text editor just fine:

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

The resulting file will contain:

Hello

On the other hand if you write real binary data (for instance random bytes) you will get garbage:

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()

This is similar to those video game save files you have seen.

If you still don't get it, try to write all possible octets to a file:

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()

and then open it with a hexadecimal editor (here I used Hex Fiend on Mac OS) to see the correspondences:

hex

Here, on the left, you have the bytes in hexadecimal and on the right you have their text representation. I have selected uppercase H which, as you can see on the left, corresponds to 0x48. 0x48 is 4*16 + 8 = 72 in base 10 (look at the bottom bar of the screenshot which tells you that).

Now look at my first code example and guess what the code for lowercase e is...

And finally look at the 4 last rows of the screenshot (bytes 128 to 255). This is the garbage you were seeing.

catwell
  • 6,770
  • 1
  • 23
  • 21
-1

I dont understand how to write binary files

My levels created on old computer and my new game can reads it 2200 bytes every level of 129

I still don't understand how i can xdata (level data) table can write to file.

     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 number expected , got string)