2010-01-01 1 views
13

Es scheint mir, dass die YAML-Bibliothek, die mit Ruby 1.9 ausgeliefert wird, kodierend-taub ist.Ruby 1.9, YAML und String Encodings: Wie führt man ein Leben in geistiger Gesundheit?

Dies bedeutet, dass beim Generieren von YAML eine beliebige Bytefolge und jede Bytefolge, die kein sauberes ASCII ausgibt, entkoppelt werden kann. Das ist lahm, aber akzeptabel.

Mein Problem ist anders herum. Wenn Inhalt von dem YAML-Speicherauszug geladen wird.

Im folgenden Beispiel erstelle ich eine UTF-8-Zeichenfolge, dump es, es wird mit dem Typ !binary ausgegeben. Wenn ich es zurücklade, hat es die Codierung ASCII-8BIT. Am Ende des Beispiels versuche ich, sowohl die ursprüngliche als auch die neu geladene Zeichenfolge mit einer anderen UTF-8-Zeichenfolge zu verketten. Letzteres wird mit einem Encoding::CompatibilityError fehlschlagen.

require 'yaml' 
s0 = "Iñtërnâtiônàlizætiøn" 
y = s0.to_yaml 
s1 = YAML::load y 
puts s0     # => Iñtërnâtiônàlizætiøn 
puts s0.encoding  # => UTF-8 
puts s1     # => Iñtërnâtiônàlizætiøn 
puts s1.encoding  # => ASCII-8BIT 
puts y     # => --- !binary | 
         # ScOxdMOrcm7DonRpw7Ruw6BsaXrDpnRpw7hu 
puts "ñårƒ" + s0  # => ñårƒIñtërnâtiônàlizætiøn 
puts "ñårƒ" + s1  # => Encoding::CompatibilityError: incompatible character encodings: UTF-8 and ASCII-8BIT 

Ich denke, es ist klar, wie dies schnell zu Problemen führen, wenn Sie mit einiger YAML Quelle zu tun haben verschachtelten Hashes und Arrays mit Blattzeichenketten enthalten.

Derzeit habe ich einige Code, der alle Hashes und Arrays durchlaufen und force_encoding auf jeder Zeichenfolge aufruft. Das ist zumindest unansehnlich.

Was ich für jetzt suche, ist ein Weg, YAML::load zu sagen, dass jede Zeichenfolge, die in kommen sollte so behandelt werden, und damit seine Codierung auf UTF-8 gesetzt hat.

Idealerweise sollte Rubins YAML nur die Zeichenketten mit der richtigen Kodierung versehen. Es gibt ein Ya2YAML-Projekt, das versucht, UTF-8-sicheres YAML auszugeben. Ich bin mir nicht sicher, wie weit es ist. Wenn jemand damit gespielt hat, begrüße ich alle Gedanken.

Unabhängig davon, habe ich immer noch diese Dumps ohne jegliche Kodierung Informationen zu bewältigen. Obwohl ich weiß, dass sie alle UTF-8 sind.

+2

+1 für die Schwermetallumblätter. –

+0

Ich renne nur in den gleichen Fehler/Verhalten ... Haben Sie eine andere Lösung gefunden oder machen Sie immer nur YAML.load und dann force_encoding ('utf-8') auf jeder Zeichenfolge? – severin

Antwort

1

Zunächst muss die Textdatei, die Sie lesen möchten, UTF-8-codiert sein (dies sollte Ihre YAML-Datei sein).

Dann diese Linie an die Spitze Ihres Rubin-Datei, Hash hinzufügen und alle

# encoding: UTF-8 

Dies bedeutet, dass die Standard-Kodierung für all Strings UTF-8 sein, und soll bedeuten, dass jeder Text, den Sie Dump mit YAML.dump ('text') oder auch String-Literalen 'so' sollte auch UTF-8 codiert sein, und alle sollten von hier aus gut funktionieren.

+0

spielt keine Rolle. Sachen, die gelesen werden als! Binary vom yaml enden als ASCII-8BIT, für vielleicht offensichtliche und vernünftige Gründe, aber so yaml sollte unsecaped UTF8 Zeichenfolgen richtig ablegen. Ich habe mehr oder weniger eine Lösung dafür, aber beinhaltet einen guten Chunk-Code. Ich werde eine Antwort posten, wenn ich einen Edelstein fertig habe. – kch

3

Überlegen Sie, Ihren Rubin auf den neuesten 1.9.2 zu aktualisieren .

Ich fand diesen Fehler in 1.9.1, aber nicht 1.9.2.

2
YAML::ENGINE.yamler='psych' 
'Résumé'.to_yaml # => "--- Résumé\n...\n" 
0

Evgeny Antwort zeigt noch binäre für mich, aber das funktioniert ('syck' instoad von 'Psych'):

YAML::ENGINE.yamler='syck' 
'Résumé'.to_yaml # => "--- "R\xE9sum\xE9" 

Ich bin mit Ruby 1.9. Hinweis für meine Zwecke, dass die Specials, die escape gibt, gut sind - ich brauchte es nur, um nicht zu zeigen! Binary ... für normale Wörter. Gott sei Dank .to_yaml ist wieder funktionstüchtig - ich benutze es die ganze Zeit. Wie man ein Leben der Vernunft tatsächlich lädt :)

+0

Danke für diesen Fehler user1262147 - yamler = 'psych' hat nichts für mich getan, aber yamler = 'syck' hat es behoben. Zuvor hatte to_yaml alles als! Binary = was auch immer - sogar Attributnamen von einem ActiveRecord, das von einer UTF8-mysql-Tabelle stammte, gedumpt. –

+0

Antwort ist veraltet, es war veraltet, als es gemacht wurde, syck ist veraltet – bbozo