我来自德国,所以我使用变音符号,如ä,ö和ü. 然而,Golang 不能从标准输入正确读取它们。当我执行这个简单的程序时:package mainimport ( "bufio" "fmt" "os")func main() { for { b, _, _ := bufio.NewReader(os.Stdin).ReadLine() printBytes(b) }}func printBytes(bytes []byte) { for _, b := range bytes { fmt.Printf("0x%X ", b) } fmt.Println()}我得到输出:C:\dev\golang>go run test.goä0xE2 0x80 0x9EE2 80 9E不是äUTF-8 中的正确字节序列(这个工具告诉我它是一个“双低 9 引号”-> „),当我打印出我读过的内容时,它会打印出来"。我写了一个小“hack”,似乎可以正确读取字符:package main/*#include <stdio.h>#include <stdlib.h>char * getline(void) { char * line = malloc(100), * linep = line; size_t lenmax = 100, len = lenmax; int c; if(line == NULL) return NULL; for(;;) { c = fgetc(stdin); if(c == EOF) break; if(--len == 0) { len = lenmax; char * linen = realloc(linep, lenmax *= 2); if(linen == NULL) { free(linep); return NULL; } line = linen + (line - linep); linep = linen; } if((*line++ = c) == '\n') break; } *line = '\0'; return linep;}void freeline(char* ptr) { free(ptr);}*/import "C"import ( "fmt" "golang.org/x/text/encoding/charmap")func getLineFromCp850() string { line := C.getline() goline := C.GoString(line) C.freeline(line) b := []byte(goline) ub, _ := charmap.CodePage850.NewDecoder().Bytes(b) return string(ub)}func main() { for { line := getLineFromCp850() printBytes([]byte(line)) }}func printBytes(bytes []byte) { for _, b := range bytes { fmt.Printf("0x%X ", b) } fmt.Println()}它打印出来:C:\dev\golang>go run test.goä0xC3 0xA4 0xAC3 A4是正确的字节序列ä(0A 是我的 hack 没有剥离的换行符)所以看起来,从 CP850 读取和转换为 UTF-8 完成了这项工作,正如我所料,但是为什么 Go 会给我胡言乱语当我使用 Go 的功能而不是 cgo 读取该行?Go 有什么问题,它给了我这些值,它不是将输入字节解释为 CP850 而是另一个字符集?有没有更好的 Go-only 方法来处理这个问题?此问题仅在从标准输入读取时出现。当我将 UTF-8ä打印到标准输出时,它会在控制台中正确打印。
1 回答
慕姐4208626
TA贡献1852条经验 获得超7个赞
因此,对于某些系统来说,这是 Golang 中的一个错误,特别是针对整体使用的字符集和控制台字符集不同的 Windows 系统(WinAPI 从哪里返回不同的东西)GetACP()
。GetConsoleCP()
例如,在德国(可能还有其他西欧国家),Windows 使用代码页 1252 作为整体字符集,但它使用代码页 850 作为控制台cmd.exe
。不知道为什么,但就是这样。Golang 错误地用于GetACP()
将输入解码为 UTF-8,而它确实应该使用GetConsoleCP()
. 我们在我创建的问题中发现了问题,我们希望看到该修复合并到 Golang 的下一个版本中。
我们还在 Windows 上发现了一个问题,其中 Golang 将字符解码为分解的 UTF-8字符(即它会读取一个ä
字符a
,然后是 COMBINING DIAERESIS ̈
),这可能会导致其他问题,例如打印这些分解的字符会将它们分开打印而不是一个组合字符。
- 1 回答
- 0 关注
- 146 浏览
添加回答
举报
0/150
提交
取消