Automatically Open a File as Binary with Ruby

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

Opening file in binary mode and saving it adds new line

I ran some tests; it depends on the way your lines end. When they end with either LF (\n) or CR (\r) it will produce output like you expect. That is, no new lines are added. However, if you have CRLF (\r\n) it will add a CR character after each line, thus ending it effectively with CRCR+LF which produces the extra line.

Most programming editors allow you to select an option which makes the line endings visible.

I am not exactly sure why this happens, but likely has to do with the following snippet from the IO docs at the 'b' mode:

Suppresses EOL <-> CRLF conversion on Windows.

It appears that when not using binary mode, CRLF (default end-of-lines on Windows) are converted to LF's. The simple solution thus seems to just replace all \r\n by either \n or \r. You can do that like this:

File.open('converted.txt', 'wb') do |converted|
File.open('1.txt', 'rb').each_line do |line|
converted << line.gsub("\r\n", "\n") # Replace CRLF with LF
end
end

If you run the script multiple times on the same file, you should make sure to replace CRLF with LF before you write it back:

# Note the .gsub at the end here
text = File.read('1.txt', mode: 'rb', encoding: 'UTF-8').gsub("\r\n", "\n")
File.write('1.txt', text, encoding: 'UTF-8')

Read binary file as string in Ruby

First, you should open the file as a binary file. Then you can read the entire file in, in one command.

file = File.open("path-to-file.tar.gz", "rb")
contents = file.read

That will get you the entire file in a string.

After that, you probably want to file.close. If you don’t do that, file won’t be closed until it is garbage-collected, so it would be a slight waste of system resources while it is open.

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

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.

Java - reading file as binary with readLine

You can use java.io.DataInputStream which provides both a readLine() method and readFully(byte[]) and read(byte[]) methods.

Warning: The JavaDoc for readLine says, it is deprecated and that the encoding might be inappropriate (read details in JavaDoc).

So think twice about your real requirements and if this is a suitable trade-off in your case.

How do I download a binary file over HTTP?

The simplest way is the platform-specific solution:

 #!/usr/bin/env ruby
`wget http://somedomain.net/flv/sample/sample.flv`

Probably you are searching for:

require 'net/http'
# Must be somedomain.net instead of somedomain.net/, otherwise, it will throw exception.
Net::HTTP.start("somedomain.net") do |http|
resp = http.get("/flv/sample/sample.flv")
open("sample.flv", "wb") do |file|
file.write(resp.body)
end
end
puts "Done."

Edit: Changed. Thank You.

Edit2: The solution which saves part of a file while downloading:

# instead of http.get
f = open('sample.flv')
begin
http.request_get('/sample.flv') do |resp|
resp.read_body do |segment|
f.write(segment)
end
end
ensure
f.close()
end


Related Topics



Leave a reply



Submit