SketchUp / sketchup-stl

A SketchUp Ruby Extension that adds STL (STereoLithography) file format import and export.
http://extensions.sketchup.com/content/sketchup-stl
MIT License
247 stars 68 forks source link

Catch file reading errors and provide a useful error message #98

Open thomthom opened 11 years ago

thomthom commented 11 years ago

We should not assume file operations succeed. See confusion in this thread related to user trying to load file from a path with non-ASCII characters.

I also think we should detect Unicode characters and provide an error message especially for this scenario as well.

http://sketchucation.com/forums/viewtopic.php?f=323&t=54409&view=unread#p493547

jimfoltz commented 11 years ago

Not sure if this is helpful yet or not...

If I know the 20th file name in my tmp folder contains UTF, then I can read the file using Dir[..] rather than File.open(file_name)

(This is reading the face count from a binary .stl.)

begin

  # file_name = 'C:\Users\Jim\tmp\François.stl'

  Dir.chdir('C:/Users/Jim/tmp')
  puts "The file name: #{Dir["*"][20].inspect}"
  file = File.open(Dir['*'][20], 'rb')
  puts file
  file.seek(80, IO::SEEK_SET)
  face_count = file.read(4).unpack('i')[0]
  puts "face_count: #{face_count}"
ensure
  file.close
  puts 'file closed.'
  puts Sketchup.version
end
|| The file name: "François.STL"
|| #<File:0xca39768>
|| face_count: 804
|| file closed.
|| 13.0.4812
thomthom commented 11 years ago

Really? That worked with Ruby 1.8? What if a parent folder has non-ascii characters?

jimfoltz commented 11 years ago

Really? That worked with Ruby 1.8?

Yes, but only when providing the unicode path string directly. It does not work when using UI.openpanel because UI.openpanel does not return unicode characters properly.

For example, this works in SketchUp 13 (Ruby 1.8.6):

puts "SketchUp Version: #{Sketchup.version}"
puts "RUBY_VERSION: #{RUBY_VERSION}"
file_name = 'C:/Users/Jim/tmp/François/François.stl'
str = File.read(file_name)
puts str[0..80].inspect
puts "Done"

prints

|| SketchUp Version: 13.0.4812
|| RUBY_VERSION: 1.8.6
|| "solid Untitled-5263eb12\nfacet normal -0.19014709506073 0.19014709506073 0.9631656"
|| Done

This is the string returned by UI.openpanel for the same file: "C:\\Users\\Jim\\tmp\\François\\François.stl"

So the problem is that Ruby 1.8.6 does not use the Windows Unicode version of file i/o functions. SketchUp Unicode Discussion

Perhaps a WebDialog file selector could return a unicode filename, but that doesn't integrate in the Sketchup::Importer api.

thomthom commented 11 years ago

UI.openpanel should be returning it as UTF-8. Are you not seeing that?

How are you entering `file_name = 'C:/Users/Jim/tmp/François/François.stl'1 into SketchUp, via a file? Is that saved as UTF-8? Or is it saved in ANSI?

jimfoltz commented 11 years ago

Copy-paste into my editor from Chrome. I think I understand what you mean. So I am using Noel's tunnel from my editor, which uses load.

thomthom commented 11 years ago

"C:\\Users\\Jim\\tmp\\François\\François.stl" is that displayed in the WebDialog Console? SketchUp's native Ruby Console doesn't do that - and the return string is a valid UTF-8 string.

jimfoltz commented 11 years ago

I don't know. I appear to be able to read the file when I get to it through the Dir class.

Here is a shot of the SketchUp 13 Ruby Console: 2013-10-23_165449

Note - In the 2nd part where I tried File.read directly and got an Error, I just copied the file path from the Ruby Console (line 4), and pasted it after File.read

And the code:

dir = Dir['C:/Users/Jim/tmp/*'][21]
C:/Users/Jim/tmp/François
file = Dir[dir + '/*'][0]
C:/Users/Jim/tmp/François/François.stl
File.read file
Hi!

File.read 'C:/Users/Jim/tmp/François/François.stl'
Error: #<Errno::ENOENT: (eval):51:in `read': No such file or directory - C:/Users/Jim/tmp/François/François.stl>
(eval):51
(eval):51
jimfoltz commented 11 years ago

I thought I might be able to trick SketchUp 2013 into reading those Unicode file names, but I don't think it's going to work. Not putting any more time in it.