如何在mingw中检测命令行参数的字符编码

假设他们是ISO-8859-15(Window-1252?)是否安全,还是有一些function可以打电话来查询? 最终目标是转换为UTF-8。


背景:

这个问题描述的问题出现了,因为XMLStarlet假定它的命令行参数是UTF-8。 在Windows下,似乎它们实际上是ISO-8859-15(Window-1252?),或者至less在main的开始部分添加以下内容:

 char **utf8argv = malloc(sizeof(char*) * (argc+1)); utf8argv[argc] = NULL; { iconv_t windows2utf8 = iconv_open("UTF-8", "ISO-8859-15"); int i; for (i = 0; i < argc; i++) { const char *arg = argv[i]; size_t len = strlen(arg); size_t outlen = len*2 + 1; char *utfarg = malloc(outlen); char *out = utfarg; size_t ret = iconv(windows2utf8, &arg, &len, &out, &outlen); if (ret < 0) { perror("iconv"); utf8argv[i] = NULL; continue; } out[0] = '\0'; utf8argv[i] = utfarg; } argv = utf8argv; } 

testing编码

以下程序以十进制打印出其第一个参数的字节:

 #include <strings.h> #include <stdio.h> int main(int argc, char *argv[]) { for (int i = 0; i < strlen(argv[1]); i++) { printf("%d ", (unsigned char) argv[1][i]); } printf("\n"); return 0; } 

chcp报告代码页850 ,所以字符æ和Æ应分别为145和146。

 C:\Users\npostavs\tmp>chcp Active code page: 850 

但是我们看到230和198报道了匹配1252 :

 C:\Users\npostavs\tmp>cmd-chars æÆ 230 198 

在代码页之外传递字符会导致有损转换

使用参数αβγ cmd-chars.exe一个到cmd-chars.exe的快捷方式(这些在代码页1252中不存在)给出

 C:\Users\npostavs\tmp>shortcut-cmd-chars.lnk 97 223 63 

哪一个是aß?

Solutions Collecting From Web of "如何在mingw中检测命令行参数的字符编码"

您可以调用CommandLineToArgvW ,并调用GetCommandLineW作为第一个参数,以在宽字符串的argv样式数组中获取命令行参数。 这是唯一可移植的Windows方式,特别是在代码页混乱的情况下; 例如,日语字符可以通过Windows快捷方式传递。 之后,可以使用WideCharToMultiByte和CP_UTF8的代码页参数将每个宽字符的argv元素转换为UTF-8。

请注意,调用WideCharToMultiByte (输出缓冲区大小(字节数)为0)将允许您确定指定字符数所需的UTF-8字节数(或者,如果您希望通过的话,包括空终止符的整个宽字符串 – 1作为宽字符的数量来简化你的代码)。 然后你可以使用malloc等分配所需的字节数。 并重新调用WideCharToMultiByte正确的字节数,而不是0.如果这是性能关键,一个不同的解决方案可能是最好的,但因为这是一个获取命令行参数的一次函数,我会说任何性能下降可以忽略不计。

当然,不要忘记释放所有的内存,包括用CommandLineToArgvW返回的指针作为参数来调用LocalFree

有关功能以及如何使用它们的更多信息,请单击链接以查看MSDN文档。

命令行参数位于系统默认的代码页中,这取决于系统设置。 可以指定"char""" ,而不是指定一个特定的源字符集,让iconv_open()找出系统字符集实际上是什么:

 iconv_t windows2utf8 = iconv_open("UTF-8", "char"); 

否则,您最好将命令行作为UTF-16而不是Ansi来检索,然后使用iconv_open("UTF-8", "UTF-16LE")WideCharToMultiByte(CP_UTF8) iconv_open("UTF-8", "UTF-16LE")来将其直接转换为UTF- WideCharToMultiByte(CP_UTF8)就像Chrono建议的那样。

看来你在窗户下。

在这种情况下,您可以调用system()来运行CHCP命令。

  #include <stdlib.h> // Uses: system() #include <stdio.h> // ..... // 1st: Store the present windows codepage in a text file: system("CMD /C \"CHCP > myenc.txt\""); // 2nd: Read the first line in the file: FILE *F = fopen("myenc.txt", "r"); char buffer[100]; fgets(buffer, F); fclose(F); // 3rd: Analyze the loaded string to find the Windows codepage: int codepage = my_CHCP_analizer_func(buffer); // The function my_CHCP_analizer_func() must be written for you, // and it has to take in account the way in that CHCP prints the information. 

最后,CHCP发送的密码可以在这里查看:

Windows代码页