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 argumentmode
.
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
How to Generate a Human Readable Time Range Using Ruby on Rails
Why Did Matz Choose to Make Strings Mutable by Default in Ruby
Openssl::Ssl::Sslerror: Ssl_Connect Returned=1 Errno=0 State=Unknown State: Unknown Protocol
Split String into a List, But Keeping the Split Pattern
Always Getting 401 Unauthorized with New Install of Rails + Devise
Why Do People Say That Ruby Is Slow
How (Replace|Create) an Enum Field on Rails 2.0 Migrations
How to Add Information to an Exception Message in Ruby
Differencebetween 'After_Create' and 'After_Save' and When to Use Which
How to Add Migration with Multiple References to the Same Model in One Table? Ruby/Rails
Prevent Rails Test from Deleting Seed Data
How to Dynamically Alter Inheritance in Ruby
Nokogiri Was Built Against Libxml Version 2.7.7, But Has Dynamically Loaded 2.7.3