user995928
user995928

Reputation:

Automatically open a file as binary with Ruby

I'm using Ruby 1.9 to open several files and copy them into an archive. Now there are some binary files, but some are not. Since Ruby 1.9 does not open binary files automatically as binaries, is there a way to open them automatically anyway? (So ".class" would be binary, ".txt" not)

Upvotes: 20

Views: 23926

Answers (3)

KARASZI István
KARASZI István

Reputation: 31467

Since Ruby 1.9.1 there is a separate method for binary reading (IO.binread) and since 1.9.3 there is one for writing (IO.binwrite) as well:

For reading:

content = IO.binread(file)

For writing:

IO.binwrite(file, content)

Since IO is the parent class of File, you could also do the following which is probably more expressive:

content = File.binread(file)
File.binwrite(file, content)

Upvotes: 19

Wolfram Arnold
Wolfram Arnold

Reputation: 7273

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

Upvotes: 39

Alex D
Alex D

Reputation: 30445

On Unix-like platforms, there is no difference between opening files in "binary" and "text" modes. On Windows, "text" mode converts line breaks to DOS style, and "binary" mode does not.

Unless you need linebreak conversion on Windows platforms, just open all the files in "binary" mode. There is no harm in reading a text file in "binary" mode.

If you really want to distinguish, you will have to match File.extname(filename) against a list of known extensions like ".txt" and ".class".

Upvotes: 1

Related Questions