为了账号安全,请及时绑定邮箱和手机立即绑定

Golang stdin 读取德语变音符号错误

Golang stdin 读取德语变音符号错误

Go
qq_遁去的一_1 2022-03-03 15:01:01
我来自德国,所以我使用变音符号,如ä,ö和ü. 然而,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 ̈),这可能会导致其他问题,例如打印这些分解的字符会将它们分开打印而不是一个组合字符。


查看完整回答
反对 回复 2022-03-03
  • 1 回答
  • 0 关注
  • 146 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信