我有一个通过 FTP 从大型机获取平面文件的进程。这通常工作正常,但有时文件会包含一些重音字符。如果我尝试获取包含口音的文件,整个过程会失败并出现以下错误:Encoding::UndefinedConversionError: "\x88"from ASCII-8BIT to UTF-8
那是使用 Net::FTP
的 gettextfile
方法。许多人建议简单地切换到 getbinaryfile
- 这样做将允许我下载文件,但生成的文件是我无法再解析的东西(说它是 UTF-8,但内容使没有意义)。
有没有什么方法可以简单地获取文件并将其保存为 ASCII,而无需让 Rails 自动将输出转换为 UTF-8?这是我的代码:
Net::FTP.open(config['host']) do |ftp|
Rails.logger.info("FTP Connection established")
ftp.login(config['user'], config['password'])
Rails.logger.info("Login Successful")
ftp.gettextfile("'#{config['es_in']}'", "data/es-in.#{Time.now.utc.strftime("%Y%m%d-%H%M%S")}")
ftp.gettextfile("'#{config['ca_in']}'", "data/ca-in.#{Time.now.utc.strftime("%Y%m%d-%H%M%S")}")
Rails.logger.info("Download(s) completed, terminating connection.")
end
最佳答案
如果我没记错的话,FTP-dom 中的文本文件是 ASCII-7 位的,不能包含设置了高位的字符,即 ASCII-8 位。重音字符,即使是扩展的 ASCII 或 8BIT 或任何我们想称之为 0x7F 以上的任何东西,都需要以二进制模式传输。
来自 the FTP RFC :
ASCII
The ASCII character set is as defined in the ARPA-Internet
Protocol Handbook. In FTP, ASCII characters are defined to be
the lower half of an eight-bit code set (i.e., the most
significant bit is zero).
所以是的,你应该使用 getbinaryfile
相反。
两者之间的主要实际区别是二进制模式不会进行行尾翻译。如果源系统是基于 ECDIC 或替代字大小,gettextfile
会将文件即时转换为 ASCII。遇到不符合预期编码的字符很容易触发您遇到的这类问题。
如果文件在使用 getbinaryfile
传输后没有意义,则它可能位于大型机上 UTF8 以外的备用代码集中。您必须找出它在该系统上的代码集,并在下载后使用适当的编码设置打开文件。您可以在 *nix 系统上使用 file
命令对文件的编码进行有根据的猜测,但这不是详尽的测试并且可能会产生误导。因为文件来自大型机,所以它可能使用不同的字长,如 UTF-16BE、UTF-32LE 或以 EBCDIC 编码。这是处理备用操作系统和硬件变得非常烦人的地方。
没有文本示例、文件的前两个字节以及十六进制转储中的文本样本,很难为您提供帮助。
毕竟,使用 cURL 可能更容易,或 Curb gem 来检索文件。 cURL 非常灵活且功能强大,可能会为您提供所需的工具。
关于ruby-on-rails - 使用带有无效字符的 Net::FTP gettextfile(ASCII-8BIT 与 UTF-8),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23661921/