2013-10-03 4 views
8

Um einen String in UTF-8 und ersetzen Sie alle Codierungsfehler zu konvertieren, können Sie tun:Wie kann ich UTF-8-Fehler in Ruby ersetzen, ohne in eine andere Kodierung zu konvertieren?

str.encode('utf-8', :invalid=>:replace) 

Das einzige Problem dabei ist, es funktioniert nicht, wenn str bereits UTF-8 ist, in denen Fall Fehler bleiben:

irb> x = "foo\x92bar".encode('utf-8', :invalid=>:replace) 
=> "foo\x92bar" 
irb> x.valid_encoding? 
=> false 

das Zitat Ruby Docs:

Bitte beachten Sie, dass die Umwandlung von einer Codierung enc auf die s eine Codierung enc ist ein No-Op, d. h. der Empfänger wird ohne irgendwelche Änderungen zurückgegeben, und es werden keine Ausnahmen ausgelöst, selbst wenn ungültige Bytes vorhanden sind.

ist die offensichtliche Abhilfe zu einer anderen Unicode-Codierung zum ersten konvertieren und dann zurück in UTF-8:

str.encode('utf-16', :invalid=>:replace).encode('utf-8') 

Zum Beispiel: zu tun

irb> x = "foo\x92bar".encode('utf-16', :invalid=>:replace).encode('utf-8') 
=> "foo�bar" 
irb> x.valid_encoding? 
=> true 

Gibt es eine bessere Art und Weise dies ohne Umwandlung in eine Dummy-Codierung?

Antwort

11

Rubin 2.1 hinzugefügt eine String#scrub Methode zu ersetzen, das tut, was Sie wollen:

2.1.0dev :001 > x = "foo\x92bar" 
=> "foo\x92bar" 
2.1.0dev :002 > x.valid_encoding? 
=> false 
2.1.0dev :003 > y = x.scrub 
=> "foo�bar" 
2.1.0dev :004 > y.valid_encoding? 
=> true 

Das gleiche begehen auch die Änderungen Verhalten von encode, so dass es funktioniert, wenn die Quell- und dest-Kodierungen sind die gleichen:

2.1.0dev :005 > x = "foo\x92bar".encode('utf-8', :invalid=>:replace) 
=> "foo�bar" 
2.1.0dev :006 > x.valid_encoding? 
=> true 

Soweit ich weiß, dass es nicht in so gebaut ist, dies zu tun, bevor 2.1 etwas Abhilfe Technik verwenden, bis 2.1 freigegeben wird (sonst scrub wäre nicht erforderlich) so müssen Sie und du kannst upgraden.

+0

Danke für die Info! Leider bin ich mit Ruby 1.9 fest und kann nicht upgraden (zumindest bei diesem Projekt). – Matt

+1

Verwenden Sie das Juwel "scrub_rb" in früheren Versionen von Ruby –

2

Try this:

"foo\x92bar".chars.select(&:valid_encoding?).join 
    # => "foobar" 

Oder

"foo\x92bar".chars.map{|c| c.valid_encoding? ? c : "?"}.join 
# => "foo?bar" 
+0

Das scheint auch ziemlich Work-Around-Ish. – Matt

+0

@Matt nein, das ist genau das, was Sie wollen. Suchen und Entfernen ungültiger Zeichen – Reactormonk

+0

@Tass Es gibt einen Unterschied zwischen "tun, was ich will" und "es richtig machen". Ja, es tut was ich will, aber auch mein Beispiel oben mit der UTF-16-Konvertierung. Ich habe nur auf eine eingebaute Methode gehofft, die wahrscheinlich effizienter ist, als selbst durch die Saite zu streichen. Ich gebe jedoch zu, dass dies eine bessere Lösung ist als die, die ich hatte. – Matt

Verwandte Themen