Ruby 如何使用:replace、:invalid和:undef参数来使用CSV.read进行编码?
由于ruby 1.9,CSV使用可以执行编码的解析器,如果您使用以下方法:Ruby 如何使用:replace、:invalid和:undef参数来使用CSV.read进行编码?,ruby,csv,encoding,Ruby,Csv,Encoding,由于ruby 1.9,CSV使用可以执行编码的解析器,如果您使用以下方法: ::foreach、::open、::read和::readlines 例如:CSV.read('path/to/file',encoding:“windows-1252:UTF-8”)尝试读取windows-1252中的文件,并返回一个带有UTF-8编码字符串的数组 如果字符集之间的编码转换包含未定义的字符,则会给出一个编码::UndefinedConversionError String.encode方法有一些很好的
::foreach、::open、::read和::readlines
例如:CSV.read('path/to/file',encoding:“windows-1252:UTF-8”)
尝试读取windows-1252中的文件,并返回一个带有UTF-8编码字符串的数组
如果字符集之间的编码转换包含未定义的字符,则会给出一个编码::UndefinedConversionError
String.encode方法有一些很好的参数来处理这些未定义的字符:
str=str.encode('UTF-8',无效::替换,未定义::替换,替换:“”)
有没有一种方法可以使用这种替换规则在CSV解析器的字符集之间进行未定义的转换
谢谢。如果您想使用String#encode的替换行为,您必须使用它对整个文件内容进行编码,或者逐行进行编码您将因此丢失信息。 但这是一种方法:
file = File.open('path/to/file.csv')
file.each do |line|
# keep in mind that the first parameter here is the destination encoding,
# the second is the source encoding
sanitized_line = line.encode('UTF-8', 'windows-1252', invalid: :replace, undef: :replace, replace: '')
fields_array = CSV.parse_line(sanitized_line)
# do whatever you want with the fields you extracted
end
如果从一种编码到另一种编码的转换几乎可以保证不会丢失信息(例如iso-8859-1到utf-8),我真的建议您在读取时简单地转换文件
要记住的另一件事是,ruby不会试图自己找出正在读取的文件的编码。如果省略该参数,它将仅使用其外部和内部编码的默认编码。因此,您必须自己指定文件的编码。Ruby没有真正可靠的方法来实现这一点,所以在我的例子中,我最终做到了(在Ubuntu系统上):
的确,有一种方法。诀窍是定义一个自定义转换器,它使用
String#encode
执行您想要的转换。转换器在CSV尝试自动转换为UTF-8之前运行。我们将自定义转换器传递给CSV。读取:converters
选项以及原始:encoding
:
UTF8_CONVERTER = ->(field) { field.encode('utf-8', invalid: :replace, undef: :replace, replace: "") }
CSV.read('foo.csv', encoding: 'windows-1252', converters: UTF8_CONVERTER)
由于Windows-1252中没有任何字符不在UTF-8中,因此我将以另一种方式演示。假设您有这个UTF-8 CSV文件:
foo,bar
是的还有一点需要注意的是,如果任何字段包含换行符(在引用的字段中有效),则此操作将失败。此解决方案有效。我发现乔丹的一个更完整。谢谢。KMoschcau解决方案也可以使用。我之所以选择这个,是因为我发现将转换器定义为过程更为完整。
UTF8_CONVERTER = ->(field) { field.encode('utf-8', invalid: :replace, undef: :replace, replace: "") }
CSV.read('foo.csv', encoding: 'windows-1252', converters: UTF8_CONVERTER)