即使在force_encoding

时间:2015-11-29 11:59:09

标签: ruby-on-rails ruby utf-8 gzip zlib

我试图在Rails中迭代一个远程nginx日志文件(压缩的.gz文件),并且我在文件中的某个位置收到此错误:

TTPArgumentError: invalid byte sequence in UTF-8

我尝试强制编码,尽管编码似乎已经是UTF8:

logfile = logfile.force_encoding("UTF-8")

我使用的方法:

  def remote_update
    uri = "http://" + self.url + "/localhost.access.log.2.gz"
    source = open(uri)
    gz = Zlib::GzipReader.new(source)
    logfile = gz.read

    # prints UTF-8
    print logfile.encoding.name
    logfile = logfile.force_encoding("UTF-8")

    # prints UTF-8
    print logfile.encoding.name

    logfile.each_line do |line|
      print line[/\/someregex\/1\/(.*)\//,1]
    end 
  end

真的试图理解为什么会发生这种情况(试图查看其他SO线程但没有成功)。这里有什么问题?

更新

添加了例外跟踪:

HTTPArgumentError: invalid byte sequence in UTF-8
    from /Users/T/workspace/sample_app/app/models/server.rb:25:in `[]'
    from /Users/T/workspace/sample_app/app/models/server.rb:25:in `block in remote_update'
    from /Users/T/workspace/sample_app/app/models/server.rb:24:in `each_line'
    from /Users/T/workspace/sample_app/app/models/server.rb:24:in `remote_update'
    from (irb):2
    from /Users/T/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/railties-4.2.5/lib/rails/commands/console.rb:110:in `start'
    from /Users/T/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/railties-4.2.5/lib/rails/commands/console.rb:9:in `start'

2 个答案:

答案 0 :(得分:1)

force_encoding不会更改实际的字符串数据:它只是更改了解释字节时要使用的编码的变量。

如果数据实际上不是utf-8或包含无效的utf-8序列,则强制编码不会有帮助。强制编码基本上只有当你从某个地方获得一些原始数据时才有用,你知道它是什么编码,你想告诉ruby那个编码是什么。

要做的第一件事是确定使用的实际编码是什么。 charlock_holmes gem可以检测编码。一个更棘手的案例是,如果文件是编码的混合,但希望不是这样(如果是,那么也许尝试单独处理每一行可能会有效)。

答案 1 :(得分:0)

如果你想获取一个具有正确编码的字符串,并将其转码为有效的UTF-8并清理无效字符,你可以使用以下内容:

str.encode!('UTF-8', invalid: :replace, undef: :replace, replace: '?')

如果您的UTF-8编码字符串中包含无效的UTF-8字符,您可以使用“二进制”编码源清除它:

str.encode!('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '?')

两者都会给你一个UTF-8字符串,其中任何无效字符都应该被问号所代替。您也可以传递replace: ''来删除不良字符,或者关闭该选项,您将获得\uFFFD unicode字符。

我的猜测是gzipping之前的源文件有一些二进制数据/损坏/无效的UTF-8登录到它?

此问题也已在StackOverflow上提出并回答过。有关详细信息,请参阅以下博文:

https://robots.thoughtbot.com/fight-back-utf-8-invalid-byte-sequences

这是SO答案的先前例子:

https://stackoverflow.com/a/18454435/506908