File input/output: Difference between revisions

→‎{{header|Ruby}}: Task changed at 14 February 2012. Create a variable, instead of just passing the value. Remove many extra details and explanations. To copy a file block by block, just use FileUtils.
(→‎{{header|Ruby}}: Task changed at 14 February 2012. Create a variable, instead of just passing the value. Remove many extra details and explanations. To copy a file block by block, just use FileUtils.)
Line 1,800:
 
=={{header|Ruby}}==
In general, open both files in binary mode.
This task is easy, with 'fileutils' from the standard library.
 
<lang ruby>requirestr = File.open('fileutilsinput.txt', 'rb') {|f| f.read}
FileUtilsFile.copy_file open('inputoutput.txt', 'output.txtwb') {|f| f.write str}</lang>
 
If 'input.txt' is a text file, we may forget binary mode. If no pathname begins with a pipe '|', then we may use ''IO::read'' and ''Kernel#open''. (The pipe is a problem, because <code>IO.read('| uname')</code> or <code>open('| sh', 'w')</code> would open a subprocess and not a file.)
It also works with open IO handles.
 
<lang ruby>File.open(# Only if 'input.txt', 'rb')is a dotext |i|file!
# Only if pipe '|' is not first character of path!
File.open('output.txt', 'wb') do |o|
str = IO.read('input.txt')
FileUtils.copy_stream(i, o)
File.open('output.txt', 'wbw') do {|of| f.write str}</lang>
end
end</lang>
 
ThisTo taskcopy isa easyfile block by block, withuse 'fileutils'FileUtils from the standard library.
----
We can also do IO with only the core library.
 
<lang ruby>File.open('input.txt',require 'rbfileutils') do |i|
FileUtils.copy_file 'input.txt', 'output.txt'</lang>
File.open('output.txt', 'wb') do |o|
buf = ""
bufsiz = (i.stat.blksize or 16384)
while i.read(bufsiz, buf) do o.write(buf) end
end
end</lang>
 
* The best buffer size is <code>i.stat.blksize</code>. Some platforms return <code>nil</code> there, so we guess 16384 bytes.
 
The shortest way to copy a file, without coding any loops and without requiring any libraries, is to read the entire file into memory.
 
<lang ruby>irb(main):001:0> open('output.txt', 'w') {|f| f << IO.read('input.txt')}
=> #<File:output.txt (closed)></lang>
 
But this has disadvantages:
 
* There was no 'b' flag, so it might not work with binary files on some platforms. With a 'b' flag, the code would be <code>open('output.txt', 'wb') {|f| f << IO.read('input.txt', mode: 'rb')}</code>, but this requires Ruby 1.9. (There is no way to pass 'b' flag to IO.read with Ruby 1.8.)
* If the file is too large, we fail to allocate enough memory.
 
----
Ruby 1.9 has a new core method, <code>IO.copy_stream</code>. With [[MRI]] 1.9, <code>IO.copy_stream</code> might use [[Linux]]'s [http://www.kernel.org/doc/man-pages/online/pages/man2/sendfile.2.html sendfile(2)] system call, or it might loop with a buffer of 16384 bytes.
 
{{works with|Ruby|1.9}}
 
<lang ruby>IO.copy_stream('input.txt', 'output.txt')
 
# It also works with open IO handles.
File.open('input.txt', 'rb') do |i|
File.open('output.txt', 'wb') do |o|
IO.copy_stream(i, o)
end
end</lang>
 
FileUtils knows about IO.copy_stream; so if you use FileUtils, then your program uses IO.copy_stream with Ruby 1.9, but still works with older Ruby versions.
 
=={{header|Run BASIC}}==
Anonymous user