为什么将字符串保存到文件时 \r\n 被转换为 \n?

Why is \r\n being converted to \n when a string is saved to a file?

字符串作为 return 值源自:

> msg = imap.uid_fetch(uid, ["RFC822"])[0].attr["RFC822"]

如果我在控制台中键入 msg,则会显示一个长字符串,每个字符串用双引号和 \r\n 分隔:

> msg
"Delivered-To: email@test.com\r\nReceived: by xx.xx.xx.xx with SMTP id;\r\n"

如果我用正则表达式匹配它的一部分,return 值有 \r\n:

> msg[/Delivered-To:.*?\s+Received:/i]
=> "Delivered-To: email@test.com\r\nReceived:"

如果我将字符串保存到文件中,将其读回并与相同的正则表达式匹配,我得到 \n 而不是 \r\n:

> File.write('test.txt', msg)
> str = File.read('test.txt')
> str[/Delivered-To:.*?\s+Received:/i]
=> "Delivered-To: email@test.com\nReceived:"

将字符串保存到文件时,是否将\r\n转换为\n? 有没有办法将字符串保存到文件中,在不修改行尾的情况下将其读回?

这在 the IO.new documentation 中有介绍:

The following modes must be used separately, and along with one or more of the modes seen above.

"b"  Binary file mode
     Suppresses EOL <-> CRLF conversion on Windows. And
     sets external encoding to ASCII-8BIT unless explicitly
     specified.

"t"  Text file mode

换句话说,Ruby 和许多其他语言一样,感知到 OS 它是打开的,并且会自动翻译“\r\n” <-> “\n 之间的行尾" 当 reading/writing 文件处于文本模式时。使用二进制模式避免翻译。


str = File.read('test.txt')

更好的做法是使用 foreach 读取文件,这样就无需关心行尾;您将分别获得每一行。另一种方法是使用 readlines,但它对大文件使用 slurping which can be very costly

此外,如果您要处理邮件文件,我强烈建议您使用已编写的工具来执行此操作,而不是自己编写。 Mail gem 就是这样一个预先构建并经过良好测试的软件包。