20

Rails バージョン 1 以降の移行から生き残った Rails アプリケーションがあり、下位互換性を維持するために無効なバイト シーケンスをすべて無視したいと考えています。

入力エンコーディングがわかりません

例:

> "- Men\xFC -".split("n")
ArgumentError: invalid byte sequence in UTF-8
    from (irb):4:in `split'
    from (irb):4
    from /home/fotanus/.rvm/rubies/ruby-2.0.0-rc2/bin/irb:16:in `<main>'

たとえば、次のようにすると、この問題を 1 行で解決できます。

> "- Men\xFC -".unpack("C*").pack("U*").split("n")
 => ["- Me", "ü -"] 

ただし、無効なバイト シーケンスを常に無視し、このエラーを無効にしたいと考えています。Ruby 自体または Rails で。

4

5 に答える 5

6

ruby 2.0 では、String#b メソッドを使用できました。これは、String#force_encoding("BINARY") の短いエイリアスです。

于 2013-06-14T19:15:45.127 に答える
3

生のバイトだけを操作したい場合は、ASCII-8BIT/BINARY としてエンコードしてみてください。

str.force_encoding("BINARY").split("n")

ただし、この場合のソース文字列は ISO-8859-1 (またはそのようなもの) であるため、これは ü を取り戻すことはありません。

"- Men\xFC -".force_encoding("ISO-8859-1").encode("UTF-8")
 => "- Menü -"

マルチバイト文字を取得したい場合は、ソース文字セットが何であるかを知る必要がありますBINARYにforce_encodingすると、文字通り生のバイトだけが得られるため、マルチバイト文字はそれに応じて解釈されません。

データがデータベースからのものである場合は、ASCII-8BIT または BINARY エンコーディングを使用するように接続メカニズムを変更できます。その場合、 Rubyそれに応じてフラグを立てる必要があります。または、データベース ドライバーにモンキー パッチを適用して、読み取ったすべての文字列を強制的にエンコードすることもできます。ただし、これは大きなハンマーであり、絶対に間違ったことをする可能性があります.

正しい答えは、文字列エンコーディングを修正することです。これには、データベースの修正、データベース ドライバ接続エンコーディングの修正、またはそれらの組み合わせが必要になる場合があります。すべてのバイトはまだそこにありますが、特定の文字セットを扱っている場合は、可能であれば、データがそのエンコーディングであると予想されることを Ruby に知らせる必要があります。よくある間違いは、mysql2 ドライバーを使用して、latin1 エンコーディングのデータを持つ MySQL データベースに接続するのに、接続に utf-8 文字セットを指定することです。これにより、Rails は DB から latin1 データを取得し、UTF-8 に変換できる latin1 として解釈するのではなく、utf-8 として解釈します。

文字列がどこから来ているかを詳しく説明できれば、より完全な答えが得られる可能性があります。デフォルトの文字列エンコーディングに対する可能なグローバル(-ish)Railsソリューションについては、この回答を確認することもできます。

于 2013-06-09T23:22:25.753 に答える
2

ASCII-8BIT で文字列を提供するようにデータベース/ページ/その他を構成できる場合、これにより実際のエンコーディングが取得されます。

Ruby の stdlib エンコーディング推測ライブラリを使用します。すべての文字列を次のように渡します。

require 'nkf'
str = "- Men\xFC -"
str.force_encoding(NKF.guess(str))

NKF ライブラリはエンコーディングを推測し (通常は成功します)、そのエンコーディングを文字列に適用します。NKF ライブラリを完全に信頼したくない場合は、文字列操作にもこのセーフガードを構築してください。

begin
  str.split
rescue ArgumentError
  str.force_encoding('BINARY')
  retry
end

NKF が正しく推測しなかった場合、これは BINARY にフォールバックします。これをメソッドラッパーに変えることができます:

def str_op(s)
  begin
    yield s
  rescue ArgumentError
    s.force_encoding('BINARY')
    retry
  end
end
于 2013-06-10T16:10:18.227 に答える