当前位置: 首页 > 面试题库 >

argv的编码是什么?

诸经略
2023-03-14
问题内容

我不清楚在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编码,但是
文件名将采用L1编码 。因此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用来更改您的语言环境。


问题答案:

感谢大家的回应。我已经了解了很多有关此问题的知识,并发现了以下解决了我问题的方法:

  1. 如前所述,在Windows上,argv使用当前代码页进行编码。但是,您可以使用GetCommandLineW将命令行检索为UTF-16。不建议在支持unicode的现代Windows应用程序中使用argv,因为不建议使用代码页。

  2. 在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。

  • 问题内容: UTF-8是Java中的默认编码吗? 如果没有,我怎么知道默认使用哪种编码? 问题答案: JVM的默认字符集是运行它的系统的默认字符集。对此没有特定的值,并且通常不应将默认编码视为任何特定的值。 可以在运行时通过对其进行访问,尽管这对你有用,但实际上你应该始终在明确指定编码的情况下这样做。

  • 问题内容: 我实际上对Java中字符串的编码感到困惑。我有一些问题。如果您知道答案,请帮助我: 1)内存中Java字符串的本地编码是什么?当我以哪种格式书写时,它将被存储?由于Java与机器无关,因此我认为系统不会进行编码。 2)我在网上读到“ UTF-16”是默认编码,但我感到困惑,因为我写的时候说我得到了ASCII表中的字符编号。那么ASCII和UTF-16是否相同? 3)另外,我不确定字符串

  • 我正在做一个测试,Firefox如何编码字符。 但事实让我困惑。 超文本标记语言代码: xxx是一些汉字。这些字符必须编码成%xx等格式才能通过HTTP传输。 首先,我用UTF-8编码源文件。使用firefox打开html文件。img标签将发送一个请求,“xxx”字符由UTF8编码。 (用UTF8编码HTML源文件,字符集=UTF8,浏览器用UTF编码URL) 我把meta改成了

  • 我试图理解Scala代码如何在Java的IDE中与Java一起工作。我在使用Spark Java时遇到了这个疑问,在Spark Java中,我看到Scala包也在代码中,并且使用了相应的类和方法。 我的理解是,Scala代码需要Scala的编译器转换成Java.class文件,然后从它们开始JDK在JVM中完成它的部分,转换成二进制文件并执行操作。如果我说错了,请指正。 之后,在eclipse中的