Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Golang stdin看错了德文字母_Go_Character Encoding - Fatal编程技术网

Golang stdin看错了德文字母

Golang stdin看错了德文字母,go,character-encoding,Go,Character Encoding,我来自德国,所以我使用umlauts,比如ä,ö和ü。然而,Golang并没有从stdin中正确读取它们 当我执行这个简单的程序时: package main import ( "bufio" "fmt" "os" ) func main() { for { b, _, _ := bufio.NewReader(os.Stdin).ReadLine() printBytes(b) } } func printByte

我来自德国,所以我使用umlauts,比如
ä
ö
ü
。然而,Golang并没有从stdin中正确读取它们

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

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()
}
c3a4
ä
的正确字节顺序(0A是我的黑客没有剥去的换行符)看起来,从CP850到UTF-8的读取和转换就像我预期的那样,但是当我使用Go的功能而不是cgo来读取行时,为什么Go会给我胡言乱语?Go给我这些值有什么问题,它不是将输入字节解释为CP850而是另一个字符集吗?有更好的Go-only方法来处理这个问题吗有问题吗


这个问题只有在读取stdin时才会出现。当我将UTF-8
ä
打印到stdout时,它会在控制台中正确打印。

因此,对于某些系统来说,这是Golang中的一个bug,特别是对于Windows系统,在这些系统中,使用的总字符集和控制台字符集是不同的(其中
GetACP()
GetConsoleCP()
从WinAPI返回了不同的东西)。例如,在德国(可能还有其他西欧国家),Windows使用代码页1252作为整个字符集,但它使用代码页850作为控制台
cmd.exe
。不确定原因,但就是这样。Golang错误地使用了
GetACP()
对UTF-8的输入进行解码,而UTF-8本应使用
GetConsoleCP()
返回的代码页。我们在我创建的代码中发现了问题,希望下一版本的Golang能够合并修复程序


我们还发现,在Golang将字符解码为分解的UTF-8字符的窗口上存在一个问题(即,Golang将a
ä
读取到字符
a
,然后再进行组合分解
)这可能会导致其他问题,例如打印这些分解的字符会将它们打印为单独的字符,而不是一个组合字符。

因此,对于某些系统来说,Golang中存在一个bug,具体来说,对于Windows系统来说,使用的总字符集和控制台字符集是不同的(其中
GetACP()
GetConsoleCP()
从WinAPI返回了不同的内容)。例如,在德国(可能还有其他西欧国家),Windows使用代码页1252作为整个字符集,但它使用代码页850作为控制台
cmd.exe
。不确定原因,但就是这样。Golang错误地使用了
GetACP()
对UTF-8的输入进行解码,而UTF-8本应使用
GetConsoleCP()
返回的代码页。我们在我创建的代码中发现了问题,希望下一版本的Golang能够合并修复程序


我们还发现,在Golang将字符解码为分解的UTF-8字符的窗口上存在一个问题(即,Golang将a
ä
读取到字符
a
,然后再进行组合分解
)这可能会导致其他问题,例如打印这些分解的字符会将它们分开打印,而不是打印一个组合字符。

您没有回答自己的问题吗?Go默认采用UTF8,并且您正在输入CP850Go,如果从终端(cmd.exe)运行,则其源代码中的字符串将采用UTF-8它不应该正确读取stdin并从终端代码页转换为UTF-8吗?即使Go希望从控制台获得UTF-8,这也不能解释为什么我得到一个完全不相关的UTF-8字符,而不仅仅是错误符文。即使我直接从stdin读取字节,我也会收到这三个字节,而控制台肯定不会将其作为我的C-fu发送nction正确接收
ä
的CP850值。因为Golang将输入解释为代码页1252,而不是850,即使控制台使用850。您没有回答自己的问题吗?Go默认采用UTF8,您输入的CP850Go在其源代码中对字符串采用UTF-8,但如果从终端(cmd.exe)运行它不应该正确读取stdin并从终端代码页转换为UTF-8吗?即使Go希望从控制台获得UTF-8,这也不能解释为什么我得到一个完全不相关的UTF-8字符,而不仅仅是错误符文。即使我直接从stdin读取字节,我也会收到这三个字节,而控制台肯定不会将其作为我的C-fu发送nction正确接收
ä
的CP850值,因为Golang将输入解释为代码页1252而不是850,即使控制台使用850。
C:\dev\golang>go run test.go
ä
0xC3 0xA4 0xA