Re: [Madeleine-devel] Binary Mode
Status: Beta
Brought to you by:
ndrs
From: Martin T. <ma...@ta...> - 2004-03-29 17:04:14
|
Hi Anders, > I take it from this that binary-mode is something that only affects > reading? Binary-mode also affects writing. So I was wondering why it worked without it and tried to reproduce the error and couldn't! Marshal seems to works no matter which combination binary/text mode was set for reading or writing. So why didn't it work in Madeleine? - Marshal.dump and Marshal.load both change the IO Stream to binary mode; Ruby source marshal.c: if (rb_respond_to(port, s_binmode)) { rb_funcall2(port, s_binmode, 0, 0); } -> So it should work not matter in which mode the stream is opened. - In Madeline there is a "while !file.eof? read" loop. It seems that the bug occurs only on the following conditions: - file opened in text mode - file.eof? called before Marshal.load - serialized data contains line-end - only on Windows? This bug is definitely NOT in Madeleine but in Ruby (or more likely the Windows implementation), but opening in binary mode is a workaround for it. (also changing to binmode when writing could do no harm). See below for a test script which can reproduce the error: (sorry for the code, I'm a Ruby newbie) Martin. Result: -------- write wb, read rb OK write w, read rb OK write w, read r marshal data too short Error! write wb, read r marshal data too short Error! ------------------ NAME = "test.dat" TEST = "\r\n \n \r \r\r\r \n\n\n \n\r" def test(mode_write, mode_read) puts "write #{mode_write}, read #{mode_read}" save(mode_write) result = load(mode_read) puts (result == TEST ? "OK" : "Error!") puts end def load(mode) File.open(NAME, mode) { |file| begin file.eof? # if the last line is removed: no error return Marshal.load(file) rescue puts $! end } end def save(mode) File.delete(NAME) if File.exists?(NAME) File.open(NAME, mode) { |file| Marshal.dump(TEST, file) } end test("wb", "rb") test("w", "rb") test("w", "r") test("wb", "r") -------------- |