Unicodeテキストファイルの読み込み方

[戻る]
24 2004/10/31(日) 09:51:51
環境:VC++6.0,WinXP

こんにちは、24と申します。
コンソールアプリケーションで、
Unicodeテキストで保存したファイルを読み込むのですが、
MSDNライブラリで書かれている設定をし、
実行しても、main関数へ飛びません。Unicodeを使う場合は、
mainがwmain()になると書かれていたので、それも試しましたが、
やはり飛びません。

[リンク]パネルの [カテゴリ] ボックスから [アウトプット] をクリックして、[エント
リ ポイント シンボル] ボックスに wWinMainCRTStartup を入力という設定が
あるのですが、これを入力すると、飛ばなくなります。はずすと飛ぶのですが、
Unicodeの文字列が化けます。

どういったことが原因か分かる方いましたら、宜しくお願いいたします。

YMF 2004/10/31(日) 23:35:18
基本的に、Unicode テキストファイルを読み書きするのと、
_UNICODE を定義してプログラムをビルドするのとは別の話と思います。

例えば、テキストモード指定で開いたファイルから fgetws() で
1行読み出しを実行した場合、_UNICODE/_MBCS の指定に関わらず
ファイル内容はマルチバイト文字からワイド文字に変換されて読み込まれます。
(テキストモードならファイル内容は無条件にマルチバイトとして扱われる)
バイナリモード指定で開いたファイルからなら、_UNICODE/_MBCS の指定に関わらず
無変換でワイド文字列の中にデータが読み込まれます。

>MSDNライブラリで書かれている設定をし、
>実行しても、main関数へ飛びません。Unicodeを使う場合は、
>mainがwmain()になると書かれていたので、それも試しましたが、
>やはり飛びません。

コンソールアプリでのプログラムのエントリポイントは、
mainCRTStartup または wmainCRTStartup であって、
リンカは main 関数に対しては mainCRTStartup を、
wmain 関数に対しては wmainCRTStartup を自動的に割り当ててくれるんじゃ
なかったかと。

>[リンク]パネルの [カテゴリ] ボックスから [アウトプット] をクリックして、[エン>リ ポイント シンボル] ボックスに wWinMainCRTStartup を入力という設定が
>あるのですが、これを入力すると、飛ばなくなります。はずすと飛ぶのですが、
>Unicodeの文字列が化けます。

wWinMainCRTStartup は GUI アプリの wWinMain 関数用のエントリポイントです。
文字が化ける件は、実際にどのように読み書きしているかを見ないとわかりません。

24 2004/11/01(月) 10:07:26
YMFさま、わかり易く丁寧なお返事ありがとうございます。
とっても勉強になりました。
wWinMainCRTStartupと設定していたのをwMainCRTStartupと
変更したら、wmain()内に入れました。
ずっとwWinMain〜で検索していました。

ファイルのOpen-Read-CloseはCStdioFileとCString型を使っています。

下記がそのソースなのですが、Unicodeではないテキストファイルは
文字列が取れますが、Unicodeモードだと文字列が取れませんん。
変換の仕方がおかしいのでしょうか・・・

-------------------------------------------------------------------------
タブ区切りのテキストファイル(Unicode)の最初の2列を他のテキストに、
残りの列を別のテキストに分ける
-------------------------------------------------------------------------

int TextFile(){
  int    i,j;
  int    pos;
   CString lineBuf1;    // 各行の文字列(Jp)
   CString lineBuf2;    // 各行の文字列(Eu)
   CString    localStr[6+1];
   CStdioFile    file_Unicode;
   CStdioFile    file_Unicode_jp;
   CStdioFile  file_Unicode_eu;
   CString    fileName = DestDir + sourceFileName;

   if( file_Unicode_jp.Open
(DestDir+createFileName_jp,CFile::modeCreate|CFile::modeWrite) == 0 )
        return 0;
    if( file_Unicode_eu.Open
(DestDir+createFileName_eu,CFile::modeCreate|CFile::modeWrite) == 0 )
        return 0;
    file_Unicode.Open(fileName,CFile::modeRead);

    for(i=0;i<LINE_MAX;i++ ){
        if( file_Unicode.ReadString( lineBuf1 ) == FALSE ){
             break;
        }
        else{
           for( j=0;j<1+1;j++){
               pos=lineBuf1.Find(_T('\t'));
               if( pos == -1 ){
            localStr[j] = lineBuf1;
            break;
               }
               localStr[j] = lineBuf1.Left(pos);
               file_Unicode_jp.WriteString(localStr[j] + _T("\t"));
               lineBuf1.Delete(0,pos+1);
           }
           file_Unicode_jp.WriteString(_T("\n"));
           if(i == 0){
           file_Unicode_eu.WriteString(_T("//"));
           }
           for( int m=j;m<5+1;m++){
              pos=lineBuf1.Find(_T('\t'));
              if( pos == -1 ){
              localStr[m] = lineBuf1;
              break;
           }
           localStr[m] = lineBuf1.Left(pos);
           file_Unicode_eu.WriteString(localStr[m] + _T("\t"));
           lineBuf1.Delete(0,pos+1);
        }
            file_Unicode_eu.WriteString(_T("\n"));
    }
   }
    file_Unicode.Close();
    file_Unicode_jp.Close();
    file_Unicode_eu.Close();
    return 0;
}

YMF 2004/11/01(月) 11:27:38
以下のようなコードで試してみてください。

  setlocale(LC_CTYPE, "jpn"); // _putts() で日本語表示のために必要

  CString str;
  CStdioFile file;
  if (file.Open(_T("Unicode.txt"), CFile::modeRead | CFile::typeBinary))
  {
    while (file.ReadString(str))
      _putts(str);
  }

24 2004/11/01(月) 13:22:04
YMFさま、教えていただいたとおりにやりましたら、
きちんと表示できました。
本当に、勉強になります、ありがとうございます。

このような定義があるんですね!!
のちのち、UnicodeのファイルはSJISと西ヨーロッパ言語の
テキストに変換されます。

MSDNで見たところ、「ワイド文字の定数やリテラル文字列を翻訳するときに
使用するロケール (国と言語) を定義します。」となっているので、
setlocale(LC_CTYPE, "jpn");ともうひとつ、
西ヨーロッパの2つを用意したほうがいいのでしょうか。

24 2004/11/02(火) 09:41:02
[[解決]]
ご教授いただいたYMFさま、本当にありがとうございました。

古いスレッドには追加発言できません。