argv的编码是什么?
我不清楚在C的何处使用什么编码argv
。我特别对以下情况感兴趣:
- 用户使用语言环境L1创建名称为
N
包含非ASCII字符的文件 - 稍后,用户使用区域设置L2在命令行上制表完成该文件的名称,该文件作为命令行参数输入到程序P中
P在命令行上看到什么字节序列?
我观察到在Linux上,在UTF-8语言环境中创建文件名,然后在(例如)zw_TW.big5
语言环境中用Tab键完成该文件名似乎会使我的程序P喂UTF-8而不是UTF-8
Big5
。但是,在OS X上,相同的一系列操作导致我的程序P获得Big5
编码的文件名。
这是到目前为止我一直在想的事情(很长,我可能错了,需要纠正):
视窗
文件名以某种Unicode格式存储在磁盘上。因此Windows以这个名称命名N
,从L1(当前代码页)转换为N
我们将称为的Unicode版本N1
,并存储N1
在磁盘上。
然后,我 假设
发生的事情是,稍后稍后使用制表符补全时,该名称N1
将转换为语言环境L2(新的当前代码页)以进行显示。运气好的话,这将产生原始名称N
-但是,如果其中N
包含L2中无法表示的字符,则该名称将不成立。我们叫新名字N2
。
当用户实际按下Enter键以使用该参数运行P时,该名称N2
将转换回Unicode,N1
再次产生。这N1
是通过在UCS2格式现在可供程序GetCommandLineW
/
wmain
/ tmain
,但用户GetCommandLine
/ main
会看到的名称N2
在当前区域设置(代码页)。
OS X
据我所知,磁盘存储的故事是相同的。OS X将文件名存储为Unicode。
对于Unicode终端,我 认为
发生的事情是该终端在Unicode缓冲区中构建了命令行。因此,完成制表符后,它会将文件名作为Unicode文件名复制到该缓冲区。
当您运行命令时,该Unicode缓冲区将转换为当前语言环境L2,并通过馈入程序argv
,并且程序可以将具有当前语言环境的argv解码为Unicode以显示。
的Linux
在Linux上,一切都不同,我对正在发生的事情感到困惑。Linux将文件名存储为 字节字符串
,而不是Unicode。因此,如果您N
在区域设置L1中创建名称为文件的文件,则该文件N
作为字节字符串存储在磁盘上。
当我稍后运行终端并尝试用Tab键完成名称时,我不确定会发生什么。在我看来,命令行被构造为字节缓冲区,而文件名
被串联到该缓冲区上。我假设当您键入标准字符时,它会即时编码为附加到该缓冲区的字节。
当您运行程序时,我认为缓冲区直接发送到argv
。现在,有什么编码argv
?在语言环境L2中,您在命令行中键入的任何字符看起来都将采用L2编码,但是
。因此argv
包含两种编码的混合!
题
如果有人能让我知道这里发生了什么,我真的很喜欢。我目前所拥有的只是半猜测和猜测,而且并不能真正融合在一起。我真正想要成为现实的是要argv
在当前代码页(Windows)或当前语言环境(Linux
/ OS X)中进行编码,但事实并非如此……
附加功能
这是一个简单的候选程序P,它使您可以自己观察编码:
#include <stdio.h>int main(int argc, char **argv)
{
if (argc < 2) {
printf("Not enough arguments\n");
return 1;
}
int len = 0;
for (char *c = argv[1]; *c; c++, len++) {
printf("%d ", (int)(*c));
}
printf("\nLength: %d\n", len);
return 0;
}
您可以locale -a
用来查看可用的语言环境,也可以export LC_ALL=my_encoding
用来更改您的语言环境。
回答:
感谢大家的回应。我已经了解了很多有关此问题的知识,并发现了以下解决了我问题的方法:
如前所述,在Windows上,argv使用当前代码页进行编码。但是,您可以使用GetCommandLineW将命令行检索为UTF-16。不建议在支持unicode的现代Windows应用程序中使用argv,因为不建议使用代码页。
在Unixes上,argv没有固定的编码:
a)通过制表符补全/通配符插入的文件名将在argv 逐字 出现,恰好是它们在磁盘上被命名的字节序列。即使这些字节序列在当前语言环境中没有意义,也是这样。
b)用户使用其IME直接输入的输入将以区域设置编码在argv中出现。(Ubuntu似乎使用LOCALE来决定如何对IME输入进行编码,而OS
X使用Terminal.app编码首选项。)
对于想要将命令行参数视为字符串的语言,例如Python,Haskell或Java,这很烦人。他们需要决定如何解码argv
为内部使用的任何编码String
(对于这些语言,编码为UTF-16)。但是,如果他们只是使用语言环境编码来执行此解码,则输入中的有效文件名可能无法解码,从而导致异常。
Python
3采用的解决此问题的方法是代理字节编码方案(http://www.python.org/dev/peps/pep-0383/),该方案将argv中任何不可解码的字节表示为特殊的Unicode代码点。当该代码点被解码回字节流时,它再次变成原始字节。这允许通过本地Python字符串类型将来自argv的在当前编码中无效的数据(即,以当前语言环境以外的名称命名的文件名)通过本机Python字符串类型往返,并返回到字节,而不会丢失信息。
如您所见,情况非常混乱:-)
以上是 argv的编码是什么? 的全部内容, 来源链接: utcz.com/qa/401336.html