2014-01-27 5 views
7

Ich muss Unicode-Dateien lesen, die möglicherweise eine Byte-Order-Markierung enthalten. Ich könnte natürlich die ersten paar Bytes der Datei selbst überprüfen und eine Stückliste verwerfen, wenn ich eine finde. Aber bevor ich das mache, gibt es einen Standardweg, entweder in den Kernbibliotheken oder in einer dritten Partei?Lesen von Dateien mit einer Stückliste in Go

Antwort

3

keine Standardmethode, IIRC hier (und die Standard-Bibliothek wäre wirklich eine falsche Schicht eine solche Überprüfung in zu implementieren sein), so sind zwei Beispiele dafür, wie man mit ihm selbst beschäftigen können.

Eine davon ist eine gepufferte Leser über Ihre Datenstrom zu verwenden:

import (
    "bufio" 
    "os" 
    "log" 
) 

func main() { 
    fd, err := os.Open("filename") 
    if err != nil { 
     log.Fatal(err) 
    } 
    defer closeOrDie(fd) 
    br := bufio.NewReader(fd) 
    r, _, err := br.ReadRune() 
    if err != nil { 
     log.Fatal(err) 
    } 
    if r != '\uFEFF' { 
     br.UnreadRune() // Not a BOM -- put the rune back 
    } 
    // Now work with br as you would do with fd 
    // ... 
} 

Ein anderer Ansatz, der mit Objekten der Umsetzung der io.Seeker Schnittstelle arbeitet, ist die ersten drei Bytes zu lesen und wenn sie nicht BOM, io.Seek() an den Anfang zurück, wie in:

import (
    "os" 
    "log" 
) 

func main() { 
    fd, err := os.Open("filename") 
    if err != nil { 
     log.Fatal(err) 
    } 
    defer closeOrDie(fd) 
    bom := [3]byte 
    _, err = io.ReadFull(fd, bom[:]) 
    if err != nil { 
     log.Fatal(err) 
    } 
    if bom[0] != 0xef || bom[1] != 0xbb || bom[2] != 0xbf { 
     _, err = fd.Seek(0, 0) // Not a BOM -- seek back to the beginning 
     if err != nil { 
      log.Fatal(err) 
     } 
    } 
    // The next read operation on fd will read real data 
    // ... 
} 

Diese seit Instanzen möglich ist *os.File (was os.Open() Returns) Unterstützung suchen und damitimplementieren. Beachten Sie, dass dies nicht der Fall ist, zB Body Leser von HTTP-Antworten, da Sie es nicht "zurückspulen" können. bufio.Buffer funktioniert um diese Funktion von nicht-seekbaren Streams durch Ausführen einer Pufferung (offensichtlich) — das ist, was Sie können UnreadRune() darauf.

Beachten Sie, dass beide Beispiele davon ausgehen, dass die Datei, mit der wir es zu tun haben, in UTF-8 kodiert ist. Wenn Sie mit einer anderen (oder unbekannten) Codierung arbeiten müssen, werden die Dinge komplizierter.

+0

Der Bufio-Ansatz hat funktioniert, und ich mag, dass er die Stückliste als eine einzelne Rune und nicht als eine Menge von Bytes betrachtet. –

+0

@kostix Wolke erklären Sie, wie man die Bedingung in der zweiten Annäherung ableitet ?. Danke – Anuruddha

+0

@Anuruddha, sorry, ich habe es versäumt, Ihre Frage zu analysieren - insbesondere die "ableiten der Bedingung" Teil, der wesentlich erscheint. Pflege um zu erarbeiten? Kann in ein paar Sätzen sein. – kostix

3

Es gibt keine Standardmethode, dies in den Go-Kernpaketen zu tun. Befolgen Sie den Unicode-Standard.

Unicode Byte Order Mark (BOM) FAQ

+1

Wenn ich alle Dateien und Streams selbst erzeugen würde, würde ich natürlich dem Unicode-Standard folgen. Aber wie viele Menschen auf der Welt bin ich dabei, Daten zu konsumieren, die von jemand anderem produziert wurden. –

1

Sie können utfbom Paket verwenden. Es umschließt io.Reader, erkennt und löscht die Stückliste nach Bedarf. Es kann auch die von der Stückliste erkannte Codierung zurückgeben.

Verwandte Themen