2012-04-23 19 views
15

Potrzebuję przeczytać plik tekstowy zakodowany w GBK. Standardowa biblioteka w języku programowania Go zakłada, że ​​cały tekst jest kodowany w UTF-8.Odczytywanie pliku tekstowego innego niż UTF-8 w Go

Jak mogę odczytać pliki w innych kodowaniach?

+0

Dlaczego spadki? –

+0

To wygląda na bardzo rozsądne i jasne pytanie, głosowanie na ponowne otwarcie (nawet w oryginalnej postaci) – OscarRyz

Odpowiedz

13

Wcześniej (jak wspomniano w starszej odpowiedzi) "łatwy" sposób na to polegał na użyciu pakietów stron trzecich, które wymagały cgo i opakowaniu biblioteki iconv. Jest to niepożądane z wielu powodów. Na szczęście, od jakiegoś czasu istnieje lepszy sposób działania Go przy użyciu tylko pakietów dostarczonych przez Go Autorzy (nie w głównym zestawie pakietów, ale w Go Sub-Repositories).

Pakiet golang.org/x/text/encoding definiuje interfejs dla ogólnych kodowań znaków, które można konwertować do/z UTF-8. Podpakiet golang.org/x/text/encoding/simplifiedchinese zapewnia implementacje kodowania GB18030, GBK i HZ-GB2312.

Oto przykład odczytywania i zapisywania pliku zakodowanego w GBK. Należy pamiętać, że kodowanie io.Reader i io.Writer odbywa się "w locie" podczas odczytu/zapisu danych.

package main 

import (
    "bufio" 
    "fmt" 
    "log" 
    "os" 

    "golang.org/x/text/encoding/simplifiedchinese" 
    "golang.org/x/text/transform" 
) 

// Encoding to use. Since this implements the encoding.Encoding 
// interface from golang.org/x/text/encoding you can trivially 
// change this out for any of the other implemented encoders, 
// e.g. `traditionalchinese.Big5`, `charmap.Windows1252`, 
// `korean.EUCKR`, etc. 
var enc = simplifiedchinese.GBK 

func main() { 
    const filename = "example_GBK_file" 
    exampleWriteGBK(filename) 
    exampleReadGBK(filename) 
} 

func exampleReadGBK(filename string) { 
    // Read UTF-8 from a GBK encoded file. 
    f, err := os.Open(filename) 
    if err != nil { 
     log.Fatal(err) 
    } 
    r := transform.NewReader(f, enc.NewDecoder()) 

    // Read converted UTF-8 from `r` as needed. 
    // As an example we'll read line-by-line showing what was read: 
    sc := bufio.NewScanner(r) 
    for sc.Scan() { 
     fmt.Printf("Read line: %s\n", sc.Bytes()) 
    } 
    if err = sc.Err(); err != nil { 
     log.Fatal(err) 
    } 

    if err = f.Close(); err != nil { 
     log.Fatal(err) 
    } 
} 

func exampleWriteGBK(filename string) { 
    // Write UTF-8 to a GBK encoded file. 
    f, err := os.Create(filename) 
    if err != nil { 
     log.Fatal(err) 
    } 
    w := transform.NewWriter(f, enc.NewEncoder()) 

    // Write UTF-8 to `w` as desired. 
    // As an example we'll write some text from the Wikipedia 
    // GBK page that includes Chinese. 
    _, err = fmt.Fprintln(w, 
     `In 1995, China National Information Technology Standardization 
Technical Committee set down the Chinese Internal Code Specification 
(Chinese: 汉字内码扩展规范(GBK); pinyin: Hànzì Nèimǎ 
Kuòzhǎn Guīfàn (GBK)), Version 1.0, known as GBK 1.0, which is a 
slight extension of Codepage 936. The newly added 95 characters were not 
found in GB 13000.1-1993, and were provisionally assigned Unicode PUA 
code points.`) 
    if err != nil { 
     log.Fatal(err) 
    } 

    if err = f.Close(); err != nil { 
     log.Fatal(err) 
    } 
} 
5

Wypróbuj go-iconv. To opakowuje iconv i implementuje io.Reader i io.Writer.

Ten message w grupie dyskusyjnej golang-china wymienia kilka przykładów użycia go-iconv.

+0

Inną opcją byłoby odczytanie pliku jako nieprzezroczystej kropli w buforze, a następnie zinterpretowanie jej jako tekstu w określonym kodowaniu za pomocą [go-charset] (http://code.google.com/p/go-charset); zobacz [to pytanie] (http://stackoverflow.com/q/10039701/720999), aby uzyskać więcej informacji. Nie spojrzałem na kod, ale wygląda na to, że aby obsługiwać zestaw najczęściej używanych starszych zestawów znaków/kodowań, ten pakiet nie potrzebuje iconv, co może być zaletą. – kostix

+0

@kostix Z informacji na stronie tytułowej http://code.google.com/p/go-charset wynika, że ​​w przypadku gbk pakiet używa biblioteki GNU iconv. –

+0

Ten pakiet może być również użyty do przeprowadzenia transformacji: https://godoc.org/golang.org/x/text/encoding – OscarRyz