久しぶりに投稿します。
OS:WinXP Pro SP2
VS2005, VC++ MFC
プロジェクトのプロパティ[文字セット] ⇒ マルチ バイト文字セットを使用する
Frameworkは使用しません。
タブ区切りのCSVを1行ずつ読込み分割して処理を行おうと思い、
ReadStringを使用しました。
簡単なプログラムと思っていたのですがCSVが「Unicode(UTF-16LE)、改行コードCRLF」
可変長で、ReadStringはSJIS前提という情報を見かけたのと1行分正確に読込まれないためfgetsに切替えました。
CSVの内容は以下のようなものです。
ああああ[TAB]いいいい[TAB]うううう[CRLF]
123ああ[TAB]4いい[TAB]5うう[CRLF]
abcd[TAB]efg[TAB]hijklm[CRLF]
・
・
(コード)
CString strResult = ""; // 1行格納用
CString strBPath = "xxxx.csv";
int nLen;
fopen_s(&fp, strBPath, "rb");
if(fp == NULL)
return;
while (1) {
TCHAR buf[1000] = {0};
if (fgets(buf, sizeof(buf), fp) == NULL)
break;
strResult = buf;
nLen = strResult.GetLength();
}
(Unicode(UTF-16LE)、改行コードCRLF)CSV
1行目nLen:11
正解はBOM+で[30]でしょうか?
(同じ内容のSJIS、改行コードCRLF)CSV
1行目nLen:28
となります。
1.「Unicode(UTF-16LE)、改行コードCRLF」の1行を読込む方法を教えてください。
2.読込み(ワイド文字列として?)後、手動でBOMを削除し、wcstombs、WideCharToMultiByte等
で変換する、でしょうか?
3.読込み後、手動で上位バイト、下位バイトの入替が必要ですか?
4.一発変換関数(たぶん、1行読込み成功後になるのでしょうが)とかご存知ありませんか?
以上、欲張りな質問になりましたが、よろしくお願いします。
matsuです。
いつも投稿後に進展があります。すみません。
まず、先頭に
setlocale(LC_CTYPE, "jpn");
を追加しました。
> fopen_s(&fp, strBPath, "rb");
fopen_s(&fp, strBPath, "rb, ccs=UNICODE");
に変更。
> TCHAR buf[1000] = {0};
WCHAR buf[1000] = {0};
に変更。
な、な、なんと正常に読込みができました。
1.2.3.4.が一気に解決しました。
お騒がせしました。
ただ、先の質問とは異なる気になる点がありまして
1.読込む前にサイズを指定しますがCSVは可変長なので予測される最大値
ということになるのでしょうか?
サイズオーバー時はオーバー分は切捨てられますよね?
2.strResult = buf;は問題ないでしょうか?
コンパイルも通りますし、メッセージボックスでも正常に表示されます。
よろしくお願いします。
あ、あと「BOMの処理は自前で」ですね?
すみません、書き忘れました。
fgets ⇒ fgetws
にしました。
>可変長で、ReadStringはSJIS前提という情報を見かけたのと1行分正確に読込まれないためfgetsに切替えました。
LPTSTR を引数に持つぐらいなので対応してるのでは?
http://homepage3.nifty.com/aokura/tips/edit6.html
で、
>CStdioFile クラスのソースをみると、ReadString, WriteString 関数はそれぞれ C ランタイムの fgetws, fputws 関数を使って実装されており、現在のロケールの LC_CTYPE カテゴリに依存して動作することが分かります。
とあるのでReadStringでも動きそうな気がします。
ツイート | ![]() |