Kunok
Kunok

Reputation: 8759

After editing my file via Ruby methods, strange characters appeared

I have this small script which I wrote to rename variables in my JS file.

  puts "Current name?"
  current_name = gets.chomp
  puts "New name? (Recommended usage of $ prefix)"
  new_name = gets.chomp
  #
  File.open(file_name, 'r+') do |file|
    file_content = file.read
    edited_file = file_content.sub "var "+current_name+" = ", "var "+new_name+" = "
    edited_file = edited_file.gsub current_name+".", new_name+"." 
    file.truncate(0)
    file.write(edited_file)
  end

When I run it, it changes all variable names and that looks just fine in my Atom text editor. But if I open this same file in Sublime text editor all characters are bunch of numbers.

Look at the screenshot (Sublime editor in front and Atom in background)

enter image description here

After trying this: Write and read a file with utf-8 encoding

  File.open(file_name, 'r+:UTF-8') do |file|
    file_content = file.read
    edited_file = file_content.sub "var "+current_name+" = ", "var "+new_name+" = "
    edited_file = edited_file.gsub current_name+".", new_name+"."
    file.truncate(0)
    file.write edited_file
  end

The invalid characters still appear and valid output afterwards. Here is screenshot:

enter image description here

Upvotes: 1

Views: 240

Answers (1)

Jordan Running
Jordan Running

Reputation: 106077

I have a hunch—but can't test it since I'm not at a computer—that File#truncate doesn't reset the File object's internal "cursor." Since you did file.read the cursor is at the end of the file (say, 500 bytes from the beginning). truncate deletes everything in the file but the cursor is still at offset 500, so when you write to the file it starts writing at that position, and the preceding bytes are all set to 00 (NUL).

When you open the file in Atom, it chooses to not display those 00 bytes. (If you can configure Atom to display invisible characters, you should. A text editor should never hide non-printable characters.) Sublime, on the other hand, sees all the 00s and decides to display the file as a binary file in a hex view.

The fact that the first three non-zero bytes shown in Sublime are 76 61 72—the ASCII codes for var—would seem to support this theory.

I think the easiest solution would be to call file.rewind before file.truncate or file.write:

File.open(file_name, 'r+') do |file|
  file_content = file.read
  file_content.sub!("var #{current_name} = ", "var #{new_name} = ")
  file_content.gsub!("#{current_name}.", "#{new_name}.")

  file.rewind
  file.truncate(0)
  file.write(file_content)
end

A better solution, perhaps, would be to embrace the prior invention of the wheel and use sed or awk for this.

Upvotes: 6

Related Questions