UNICODEテキストファイルにBOMを付ける方法 – プログラミング – Home

UNICODEテキストファイルにBOM...
 
通知
すべてクリア

[解決済] UNICODEテキストファイルにBOMを付ける方法


花の慶次
 花の慶次
(@花の慶次)
ゲスト
結合: 12年前
投稿: 4
Topic starter  

VS2010 MFC ダイアログベースアプリです。
コンマ区切りCSVファイルを出力するプログラムを作っています。
UNICODE文字を扱えるようにしたいので、プロジェクトは「UNICODE 文字セットを使用す
る」としています。
サンプルとして、次のコードを書きました。

void CCSVDlg::OnBnClickedButton1()
{
CString sData[] = {_T(いつやるか。), _T(今でしょ!), _T(あとで), _T
(やります。)};
CString sSave;
sSave = sData[0] + _T(,) + sData[1] + _T(\n);
sSave += sData[2] + _T(,) + sData[3] + _T(\n);
CFile f;
f.Open(_T(test1.csv), CFile::modeCreate | CFile::modeWrite);
f.Write(sSave, sSave.GetLength() * sizeof(TCHAR));
f.Close();
}

これで test1.csv というファイルが出来ます。
MIFESというテキストエディタで調べると、UTF-16のファイルとなっているようです。
しかし、このファイルをエクセルで開くと文字化けします。
エクセルで編集できるUNICODEファイルを出力したいのです。

調べたら、エクセルで開けるUNICODEのCSVファイルは、
①コンマ区切りではなく、タブ区切りであること。
②UTF-16 LE の BOM付きであること。
と解りました。

①は、前記の _T(,) を _T(\t) に置き換えました。
②は、ファイルの先頭に、0xFF 0xFE の2バイトを付ければいいらしいのですが、どの
ようにプログラムコードを書けばいいかが解りません。

どうぞご教授ください。よろしくお願いいたします。


引用未解決
トピックタグ
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 15年前
投稿: 64
 

> ①コンマ区切りではなく、タブ区切りであること。

この時点でCSVじゃなくなりますけど、かまわんのですか?

> ②は、ファイルの先頭に、0xFF 0xFE の2バイトを付ければいいらしいのですが

CString sSave = L\xFFFE;

sSave += sData[0] + _T(,) + sData[1] + _T(\n);

これじゃダメ?


返信引用
花の慶次
 花の慶次
(@花の慶次)
ゲスト
結合: 12年前
投稿: 4
Topic starter  

επιστημη様、有り難うございます。

> この時点でCSVじゃなくなりますけど、かまわんのですか?
はい、かまいません。

CString sSave = L\xFFFE;
sSave += sData[0] + _T(\t) + sData[1] + _T(\n);

これでやってみましたが、文字化けします。


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

エクセルのバージョンにもよるとは思いますが、

CSVとして完全に自動的に認識できるUnicodeは

 1.UTF-16LE タブ区切り

のようですね。ただし、

エクセルを開いてから読み込む場合で、ウィザードDLGが出ても良いのなら、

 2.UTF-8(BOM付き) (区切りはウィザードで設定する)

もOKのようですよ。

特にUnicodeにこだわらなければShift-JISが最も安全ですけどね。


返信引用
akey
 akey
(@akey)
ゲスト
結合: 22年前
投稿: 53
 

エンディアン的に逆ですかね
>CString sSave = L\xFFFE;
CString sSave = L\xFEFF;


返信引用
蒼の洞窟
 蒼の洞窟
(@蒼の洞窟)
ゲスト
結合: 12年前
投稿: 28
 

文字列に無理やりしないでバイトとして書き出したほうが簡明かも。

> f.Open(_T(test1.csv), CFile::modeCreate | CFile::modeWrite);
BYTE bom = {0xff, 0xfe};
f.Write(bom, sizeof(bom));
> f.Write(sSave, sSave.GetLength() * sizeof(TCHAR));
> f.Close();


返信引用
akey
 akey
(@akey)
ゲスト
結合: 22年前
投稿: 53
 

構文的に配列ですかね
>BYTE bom = {0xff, 0xfe};
BYTE bom[] = {0xff, 0xfe};


返信引用
蒼の洞窟
 蒼の洞窟
(@蒼の洞窟)
ゲスト
結合: 12年前
投稿: 28
 

>akeyさん
普通に間違えてましたorz

ご指摘感謝します。


返信引用
花の慶次
 花の慶次
(@花の慶次)
ゲスト
結合: 12年前
投稿: 4
Topic starter  

出来ました。

CString sData[] = {_T(いつやるか。), _T(今でしょ!), _T(あとで), _T
(やります。)};
CString sSave;
sSave = sData[0] + _T(\t) + sData[1] + _T(\n);
sSave += sData[2] + _T(\t) + sData[3] + _T(\n);
BYTE bom[] = {0xff, 0xfe};
CFile f;
f.Open(_T(test1.csv), CFile::modeCreate | CFile::modeWrite);
f.Write(bom, sizeof(bom));
f.Write(sSave, sSave.GetLength() * sizeof(TCHAR));
f.Close();

これで、タブ区切りのCSV?ファイルが出来て、ダブルクリックでエクセルが開き、文字
化けなく正常に表示されました。

本当はコンマ区切りにしたいので、コンマ区切りで作成した場合もやってみました。
① 作成したファイルをダブルクリックすると、エクセルが開いて、文字化けはありませ
んが、コンマも文字として認識した文字列「いつやるか。,今でしょ!」が表示されま
す。
② エクセルを起動してからファイルを開き、ウィザードDLGで”カンマ区切り”を選択
して進むと、正常に表示されました。
③ 次に、エクセル上で編集を行い、上書き保存のアイコンで保存すると、タブ区切りの
ファイルに変化しました。
④ 名前を付けて保存で「CSV(カンマ区切り)」で保存すると、正常に保存されまし
た。
⑤ そのファイルは次回ダブルクリックでも正常に開きました。

②の方法で開き④の方法で保存・・・これを励行すればコンマ区切りでも使えそうで
す。

それにしても、エクセルの Unicode 対応は中途半端と思います。

⑤の理由が解りません。BOM以外の何かをエクセルが書き込んだのでしょうか?

蒼の洞窟様はじめ、皆様ありがとうございました。


返信引用
瀬戸っぷ
 瀬戸っぷ
(@瀬戸っぷ)
ゲスト
結合: 18年前
投稿: 178
 

>⑤の理由が解りません。BOM以外の何かをエクセルが書き込んだのでしょうか?

④で書き出したファイルがShift-JISだった…とかではないですか?


返信引用
花の慶次
 花の慶次
(@花の慶次)
ゲスト
結合: 12年前
投稿: 4
Topic starter  

これは、これは、親分! 大笑い (^o^)

④で書き出したファイルは Shift-JIS でした。
やはりタブ区切りでないとエクセルではまともに扱えませんね。

タブ区切りだと、何かと扱いにくい。
Unicode が大前提なので、エクセルに阿て(おもねて)タブ区切りにするか、エクセル
を無視してコンマ区切りで押し通すか・・・うーむ

ありがとうございました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました