Hi,
I am having issues with my binary file parsing and the file pointer seems to be one byte away from the expected position.
In parse_block( {block_size, "YYY"} , assets_file_pointer)
, I have one line before I return data IO.binread(1)
which I believe should just advance the file pointer 1 byte. It should be reading from a point in the file that then executes parse_block( {block_size, "PPP"} , _assets_file_pointer)
, but I am 1 byte away from getting “PPP”… Even if I make the discard line IO.binread(2), I don’t get any closer.
parse_block( {block_size, "YYY"} , assets_file_pointer)
works successfully, however I notice that for me to get the error to display in iex
, I need to hit the enter key. It is like it suspends data output to the console. If I comment out the IO.binread(1)
, then this doesn’t happen. I suspect it is because I am reading 1 zero byte, but don’t quite understand why that messes things up. Either way, I would have still thought it would advance the file pointer by 1 byte…
Here is my complete code:
defmodule Parser do
def parse do
index_data = %{}
assets_file_pointer = File.open!("data.file")
block_meta_data = parse_block(assets_file_pointer)
block_contents = parse_block(block_meta_data, assets_file_pointer)
index_data = Map.merge(index_data, block_contents)
block_meta_data = parse_block(assets_file_pointer)
block_contents = parse_block(block_meta_data, assets_file_pointer)
index_data = Map.merge(index_data, block_contents)
end
def parse_block(assets_file_pointer) do
block_size = assets_file_pointer
|> IO.binread(4)
|> Helpers.reverse_binary()
|> :binary.decode_unsigned()
block_type = assets_file_pointer
|> IO.binread(2)
{block_size, block_type}
end
def parse_block( {block_size, "YYY"} , assets_file_pointer) do
number_of_rooms = (block_size - 7) / 10
|> trunc
room_data = Enum.reduce(1..number_of_rooms, %{}, fn(_, acc) ->
room_number = assets_file_pointer
|> IO.binread(1)
|> :binary.decode_unsigned
room_name = assets_file_pointer
|> IO.binread(9)
|> Helpers.xor(0xFF)
Map.put(acc, room_name, room_number)
Map.put(acc, room_number, room_name)
end)
# discard end of block zero byte (not working as expected)
IO.binread(1)
%{"rooms" => room_data}
end
def parse_block( {block_size, "PPP"} , _assets_file_pointer) do
number_of_entries = (block_size - 8) / 5
|> trunc
room_directory_data = Enum.reduce(1..number_of_entries, %{}, fn(_, acc) ->
Map.put(acc, "dummy", "data")
end)
%{"room_directory" => room_directory_data}
end
end
Parser.parse()