【问题标题】:Rails/Ruby invalid byte sequence in UTF-8 even after force_encoding即使在 force_encoding 之后,Rails/Ruby 中的 UTF-8 字节序列也无效
【发布时间】:2015-11-29 11:59:08
【问题描述】:

我正在尝试在 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'

【问题讨论】:

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


    【解决方案1】:

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

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

    首先要做的是确定实际使用的编码是什么。 charlock_holmes gem 可以检测编码。一个更棘手的情况是,如果文件是混合的编码,但希望不是这种情况(如果是,那么尝试单独处理每一行可能会起作用)。

    【讨论】:

      【解决方案2】:

      如果您想获取一个具有正确编码的字符串,并将其转码为有效的 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

      【讨论】:

        猜你喜欢
        • 2023-04-03
        • 2012-03-25
        • 1970-01-01
        • 2012-01-12
        • 2011-02-28
        • 1970-01-01
        • 2012-06-19
        • 2013-03-02
        • 1970-01-01
        相关资源
        最近更新 更多