class File # Opens a file as a string and writes back the string to the file at # the end of the block. # # Returns the number of written bytes or +nil+ if the file wasn't # modified. # # Note that the file will even be written back in case the block # raises an exception. # # Mode can either be "b" or "+" and specifies to open the file in # binary mode (no mapping of the plattform's newlines to "\n" is # done) or to append to it. # # # Reverse contents of "message" # File.rewrite("message") { |str| str.reverse } # # # Replace "foo" by "bar" in "binary" # File.rewrite("binary", "b") { |str| str.gsub("foo", "bar") } # # IMPORTANT: The old version of this method required in place modification # of the file string. The new version will write whatever the block # returns instead!!! # # CREDIT: George Moschovitis # def self.rewrite(name, mode = "") #:yield: unless block_given? raise(ArgumentError, "Need to supply block to File.rewrite") end if mode.is_a?(Numeric) then flag, mode = mode, "" mode += "b" if flag & File::Constants::BINARY != 0 mode += "+" if flag & File::Constants::APPEND != 0 else mode.delete!("^b+") end old_str = open(name, "r#{mode}") { |file| file.read } #rescue "" old_str = old_str.clone begin new_str = yield(old_str) ensure if old_str != new_str open(name, "w#{mode}") { |file| file.write(new_str) } end end end # In place version of #rewrite. This version of method requires that the # string be modified in place within the block. # # # Reverse contents of "message" # File.rewrite("message") { |str| str.reverse! } # # # Replace "foo" by "bar" in "binary" # File.rewrite("binary", "b") { |str| str.gsub!("foo", "bar") } # def self.rewrite!(name, mode = "") #:yield: unless block_given? raise(ArgumentError, "Need to supply block to File.rewrite") end if mode.is_a?(Numeric) then flag, mode = mode, "" mode += "b" if flag & File::Constants::BINARY != 0 mode += "+" if flag & File::Constants::APPEND != 0 else mode.delete!("^b+") end old_str = open(name, "r#{mode}") { |file| file.read } #rescue "" new_str = old_str.clone begin yield(new_str) ensure if old_str != new_str open(name, "w#{mode}") { |file| file.write(str) } end end end end