timr wrote:
On Apr 29, 9:27�pm, Adam B. [email protected] wrote:
Truncates file to at most integer bytes. The file must be opened for
writing. Not available on all platforms.
f = File.new(“out”, “w”)
f.syswrite(“1234567890”) #=> 10
f.truncate(5) #=> 0
f.close() #=> nil
File.size(“out”) #=> 5
That’s pretty close to how I’ve been modifying files:
File.open(filename, ‘r+’) do |file|
lines = file.readlines
# modify data in the lines array
file.pos = 0
file.print lines # will not put \$ between array elements
file.truncate(file.pos)
end
This opens a file for reading and writing, reads the file into an array,
then you modify the array how you need to. Then the block returns to
the beginning of the file, writes out your changes over the existing
file, then chops off what’s left. Then, of course, the file is closed
when the block exits.
To get a little more complicated, I wrapped this in a class method:
class File
def self.change!(filename, create = false)
### method to make it easy to open a file and make changes to it.
### usage example
## File.change(myfile) do |contents|
## contents.gsub!(/this/, “that”)
## end
### I can also use “throw(:nochanges)” anywhere in the block
### to prevent the file from being written.
### Make sure ‘contents’ does not get pointed to a new object;
### for example, an assignemt “contents = ‘new data’” will break the
method
# if create is true, create the file if it does not exist
if create == true
File.open(filename, 'w') { |blank| blank.write '' } unless
File.exist?(filename)
end
# read the file, execute a block, then write the file
if File.exist?(filename)
File.open(filename, 'r+') do |file|
lines = file.readlines
# do not write the file if it did not change (block must "throw
:nochanges")
catch(:nochanges) do
yield lines
file.pos = 0
file.print lines # will not put $ between array elements
file.truncate(file.pos)
end
end
end
end
end