2012-02-02 7 views
1

Macでpopen()コマンドを使用してファイルに対してプログラムを実行しようとしています。このため、私は<path-to_executable> <path-to-file>という形式のコマンドを作成し、このコマンドでpopen()を呼び出します。今のところ、これら2つのコンポーネントは両方ともchar *で宣言されています。私はpopen()によって与えられたパイプが必要なので、コマンドの出力を読む必要があります。Mac上の中国語のコマンドでpopen()を呼び出す

これで、パスツーファイルには中国語、日本語、ロシア語、その他の文字を含めることができました。このために、私はwchar_t *としてファイルへのパスを表すことができます。明らかにMac/LinuxにはWindowsのような幅広い_wpopen()がないので、これはpopen()では機能しません。

私はこの作業を行うことができます他の方法はありますか?私はwchar_t *だけを与えることができるデータ構造からファイルへのパスを取得しているので、必要に応じてそこから取り出して適切に変換する必要があります。

ありがとうございます。

編集:

あなたは自分の髪を引っ張ってしまう当時の1のように思えます。

私はwcstombsを使ってみましたが、 "C.UTF-8"とその置換のいずれかでsetlocale呼び出しが失敗しました。当然のことながら、wcstombs呼び出しは-1を返して失敗しました。

次に、Googleで検索したサンプルコードに基づいて独自のiconv実装を作成しようとしました。私は頑固に働くことを拒否され、この思い付いた:

iconv_t cd = iconv_open("UTF-8", "WCHAR_T"); 
// error checking here 

wchar_t* inbuf = ...; // get wchar_t* here 
char outbuf[<size-of-inbuf>*4+1]; 

size_t inlen = <size-of-inbuf>; 
size_t outlen = <size-of-inbuf>*4+1; 

char* c_inbuf = (char*) inbuf; 
char* c_outbuf = outbuf; 

int ret = iconv(cd, &c_inbuf, &inlen, &c_outbuf, &outlen); 
// more error checking here 

のiconvは常に-1を返し、errnoがEINVALに設定されています。 <size-of-len>が正しく設定されていることを確認しました。なぜ私はこのコードが今失敗したのか分からない。

編集2:私は、入力バッファの長さを右に設定されなかったため

のiconvは失敗しました。また、Macは「WCHAR_T」エンコーディングをサポートしていないようですので、UTF-16に変更しました。今では長さを修正し、エンコードから変更しましたが、iconvは文字を変換せずに戻ります。

この問題をデバッグするために、入力文字列を一時文字列に変更し、入力の長さを適切に設定することさえできました。でもこれのiconvコールは今0.私のコードを返すようになっています。私は、コンバータの記述が正しく開かれていることを確認しました

iconv_t cd = iconv_open("UTF-8", "UTF-16"); 
// error checking here 

wchar_t* inbuf = ...; // get wchar_t* here - guaranteed to be UTF-16 
char outbuf[<size-of-inbuf>*4+1]; 

size_t inlen = <size-of-inbuf>; 
size_t outlen = <size-of-inbuf>*4+1; 

char* c_inbuf = "abc"; // (char*) inbuf; 
inlen = 4; 
char* c_outbuf = outbuf; 

int ret = iconv(cd, &c_inbuf, &inlen, &c_outbuf, &outlen); 
// more error checking here 

。 from-encodingは正しいです。入力バッファにはいくつかの単純な文字が含まれています。すべてがハードコードされていますが、iconvは文字を変換せず、単に0を返し、outbufは空のままです。

サニタリーアラート!

+0

Mac OSのファイル名はUTF-8でエンコードされているため、使用する必要があります。 – zneak

答えて

1

popenのUTF-8文字列が必要です。そのため、iconvを使用して、ローカルのwchar_tエンコーディングからUTF-8に変換するなど、さまざまなエンコーディング間で変換できます。 EDIT

wchar_tは実際に32ビットではなく、16で、Mac OSのインストール私の上のことに注意してください)ここではOS Xのライオンに取り組んでいます例です。wchar_tエンコーディングを使用しても問題は発生しませんでした(詳細はiconvのマニュアルページに記載されています)。

#include <sys/param.h> 
#include <string.h> 
#include <iconv.h> 
#include <stdio.h> 
#include <errno.h> 

char* utf8path(const wchar_t* wchar, size_t utf32_bytes) 
{ 
    char result_buffer[MAXPATHLEN]; 

    iconv_t converter = iconv_open("UTF-8", "wchar_t"); 

    char* result = result_buffer; 
    char* input = (char*)wchar; 
    size_t output_available_size = sizeof result_buffer; 
    size_t input_available_size = utf32_bytes; 
    size_t result_code = iconv(converter, &input, &input_available_size, &result, &output_available_size); 
    if (result_code == -1) 
    { 
     perror("iconv"); 
     return NULL; 
    } 
    iconv_close(converter); 

    return strdup(result_buffer); 
} 

int main() 
{ 
    wchar_t hello_world[] = L"/éè/path/to/hello/world.txt"; 

    char* utf8 = utf8path(hello_world, sizeof hello_world); 
    printf("%s\n", utf8); 
    free(utf8); 
    return 0; 
} 

utf8_hello_world関数は、バイト長wchar_t文字列を受け取り、等価なUTF-8文字列を返します。 wchar_tの代わりにwchar_tのポインタを処理する場合は、sizeofの代わりに(wcslen(ptr) + 1) * sizeof(wchar_t)を使用します。

+0

iconvの評判については、実装するのが面倒だと読んでいます。今はそれにふさわしいと分かっています。 – Sameer

+0

@Sameer、実装するのは厄介で使いにくいですか?周りを見回すと、それは十分に単純に見えます。私はそれを使用して事例を投稿できるかどうかを見ていきます。 – zneak

+0

ありがとうございました。ほんとうにありがとう。 私はあなたのコードを試してみましたが、結果はここにあります。 iconv_openのfromEncodingに対してwchar_tを使用するか、UTF-32を使用する場合は、「無効なバイトシーケンス」でiconvエラーが発生します。実際に間違っているUTF-16を使用すると、iconvは正常に実行されますが、0バイトが変換されます。あなたが言ったように、私は10.6 Macをチェックし、wchar_tは32ビットです。 私は何かを見つけたときにこれを調べて更新します。再度、感謝します! – Sameer

0

Mac OS XはUTF-8を使用しているため、ワイド文字列をUTF-8に変換する必要があります。最初にUTF-8ロケールに切り替える場合は、wcstombsを使用してこれを行うことができます。たとえば:あなたはあなたのプログラムのロケール設定を変更したくない場合は

// Do this once at program startup 
setlocale(LC_ALL, "en_US.UTF-8"); 
... 
// Error checking omitted for expository purposes 
wchar_t *wideFilename = ...; // This comes from wherever 
char filename[256]; // Make sure this buffer is big enough! 
wcstombs(filename, wideFilename, sizeof(filename)); 
// Construct popen command using the UTF-8 filename 

また、あなたのためにUTF-8変換にUTF-16を行うためにlibiconvを使用することができます。変換を行うのはそれほど複雑ではないので、独自の実装をロールバックすることもできます。

+0

wcstombsがマルチバイト文字を必要に応じて2バイトまたは3バイトに分割すると思うので、ファイル名には(length of wideFilename)x 3で十分ですか? – Sameer

+0

いいえ、各ワイド文字がUTF-8で最大4バイト、NULターミネータで1にデコードされる可能性があるため、少なくとも((length of wideFilename)* 4 + 1)必要です。 –

+0

setlocale(LC_ALL、 "C.UTF-8")呼び出しが失敗する理由は何ですか? wcstombs呼び出しも失敗する原因になります。 – Sameer

関連する問題