Go语言中如何将UCS-2 little Endian编码文件转UTF-8读取?
如何在Go中将UCS-2 Little Endian编码文件转换为UTF-8读取?
你的现有代码默认按UTF-8编码处理文件,而UCS-2 Little Endian(本质是UTF-16LE的子集,不支持代理对)是双字节编码,直接用bufio.Scanner读取会因为编码不匹配导致乱码或读取失败。下面是一个实用的修改方案,帮你完成编码转换并正常读取内容:
核心思路
Go标准库的encoding/binary和unicode/utf16包可以完美解决这个转码需求:
encoding/binary:负责按小端序读取UCS-2的双字节码点unicode/utf16:将UTF-16码点转换为Go原生的rune序列(Go字符串底层是UTF-8编码)
修改后的完整代码
package main import ( "encoding/binary" "io/ioutil" "log" "unicode/utf16" ) func main() { // 读取文件全部字节(UCS-2是双字节对齐,避免截断码点) fileBytes, err := ioutil.ReadFile("test.txt") if err != nil { log.Fatalf("failed to open file: %v", err) } // 校验文件字节数:UCS-2每个字符占2字节,奇数字节说明文件损坏 if len(fileBytes)%2 != 0 { log.Fatalf("invalid UCS-2 LE file: odd number of bytes detected") } // 将字节切片解析为UTF-16LE编码的码点切片 var utf16CodePoints []uint16 for i := 0; i < len(fileBytes); i += 2 { utf16CodePoints = append(utf16CodePoints, binary.LittleEndian.Uint16(fileBytes[i:i+2])) } // 将UTF-16码点转换为UTF-8编码的字符串 utf8Runes := utf16.Decode(utf16CodePoints) utf8Content := string(utf8Runes) // 如果你需要按行处理,可以用bufio.Scanner处理转换后的UTF-8内容 // 示例: // scanner := bufio.NewScanner(strings.NewReader(utf8Content)) // scanner.Split(bufio.ScanLines) // var lines []string // for scanner.Scan() { // lines = append(lines, scanner.Text()) // } // if err := scanner.Err(); err != nil { // log.Fatalf("error scanning lines: %v", err) // } log.Println("Converted UTF-8 content:") log.Println(utf8Content) }
关键步骤说明
- 读取全部字节:UCS-2是双字节编码,一次性读取所有字节能保证不会截断单个字符的字节对,避免转码错误。
- 合法性校验:如果文件字节数为奇数,说明文件可能损坏或编码不规范,直接抛出错误避免后续问题。
- 解析UTF-16码点:通过
binary.LittleEndian.Uint16逐个读取双字节数据,得到UTF-16的无符号16位整数码点。 - 转码为UTF-8:
utf16.Decode会自动处理UTF-16的代理对(如果有的话,虽然UCS-2不包含,但兼容处理),将码点转换为Go的rune切片,直接转为字符串就是标准UTF-8编码的内容了。
额外说明
如果你的UCS-2文件开头包含BOM(字节顺序标记,FF FE),不用担心——utf16.Decode会自动忽略这个标记码点(0xFEFF),无需额外处理。
内容的提问来源于stack exchange,提问作者B.G.Venkatraj
相关产品推荐
相关产品推荐

