wake-up-neo.net

Konvertieren Sie Nicht-ASCII-Zeichen von ASCII-8BIT in UTF-8

Ich ziehe Text von entfernten Standorten und versuche, ihn in eine Ruby 1.9/Rails 3-App zu laden, die standardmäßig utf-8 verwendet.

Hier ist ein Beispiel für einen beleidigenden Text:

Cancer Res; 71(3); 1-11. ©2011 AACR.\n

Dieser erweiterte Copyright-Code sieht folgendermaßen aus:

Cancer Res; 71(3); 1-11. \xC2\xA92011 AACR.\n

Ruby sagt mir, dass der String als ASCII-8BIT codiert ist und in meine Rails-App eingespeist wird:

incompatible character encodings: ASCII-8BIT and UTF-8

Ich kann den Copyright-Code mit dieser Regex entfernen

str.gsub(/[\x00-\x7F]/n,'?')

dies zu produzieren

Cancer Res; 71(3); 1-11. ??2011 AACR.\n

Aber wie bekomme ich in UTF-8 ein Copyright-Symbol (und verschiedene andere Symbole wie griechische Buchstaben) konvertiert in dieselben Symbole? Sicher ist es möglich ...

Ich sehe Verweise auf die Verwendung von force_encoding, aber das funktioniert nicht:

str.force_encoding('utf-8').encode

Ich weiß, dass es viele andere Menschen mit ähnlichen Problemen gibt, aber ich habe noch keine Lösung gesehen, die funktioniert.

40
craic.com

Das funktioniert für mich:

#encoding: ASCII-8BIT
str = "\xC2\xA92011 AACR"
p str, str.encoding
#=> "\xC2\xA92011 AACR"
#=> #<Encoding:ASCII-8BIT>

str.force_encoding('UTF-8')
p str, str.encoding
#=> "©2011 AACR"
#=> #<Encoding:UTF-8>
58
Phrogz

Es gibt zwei Möglichkeiten:

  1. Die Eingabedaten sind bereits UTF-8, aber Ruby weiß es nicht. Das scheint Ihr Fall zu sein, da "\ xC2\xA9" UTF-8 für das Copyright-Symbol ist. In diesem Fall müssen Sie Ruby lediglich mitteilen, dass die Daten bereits UTF-8 mit force_encoding verwenden.

    Zum Beispiel "\ xC2\xA9" .force_encoding ('ASCII-8BIT') würde das relevante Bit Ihrer Eingabedaten neu erstellen. Und "\ xC2\xA9" .force_encoding ('ASCII-8BIT'). Force_encoding ('UTF-8') würde zeigen, dass Sie Ruby sagen können, dass es wirklich UTF-8 ist und das gewünschte Ergebnis erhalten.

  2. Die Eingabedaten liegen in einer anderen Kodierung vor und Sie benötigen Ruby, um sie in UTF-8 umzuwandeln. In diesem Fall müssten Sie Ruby mitteilen, wie die aktuelle Kodierung lautet (ASCII-8BIT ist Ruby-speak für binär, es handelt sich nicht um eine echte Kodierung). Dann müssen Sie Ruby die Transkodierung mitteilen.

    Angenommen, Ihre Eingabedaten waren ISO-8859-1. In dieser Kodierung ist das Copyright-Symbol nur "\ xA9". Dies würde so ein bisschen Daten erzeugen: "\ xA9" .force_encoding ('ISO-8859-1') Und das würde zeigen, dass Sie Ruby dazu bringen können, das zu UTF-8 zu transcodieren: "\ xA9" .force_encoding ('ISO -8859-1 '). Encode (' UTF-8 ')

27
Jason Heiss

Ich habe das für ein Skript gemacht, das griechische Windows-kodierte Seiten mit Open-Uri, Iconv und Hpricot abrief:

doc = open(DATA_URL)
doc.rewind
data = Hpricot(Iconv.conv('utf-8', "WINDOWS-1253", doc.readlines.join("\n")))

Ich glaube, das war Ruby 1.8.7, nicht sicher, wie es mit Ruby 1.9 geht

6
Achilles

Ich hatte Probleme mit der Zeichenkodierung und die anderen Antworten waren hilfreich, funktionierten jedoch nicht in jedem Fall. Hier ist die Lösung, mit der ich die Codierung erzwungen habe, wenn dies möglich ist, und Transcodierungen mit '?', Wenn dies nicht möglich ist. Hier ist die Lösung:

  def encode str
    encoded = str.force_encoding('UTF-8')
    unless encoded.valid_encoding?
      encoded = str.encode("utf-8", invalid: :replace, undef: :replace, replace: '?')
    end
    encoded
  end

force_encoding funktioniert meistens, aber ich habe einige Zeichenfolgen gefunden, bei denen dies fehlschlägt. Bei solchen Zeichenfolgen werden ungültige Zeichen ersetzt:

 str = "don't panic: \xD3"
 str.valid_encoding?
 false
 str = str.encode("utf-8", invalid: :replace, undef: :replace, replace: '?')
 "don't panic: ?"
 str.valid_encoding?
 true
0
Jared Menard