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

我来自德国,所以我使用变音符号,如ä,ö和ü. 然而,Golang 不能从标准输入正确读取它们。


当我执行这个简单的程序时:


package main


import (

    "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 0x9E

E2 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 0xA

C3 A4是正确的字节序列ä(0A 是我的 hack 没有剥离的换行符)所以看起来,从 CP850 读取和转换为 UTF-8 完成了这项工作,正如我所料,但是为什么 Go 会给我胡言乱语当我使用 Go 的功能而不是 cgo 读取该行?Go 有什么问题,它给了我这些值,它不是将输入字节解释为 CP850 而是另一个字符集?有没有更好的 Go-only 方法来处理这个问题?


此问题仅在从标准输入读取时出现。当我将 UTF-8ä打印到标准输出时,它会在控制台中正确打印。


qq_遁去的一_1
浏览 147回答 1
1回答

慕姐4208626

因此,对于某些系统来说,这是 Golang 中的一个错误,特别是针对整体使用的字符集和控制台字符集不同的 Windows 系统(WinAPI 从哪里返回不同的东西)GetACP()。GetConsoleCP()例如,在德国(可能还有其他西欧国家),Windows 使用代码页 1252 作为整体字符集,但它使用代码页 850 作为控制台cmd.exe。不知道为什么,但就是这样。Golang 错误地用于GetACP()将输入解码为 UTF-8,而它确实应该使用GetConsoleCP().&nbsp;我们在我创建的问题中发现了问题,我们希望看到该修复合并到 Golang 的下一个版本中。我们还在 Windows 上发现了一个问题,其中 Golang 将字符解码为分解的 UTF-8字符(即它会读取一个ä字符a,然后是 COMBINING DIAERESIS&nbsp;̈),这可能会导致其他问题,例如打印这些分解的字符会将它们分开打印而不是一个组合字符。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go