締切済み

VC++でUTF-8のファイルを出力したい

  • すぐに回答を!
  • 質問No.6890711
  • 閲覧数9833
  • ありがとう数7
  • 気になる数0
  • 回答数5
  • コメント数0

お礼率 100% (6/6)

VisualStudio2005で以下のコードを実行したとき、ファイルをUTF-8で作成したいのですが、なにか方法がありますか?
現状では、SJISで出力されてしまいます。
ソースは、『ファイル』-『保存オプションの詳細設定』で『UTF-8(BOM付き)』にしてあります。

#include <stdio.h>

int main(int argc, char* argv[])
{
    FILE *fp;

    fp = fopen( "c:/temp/log.txt", "w");

    fprintf( fp, "%s\n", "あいうえお" );

    fclose( fp );

    return 0;
}

ちなみに、”あいうえお”の部分を(EmEditorで)SJISに無くてUTF-8にだけ存在する文字にした場合、VisualStudioのエディタ上では正しく文字が表示されます。
したがって、VisualStudio内ではリテラルの文字コードはUTF-8で扱われていると考えられます。・・・が、上記プログラムで出力すると文字化けします。つまり、SJISで出力されてしまいます。

ご教授のほど、よろしくお願いいたします。

回答 (全5件)

  • 回答No.5

ベストアンサー率 43% (38/87)

再回答で。

よく見たらソース全体がUnicode用になってないですよね、これ。

int main(int argc, char* argv[])

int _tmain(int argc, _TCHAR* argv[])

fp = fopen( "c:/temp/log.txt", "w");

fp = _tfopen( _T( "c:/temp/log.txt" ), _T( "w, ccs=UTF-8" ) );

fprintf( fp, "%s\n", "あいうえお" );

_tfopen( fp, _T( "%s\n" ), _T( "あいうえお" ) );

_UNICODEを定義する。
tchar.hをインクルードする。

などの変更が必要です。
詳細はマニュアルの「Unicode プログラミングの要約」辺りを参照してください。
お礼コメント
bigbang2010

お礼率 100% (6/6)

お礼が遅れて申し訳ありません。
現在別件作業中で、この問題は別担当者に任せていました。
現在の解決策としては、リテラル文字列使用時にsjis→UTF-8変換して動かしている状態です。
ご回答いただいた件、調査してみます。コンパイラオプションではなく、_UNICODEを定義することによってオブジェクトがUTF-8になる…ということ?ですかね。このようなことは、コンパイルオプションでやるものだとばかり思っていました。

色々な流れで、今回のコードはワンソースでWinとLINUX両方で動かす可能性が大です。したがって、Win独自のコーディングが出来ない(部分的なifdefはありますが)可能性大です。ご回答いただいた件がgcc(g++)で可能なのか合わせて調べてみたいと思います。

Win環境だけでの文字コード関係なしプログラミング…勉強不足を痛感です。
投稿日時 - 2011-08-05 10:29:18
  • 回答No.4

ベストアンサー率 53% (2177/4070)

>したがって、UTF-8で書かれたソースコードがVisualStudioのエディタで正しく表示されているにもかかわらず、その文字列を出力するとsjisになってしまうのです。

出力したファイル(c:/temp/log.txt)がShift-JISになっている。
というのはどのように確認しましたか?
BOM付きで出力されていない場合、エディタの自動認識では失敗(UTF-8のつもりがShift-JIS)することもありますが…。
秀丸Ver8.10の自動認識ではShift-JISとして認識される。
そこからエンコーディングをUTF-8にして読み込みし直すとは『羽かんむりに軍(UTF-8コード0xE7,0xBF,0xAC)』になります。
もちろん、バイナリエディタで覗くと0xE7 0xBF 0xAC 0x0D 0x0Aです。
さらに、名前をつけて保存でBOM付きで保存して開き直すと、普通にUTF-8になります。
ソースファイルがBOM付きでも、そのコードから出力されるファイルには関係ないコトでしょう……。
# 実行バイナリ中のデータには影響するかも知れませんが…


fprintf()でなぜかDebug Assertionになってしまいます……>#3
fopen()でオープンはできるんですけど。
# VS2005SP1とVC++2008EE SP1で確認…。
補足コメント
bigbang2010

お礼率 100% (6/6)

ご回答ありがとうございます。

出力したファイル(c:/temp/log.txt)がShift-JISになっている。
というのはどのように確認しましたか?
 → EmEditorとVisualStudioのバイナリエディタで確認しました。

ソースファイルがBOM付きでも、そのコードから出力されるファイルには関係ないコトでしょう……。
 → おっしゃる通りです。

私も、VS2005SP1で『No.3 jx-word』様の方法を試してみましたが、Assertionとなってしまいました。
投稿日時 - 2011-07-22 13:53:50
お礼コメント
bigbang2010

お礼率 100% (6/6)

皆様ありがとうございました。
結局、オブジェクトコードがUTF-8にならない限り、出力時のsjis→UTF-8変換が必用になるということですね。
先程exe内でリテラル文字列がsjisになっていることを確認しました。

追加確認結果です。
sjis範囲外のUTF-8(例えば羽かんむりに軍)はVisualStudioのエディタ上では表示されますが、オブジェクトコード上では0x3f(?)になってしまいます。
したがって、sjis→UTF-8変換も出来ないと思われます。0x3fはどう変換しても0x3fですから。
投稿日時 - 2011-07-22 19:38:27
  • 回答No.3

ベストアンサー率 43% (38/87)

VS2005であればfopenの下記のパラメータ指定でいけるはずです。

fp = fopen("c:/temp/log.txt", "w, ccs=UTF-8");

詳細はマニュアルのfopenの項を参照してください。
補足コメント
bigbang2010

お礼率 100% (6/6)

ご回答ありがとうございます。

VisualStudio2005+SP1で上記方法を試してみましたが、fprintf()でAssertionとなってしまいました。
『これだ!』と思ったんですけど…
投稿日時 - 2011-07-22 13:52:15
お礼コメント
bigbang2010

お礼率 100% (6/6)

皆様ありがとうございました。
結局、オブジェクトコードがUTF-8にならない限り、出力時のsjis→UTF-8変換が必用になるということですね。
先程exe内でリテラル文字列がsjisになっていることを確認しました。

追加確認結果です。
sjis範囲外のUTF-8(例えば羽かんむりに軍)はVisualStudioのエディタ上では表示されますが、オブジェクトコード上では0x3f(?)になってしまいます。
したがって、sjis→UTF-8変換も出来ないと思われます。0x3fはどう変換しても0x3fですから。
投稿日時 - 2011-07-22 19:38:54
  • 回答No.2

ベストアンサー率 74% (465/626)

ソースファイルの文字コードが何であれ,コンパイル時に想定されるexecution character setが,
日本語環境においてShift_JISから変化するわけではありません。
# source character setが変化するだけ。

想定されるexecution character setへの変換はコンパイル時に行われるため,
・ソースファイル中ではwide string literalを使う
・必要に応じてUTF-16からUTF-8に変換する
という二段階で行う必要があります。
# chcp 65001したコマンドプロンプトでビルドすれば想定がUTF-8になるかもしれませんが,試していません。
補足コメント
bigbang2010

お礼率 100% (6/6)

『想定されるexecution character setへの変換はコンパイル時に行われるため・・・』
 → と、言うことはコンパイル時にUTF-8のオブジェクトが出力できればいいわけですよね。
 → Linux環境のgcc(g++)はコンパイルオプション『-fexec-charset=xxxxx』があります。
  たしかに、この機能を使ってLinux上でsjisのファイル操作(リテラル文字列を検索したり…)
  したことがあります。

しかしながら、VisualStudioのコンパイルオプションには・・・見つけられませんでした。
これが出来れば、コーディング的にも綺麗に行けるんですけどね。
投稿日時 - 2011-07-22 13:41:51
お礼コメント
bigbang2010

お礼率 100% (6/6)

皆様ありがとうございました。
結局、オブジェクトコードがUTF-8にならない限り、出力時のsjis→UTF-8変換が必用になるということですね。
先程exe内でリテラル文字列がsjisになっていることを確認しました。

追加確認結果です。
sjis範囲外のUTF-8(例えば羽かんむりに軍)はVisualStudioのエディタ上では表示されますが、オブジェクトコード上では0x3f(?)になってしまいます。
したがって、sjis→UTF-8変換も出来ないと思われます。0x3fはどう変換しても0x3fですから。
投稿日時 - 2011-07-22 19:39:16
  • 回答No.1

ベストアンサー率 46% (546/1184)

Shift_JIS→UTF-8 変換かけるだけじゃないかと。

WideCharToMultiByte、MultiByteToWideChar 使えばたいした手間ではないでしょう。
補足コメント
bigbang2010

お礼率 100% (6/6)

早速のご回答ありがとうございます。
確かにソースコードがsjisであればUTF-8変換すればOKです。

ところが、このソースコードはすでにUTF-8なのです。質問のところで『”あいうえお”の部分を…』と書きましたが、ここには実際には『羽かんむりに軍(UTF-8コード0xE7,oxBF,0xAC)』が書かれています。そして、VisualStudioのエディタでは、『羽かんむりに軍』は表示されています。
したがって、UTF-8で書かれたソースコードがVisualStudioのエディタで正しく表示されているにもかかわらず、その文字列を出力するとsjisになってしまうのです。

話を簡単にするために『あいうえお』と書いたために誤解させてしまったかもしれません。すみませんでした。
…というわけです。
ちなみに、『羽かんむりに軍』はsjisには無い文字です。
投稿日時 - 2011-07-22 10:59:53
お礼コメント
bigbang2010

お礼率 100% (6/6)

皆様ありがとうございました。
結局、オブジェクトコードがUTF-8にならない限り、出力時のsjis→UTF-8変換が必用になるということですね。
先程exe内でリテラル文字列がsjisになっていることを確認しました。

追加確認結果です。
sjis範囲外のUTF-8(例えば羽かんむりに軍)はVisualStudioのエディタ上では表示されますが、オブジェクトコード上では0x3f(?)になってしまいます。
したがって、sjis→UTF-8変換も出来ないと思われます。0x3fはどう変換しても0x3fですから。

さっき気付きましたが「επιστημη」さんだったんですね。DDJJ読んでました。光栄です。
投稿日時 - 2011-07-22 19:40:32
結果を報告する
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。
関連するQ&A
AIエージェント「あい」

こんにちは。AIエージェントの「あい」です。
あなたの悩みに、OKWAVE 3,500万件のQ&Aを分析して最適な回答をご提案します。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する

ピックアップ

ページ先頭へ