Ruby读取文件时无法移除非法UTF-8字节序列问题求助
问题分析与解决
核心问题原因
同编码下不触发转码:在Ruby 1.9.x(包括你使用的JRuby 1.7.21)中,当
external_encoding和internal_encoding设置为同一编码时,Ruby不会执行任何编码转换操作,你传入的invalid: :replace等转码参数完全不会生效。这就是为什么读取后的字符串里还保留着非法字节FC。converters选项无效:IO.read并不支持converters参数,这个选项是给IO::readlines或CSV类的解析方法用的,所以你之前定义的UTF8_CONVERTER根本没被调用。
解决方案
方法一:二进制读取后手动转码(推荐)
直接以二进制模式读取原始字节,再手动调用encode处理非法序列,这种方式最直观且可靠:
# 二进制读取原始字节,再转码为UTF-8并移除非法序列 file_content = File.binread('illegal.txt').encode( 'UTF-8', invalid: :replace, undef: :replace, replace: '' ) # 验证结果:输出 [102, 114, 10],对应 "fr\n" puts file_content.bytes.to_a
方法二:指定不同的内外编码触发转码
如果需要通过IO.read的参数配置来实现,必须确保external_encoding和internal_encoding不同,比如将外部编码设为二进制(ASCII-8BIT):
file_content = IO.read( 'illegal.txt', external_encoding: Encoding::ASCII_8BIT, internal_encoding: Encoding::UTF_8, invalid: :replace, undef: :replace, replace: '' )
后续CSV处理优化
既然已经将file_content转换为合法的UTF-8字符串,后续解析CSV时无需重复指定编码参数,直接传入字符串即可:
CSV.foreach(file_content, col_sep: ';', row_sep: :auto) do |row| # 处理逻辑 end
内容的提问来源于stack exchange,提问作者user1934428
相关产品推荐
相关产品推荐

