2

私のプログラムstat()が特定の UTF-8 文字を含むファイルにアクセスしようとすると、stat()関数はエラーを返します。たとえば、/tmp/surgateDlpMgQure/Özkul Gazetevi でファイルを開くことはできますが、この同じファイルを に渡すとstat()エラーが発生します。システム ロケール設定は次のとおりです。

LANG=en_US.UTF-8

LC_CTYPE="en_US.UTF-8"

LC_COLLATE=C

LC_TIME="en_US.UTF-8"

LC_NUMERIC="en_US.UTF-8"

LC_MONETARY="en_US.UTF-8"

LC_MESSAGES="en_US.UTF-8"

LC_ALL=

stat()UTF-8 文字を理解するために何かをする必要がありますか?

コードは次のとおりです。

int main ()
{
    struct stat s;
    if (stat("/tmp/surgateDlpMgQure/Özkul Gazete", &s) == -1)
            perror("stat");


    switch (s.st_mode & S_IFMT) {
            case S_IFBLK:  printf("block device\n");            break;
            case S_IFCHR:  printf("character device\n");        break;
            case S_IFDIR:  printf("directory\n");               break;
            case S_IFIFO:  printf("FIFO/pipe\n");               break;
            case S_IFLNK:  printf("symlink\n");                 break;
            case S_IFREG:  printf("regular file\n");            break;
            case S_IFSOCK: printf("socket\n");                  break;
            default:       printf("unknown?\n");                break;
    }

 return 0;
}
4

3 に答える 3

0

問題はおそらく、ファイル名のエンコーディングが、プログラムの内部で使用しているエンコーディングと同じではないことです。ここでの重要な質問は、誰がファイルを作成したか(そしてこの名前を付けたのか)、そしてコード内の文字列がどこから来たのかです。'/'Unixのほとんどは、のようないくつかの特殊文字が期待されるエンコーディングを持っている限り、エンコーディングに関して不可知論者 です。したがって、現在のロケールに関係なく、ファイル名はLatin-1、Latin-5(推測ですが、名前はトルコ語に見えます)またはUTF-8にすることができます。Unixでは実質的に何も気にしませんが、あなたはプログラムで、ファイルの作成に使用されたものと同じエンコーディングを使用していることを確認する必要があります。そうしないと、名前が一致しません。(実際には、ファイル名の文字を非常に小さなセット(ASCII英数字、数字、 '_'場合によっては)に制限するのが最も簡単なポリシーであることがわかりました'-'。)

ディスク上のファイル名の実際のエンコーディングがわからない場合は、ls | od -t x1 -tcその中のバイトの実際の値を調べるために使用できます。が0xD6の場合Ö、エンコーディングはLatin-1またはLatin-5のいずれかであり(おそらくどちらでも大きな違いはありません)、渡すファイル名stat(またはopen、またはその他の関数)を確認する必要があります。ファイル名を取ります)は、これらのエンコーディングの1つでエンコードされます。代わりに、2バイトシーケンス0xC3、0x96がある場合、ファイル名はUTF-8です。

ASCIIサブセット以外の文字をサポートしたい場合は、すべてのファイル名がUTF-8でエンコードされていることを確認することを強くお勧めします。可能だとすると、エンコーディングはファイルを作成するプログラムによって決定され、それが自分のプログラムでない場合(または別のシステムからファイルを受信して​​いる場合)、それについて何もできない可能性があります。最悪のシナリオでは、実際のファイル名(エンコーディングに関係なく)を見つけてそれを使用するためopendirに、ある種のマッチングアルゴリズムを使用する必要がある場合もあります。readdir

于 2012-08-08T08:40:08.960 に答える
0

そのファイル名の名前のスペースが原因で問題があると思います...

スペースなしでそのファイル名を変更してみてください

Özkul Gazete  -> Özkul_Gazete

Linuxでは通常、ファイル名やディレクトリ名にスペースを使用しません

于 2012-08-08T08:42:09.040 に答える
-1

それをハックする簡単な方法:

その Unicode 文字のエスケープ表現を使用します。

"/tmp/surgateDlpMgQure/\x00\xF6zkul Gazete"

私はテストしませんでしたが、うまくいくでしょう。ただし、C で Unicode 文字列を使用する方法ではありません。

奇妙なことに、あなたのコードは私のシステムでは機能しますが、私のシステムでは機能しません:)

于 2012-08-08T08:31:30.437 に答える