如何在 Go 中读取 UTF-16 文本文件
理解问题
许多文件格式使用 UTF-16 编码(一种两字节 Unicode 编码)对文本数据进行编码。当您在 Go 中读取 UTF-16 文件时,正确解码字节以获得实际的文本内容非常重要。然而,Go 中的默认行为是将 UTF-16 字节视为 ASCII,这可能会导致错误的结果。
解码 UTF-16 文件
读取正确的UTF-16文件,读取文件时需要指定编码。 Go 为此提供了 unicode.UTF16 解码器。这是您提供的代码的更新版本:
package main import ( "bytes" "fmt" "io/ioutil" "os" "strings" "golang.org/x/text/encoding/unicode" ) func main() { // Read the file into a []byte raw, err := ioutil.ReadFile("test.txt") if err != nil { fmt.Printf("error opening file: %v\n", err) os.Exit(1) } // Create a Unicode UTF-16 decoder utf16be := unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM) // Create a transformer to decode the data transformer := utf16be.NewDecoder() // Decode the text using the transformer decoded, err := transformer.Bytes(raw) if err != nil { fmt.Printf("error decoding file: %v\n", err) os.Exit(1) } // Convert the decoded bytes to a string text := string(decoded) // Remove any Windows-style line endings (CR+LF) final := strings.Replace(text, "\r\n", "\n", -1) // Print the final text fmt.Println(final) }
此代码使用 unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM) 创建具有大端字节顺序的 UTF-16 解码器忽略任何字节顺序标记 (BOM)。 BOM 用于指示文件的字节顺序,但由于我们忽略它,因此无论 BOM 如何,代码都将正常工作。
然后使用 string() 函数将解码后的字节转换为字符串。最后,使用 strings.Replace() 删除所有 Windows 样式的行结尾。
使用新扫描仪扫描 UTF-16 文件
如果您需要读取文件逐行,您可以使用 golang.org/x/text 包中的 New ScannerUTF16 函数来代替 ioutil.ReadFile。下面是一个示例:
package main import ( "bufio" "fmt" "os" "golang.org/x/text/encoding/unicode" "golang.org/x/text/transform" ) func NewScannerUTF16(filename string) (*bufio.Scanner, error) { // Read the file into a []byte raw, err := os.ReadFile(filename) if err != nil { return nil, err } // Create a Unicode UTF-16 decoder utf16be := unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM) // Create a transformer to decode the data transformer := utf16be.NewDecoder() // Create a scanner that uses the transformer scanner := bufio.NewScanner(transform.NewReader(bytes.NewReader(raw), transformer)) return scanner, nil } func main() { // Create a scanner for the UTF-16 file scanner, err := NewScannerUTF16("test.txt") if err != nil { fmt.Printf("error opening file: %v\n", err) os.Exit(1) } // Read the file line by line for scanner.Scan() { fmt.Println(scanner.Text()) } }
此代码使用 bufio.NewScanner() 函数创建一个扫描仪,该扫描仪从转换后的读取器中读取数据,并解码 UTF-16 字节。通过使用扫描仪,您可以迭代文件的行,而无需将整个文件读入内存。
以上是如何在Go中正确读取和解码UTF-16文本文件?的详细内容。更多信息请关注PHP中文网其他相关文章!