Write Binary File in Ruby

Write binary file in Ruby

You can use Array#pack and String#unpack to convert to and from binary representations. Combine them with IO#write and IO#read, and away you go.

Ruby: How to convert a string to binary and write it to file

Try using double quotes:

data = "BZh91AY&SY\x94$|\x0e\x00\x00\x00\x81\x00\x03"

Then do as sepp2k suggested.

Write binary file from text string that represents hex bytes in Ruby

You have to split the string by aligned bytes in the first place.

str.
each_char. # enumerator
each_slice(2). # bytes
map { |h, l| (h.to_i(16) * 16 + l.to_i(16)) }.
pack('C*')

#⇒ "\x00\x11\x04\x05\x94\x19c(\x01\x00\e#q\x000\x03\x81\x01\n"

or, even better:

str.
scan(/../).
map { |b| b.to_i(16) }.
pack('C*')

Now you might dump this to the file using e.g. IO#binwrite.

How to write a Tempfile as binary

Tempfile.new passes options to File.open which accepts the options from IO.new, in particular:

:binmode

If the value is truth value, same as “b” in argument mode.

So to open a tempfile in binary mode, you'd use:

temp_file = Tempfile.new([name, extension], binmode: true)

temp_file.binmode? #=> true
temp_file.external_encoding #=> #<Encoding:ASCII-8BIT>

In addition, you might want to use Tempfile.create which takes a block and automatically closes and removes the file afterwards:

Tempfile.create([name, extension], binmode: true) do |temp_file|
temp_file.write(unzipped_io.read)
# ...
end

Automatically open a file as binary with Ruby

Actually, the previous answer by Alex D is incomplete. While it's true that there is no "text" mode in Unix file systems, Ruby does make a difference between opening files in binary and non-binary mode:

s = File.open('/tmp/test.jpg', 'r') { |io| io.read }
s.encoding
=> #<Encoding:UTF-8>

is different from (note the "rb")

s = File.open('/tmp/test.jpg', 'rb') { |io| io.read }
s.encoding
=> #<Encoding:ASCII-8BIT>

The latter, as the docs say, set the external encoding to ASCII-8BIT which tells Ruby to not attempt to interpret the result at UTF-8. You can achieve the same thing by setting the encoding explicitly with s.force_encoding('ASCII-8BIT'). This is key if you want to read binary into a string and move them around (e.g. saving them to a database, etc.).

Rails/Ruby: uploading a binary File and writing it with a File-Object

Binary file mode "b" may appear with any of the key letters (r, r+, w, w+, a, a+) so you can do it like this f = File.new("public/files/#{user.id.to_s}/filename", "w+b").

And the "b" mode is not only for windows. Ruby documentation says that "Binary file mode (may appear with any of the key letters r, r+, w, w+, a, a+. Suppresses EOL <-> CRLF conversion on Windows. And sets external encoding to ASCII-8BIT unless explicitly specified." and says nothing about "b" being just for windows. It just tells that it works different on windows/linux with line endings. So you can use "w+b" mode on linux and windows.

Ruby: Is there a way to specify your encoding in File.write?

AFIK you can't do it at the time of performing the write, but you can do it at the time of creating the File object; here an example of UTF8 encoding:

File.open(FILE_LOCATION, "w:UTF-8") do 
|f|
f.write(....)
end

Another possibility would be to use the external_encoding option:

File.open(FILE_LOCATION, "w", external_encoding: Encoding::UTF_8)

Of course this assumes that the data which is written, is a String. If you have (packed) binary data, you would use "wb" for openeing the file, and syswrite instead of write to write the data to the file.

UPDATE As engineersmnky points out in a comment, the arguments for the encoding can also be passed as parameter to the write method itself, for instance

IO::write(FILE_LOCATION, data_to_write, external_encoding: Encoding::UTF_8)

Ruby Write Hex String To Binary File By Keeping Hex Values

You can turn it into a single element array and pack it as hex. For instance, when I run your code:

require 'securerandom'

length = 2 ** 6
random_hex_string = SecureRandom.hex (length)
random_hex_string.insert(0,"0102")
random_hex_string.insert(30*1,"36")

puts random_hex_string
File.open("file.txt", 'w+b') do |file|
file.write([random_hex_string].pack('H*')) # see also 'h'
end

I get the output

010299e84e9e4541d08cb800462b6f36a87ff118d6291368e96e8907598a2dfd4090658fea1dab6ed460ab512ddc54522329f6b4ddd287e4302ef603ce60e85e631591

and then running

$ hexdump  file.txt 
0000000 01 02 99 e8 4e 9e 45 41 d0 8c b8 00 46 2b 6f 36
0000010 a8 7f f1 18 d6 29 13 68 e9 6e 89 07 59 8a 2d fd
0000020 40 90 65 8f ea 1d ab 6e d4 60 ab 51 2d dc 54 52
0000030 23 29 f6 b4 dd d2 87 e4 30 2e f6 03 ce 60 e8 5e
0000040 63 15 91
0000043

Unless, I'm mistaken, it matches up perfectly with the output from the script.


I've never messed with Array#pack before, and haven't done much with hex, but this seems to be giving the results you require, so should be a step in the right direction at least.



Related Topics



Leave a reply



Submit