UTF8からShiftJISに変換する方法

このQ&Aのポイント
  • UTF8からShiftJISに変換する方法について説明します。
  • メディアプレーヤーで作られたwplファイルを扱うために、UTF8からShiftJISに変換する必要があります。
  • 現在のソースコードではUTF8からShiftJISに変換する処理が行われていますが、正しく変換されていないようです。
回答を見る
  • ベストアンサー

UTF8→ShiftJISに変換したいです!

VC++2010, MFCです。 参考ページ(↓)でできそうだったのですが、 http://www.sutosoft.com/oldroom/devdiary/20020504.html UTF-8からShift_JISにしたいのは、メディアプレーヤーで作られた wpl ファイルも扱いたいからです。 具体的にいうと、ファイル一覧に プレイリストがあった場合、展開してメディアプレイヤーで開いて、再生後 【m3u ファイル】に(コーディングで)アウトプットするのが目的です。 ShiftJISに変換して、いったんファイルに出力してから、再度読込処理を行ってもかまいません。 BOOL C○○Dlg::UTF8ToShiftJIS(const CString& src, CString* dest) {  int sizeOfString = (src.GetLength() + 1);  LPWSTR lpsz = new WCHAR[sizeOfString];  //LPSTR lpsz = new char[ sizeOfString ];  _tcscpy_s(lpsz, sizeOfString, src);    //strcpy_s(lpsz,sizeOfString, src);  //delete[] lpsz //http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200612/06120010.txt //char* orig = "Hello, World"; char* nstring; nstring = new char[sizeOfString]; strcpy_s(nstring,sizeOfString, (LPCSTR)(lpsz)); // ●UTF8からUnicodeに変換した場合の長さを求める。●  //http://msdn.microsoft.com/ja-jp/library/cc448053.aspx  //const_cast<LPTSTR>(static_cast<LPCTSTR>(str)  int iWideLength = ::MultiByteToWideChar(CP_UTF8, 0,【1】nstring, src.GetLength(), NULL, 0);  if (iWideLength == 0)return FALSE;  LPWSTR lpWideString = new WCHAR[iWideLength];  int iLength;  if (    // ●UTF8からUnicodeに変換する。●    (::MultiByteToWideChar(CP_UTF8, 0, 【2】nstring, src.GetLength(), lpWideString, iWideLength) == 0)    // ●UnicodeからShift_JISに変換した場合の長さを求める。●    || ((iLength = ::WideCharToMultiByte(CP_ACP, 0, lpWideString, iWideLength, NULL, 0, NULL, NULL)) == 0)    // ●UnicodeからShift_JISに変換する。●        //http://msdn.microsoft.com/ja-jp/library/cc448089.aspx    || (::WideCharToMultiByte(CP_ACP, 0, lpWideString, iWideLength, 【3】(LPSTR)dest->GetBuffer(iLength), iLength, NULL, NULL) == 0)){    // ●変換に失敗●    delete lpWideString;    return FALSE;  }  // ●変換に成功●  delete lpWideString;  dest->ReleaseBuffer();  return TRUE; } ・・・という風に少し修正をして、次のソースで呼び出しています。  CString src;  CFile file;  if (file.Open(FilePath, CFile::modeRead)){   DWORD iLength = file.GetLength();   //CString src;   file.Read(src.GetBuffer(iLength), iLength);   file.Close();   src.ReleaseBuffer(iLength);   CString dest;   if (UTF8ToShiftJIS(src, &dest) ==TRUE){    MessageBox (dest);   }   // ●この時点で、destにShift_JISに変換された文字列が格納されている。  } 以下(↓)を参考に、【1】~【3】の部分で、他のパターンもキャストしてみたのですが・・・ /* http://d.hatena.ne.jp/shikaku/20090519/p3 ■[CPP][VC]LPCSTRなどのVC++の紛らわしい定義の意味 一見正体不明のVC++オリジナル定義。よーくみれば違いが分かる。名前 意味 LP *(ポインタ) C const TSTR TCHAR(char) STR char WSTR WCHAR(ユニコード用:2byte) ゆえに定義 正体 LPSTR char* LPCSTR const char* LPTSTR TCHAR* LPCTSTR const TCHAR* LPWSTR WCHAR* LPCWSTR const WCHAR* となる。+/ できるだけスマートに記述したいです。エクセル版を作っていたときは、CreateObject("ADODB.Stream")を使っていたみたいです。ただ、VC++でどう書けばいいか、分かりませんυ UTF8→UTF16→ShiftJIS ←これは、あまり、使いたくない 変換 です。 後は、これも参考になりそうですが、 http://www.softist.com/programming/sjis-utf8/sjis-utf8.htm bufUTF8を何型でどこで宣言すればいいのか?分かりません。 これも(↓)はてなです。 http://www.s-cradle.com/developer/sophiaframework/sf_reference/ref.SFXTextEncoding.html 何回も試しましたが、TRUEが返ってきても、変換前と変換後をMessageBoxで比べてみても、変わりがなく、漢字や記号の羅列でしかありません。どうか教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • a_kwn
  • ベストアンサー率34% (8/23)
回答No.3

CString型は、プロジェクトの文字セットの設定の影響を受けます。 ・”マルチバイト文字セットを使用する”の場合:CStringA ・”Unicode 文字セットを使用する”の場合:CStringW 異なる文字コードを扱う必要のあるプログラムでは、CString型ではなく、 CStringA, CStringW を使い分ける必要があります。 UTF-8 を格納する適切なCString型はありませんので、 ・バイナリデータとして扱う(通常はこちら) ・CStringA に格納する(次善の策) ぐらいかと思います。 残念ながら元のコードでは、プロジェクトがUnicode文字セットの設定の場合には、 動作する可能性がありません。 <コード例> BOOL C○○Dlg::UTF8ToShiftJIS(const CStringA& src, CStringA* dest) {  // UTF-8 -> Unicode  //  int iWideLength = ::MultiByteToWideChar(CP_UTF8, 0, src, -1, NULL, 0);  if (iWideLength == 0) return FALSE;    CStringW temp;    int iLength = ::MultiByteToWideChar(CP_UTF8, 0, src, -1, temp.GetBuffer(iWideLength), iWideLength);  temp.ReleaseBuffer();    if (iLength == 0) return FALSE;    // Unicode -> S-JIS は、CString 標準の変換を使用する。  // 何か問題がある場合は、::WideCharToMultiByte の使用を検討する。  //  *dest = temp;    return TRUE; } CStringA src; CFile file; if (file.Open(FilePath, CFile::modeRead)) {  DWORD iLength = file.GetLength();  file.Read(src.GetBuffer(iLength), iLength);  file.Close();  src.ReleaseBuffer(iLength);    // ファイルから読み込んでるが、UTF-8 の BOM(EF, BB, BF)の扱いは大丈夫か?  //  static const BYTE utf8_bom[3] = { 0xEF, 0xBB, 0xBF };    if (::strncmp(src, reinterpret_cast<const char*>(utf8_bom), 3) == 0) {   src.Delete(0, 3);  }    CStringA dest;  if (UTF8ToShiftJIS(src, &dest)) {   // 文字コードが S-JIS なので、ANSIバージョンを明示的に使用する必要がある   // (MessageBox ではなくて、MessageBoxA)   //   ::MessageBoxA(m_hWnd, dest, "てすと", MB_OK);  } }

psychang
質問者

お礼

分かりやすい説明と完全に動くソースコードまで、ありがとうございました! うまく行きました。 (メディアプレイヤーのパラメータに、大量のファイルのフルパスを一個一個与えて再生しようとすると、全然再生されない(遅い?)ようです。パラメータの長さに限りがあるのでしょうか?) (一度、プレイリスト(m3u)ファイルに出力して、そのファイルのフルパスをメディアプレイヤーのパラメータに与えると、早く処理されるようです。) では、締め切らせていただきますね。m(_ _)m

psychang
質問者

補足

凄いです!こんなにスマートにかけるなんて、ご回答ありがとうございました m(_ _)m 後は、もう少し検証してから(土曜日あたりに)締め切らせてもらいます。 エクセルの方でも、バイナリ形式で処理するサンプルがありますので、そこら変ももう一度見てみます。 今回は全てコーディングしてもらいましたが、VC初心者を免罪符にしないようにしたいですが、正直、難しいです。。。(ΘoΘ;) では。

その他の回答 (2)

回答No.2

下記の回答は誤りです。申し訳ありません。 -------------------- UTF8->ShiftJISは、 WideCharToMultiByte(CP_UTF8, .....); で、UNICODEを経由しなくても、1回で変換できると思います。 第1引数をCP_UTF8にしてください。

psychang
質問者

お礼

解決への きっかけ を作っていただき、感謝しています。

psychang
質問者

補足

回答ありがとうございます。 誤り、分かりました。 今は、心が折れて(?)しまったので、水曜日以降、もうちょっと試行錯誤してみようと思います。 極力、コード表とにらめっこでコーディングする事をさけ(←バグを排除するためにです)、VCに用意された命令で、実現したいです。 でも検索したら、文字コードを変換するフリーソフトが沢山ヒットしました。 簡単に作れるなら、それらのツールは不要なわけで・・・と、ここで質問した事との矛盾は感じています。(だから、しばらく回答が0だったのかも知れませんねυ) 質問にあるとおり、 http://www.sutosoft.com/oldroom/devdiary/20020504.html から、コードをコピーしたら、引数の所で、型が合わないというエラーがでたので、型だけ無理やりあわせました。 (つじつま合わせの型変換は意味ないのでしょうか?) 値渡しか、参照渡しか、の意味は分かりますが、正確な表記方法は分からないかもしれません。 ちなみに、言い忘れましたが、プロジェクトの設定は、ちゃんとユニコード対応にしています。 どなたからヒントだけでもいいので、教えていただけると嬉しいです。 ではでは。

回答No.1

UTF8->ShiftJISは、 WideCharToMultiByte(CP_UTF8, .....); で、UNICODEを経由しなくても、1回で変換できると思います。 第1引数をCP_UTF8にしてください。

関連するQ&A

  • CStringをwchar_tに変換したい

    CStringをwchar_tに変換したく思い、ネットで探したところ、 http://msdn2.microsoft.com/ja-jp/library/ms235631(VS.80).aspx のページを見つけたので、下記のプログラムを組んで実行してみましたがエラーになって しまいます。 【プログラム】 CString orig("Hello, World!"); // Convert to a char* const size_t newsize = 100; // Convert to a wchar_t* // You must first convert to a char * for this to work. size_t origsize = strlen(orig) + 1; size_t convertedChars = 0; wchar_t wcstring[newsize]; mbstowcs_s(&convertedChars, wcstring, origsize, orig, _TRUNCATE); 【エラー】 error C2664: 'strlen' : 1 番目の引数を 'CString' から 'const char *' に変換できません。 error C2664: 'mbstowcs_s' : 4 番目の引数を 'CString' から 'const char *' に変換できません。 &CStrinをconst char *でキャストしてもうまくいきません。 どこがおかしいのでしょうか? 【環境】 WindowsXP+VC++2005

  • VC++にてCString型のフルパスをfopenする

    VC++(VisualStudio2005)にてCString型のフルパスをfopenしたいと思っています。 他ページでは char *name = new char[filepass.GetLength()+1]; strcpy( name, filepass ); でstrcpyでCstring→charへ変換できるとあったのですが、 'strcpy' : 2 番目の引数を 'CString' から 'const char *' に変換できません。(新しい機能 ; ヘルプを参照) 1> この変換を実行可能なユーザー定義変換演算子がないか、または演算子を呼び出せません。 というエラーをはいて実行できませんでした。 lstrcpy(name, filepass)でも 1 番目の引数を 'char [100]' から 'LPWSTR' に変換できません。(新しい機能 ; ヘルプを参照) 1> 指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。 となりました。 何か良い方法をご存じないですか? char型に変換できなくとも、結果的にfopenを使ってファイルオープンできれば良いです。

  • CString ←→ BSTRの変換について

    次のコードのように、CString ←→ BSTRの変換を行いたいのですが、データがUTF8だと文字化けしてしまいます。 どうすれば良いでしょうか? 環境:VC++7(.net 2003)+MFC+WinXP 【結果】 CString-------------------------- FFFFFFE2 FFFFFF97 FFFFFF8B 3C BSTR-------------------------- FFFFFFE2 FFFFFF97 FFFFFF81 45 【ソース】 int intCT; int nSize = 0; BYTE *pSource = (BYTE *)"○<"; this->ConvSJistoUtf8(pSource, (BYTE *)NULL, &nSize ); BYTE* pDist = new BYTE[ nSize + 1 ]; ZeroMemory( pDist, nSize + 1 ); this->ConvSJistoUtf8(pSource, pDist, &nSize ); CString str = CString(pDist); delete []pDist; pDist = NULL; BSTR bstr; bstr=str.AllocSysString();//CString→BSTRへの変換 CString str2=CString(bstr);//BSTR→CStringへの変換 TRACE("CString--------------------------\n "); for( intCT = 0; intCT < str.GetLength(); intCT++ ) { if( intCT%16 == 0 ) TRACE("\n"); TRACE("%02X " , str[intCT]); } TRACE("\n "); TRACE("BSTR--------------------------\n "); for( intCT = 0; intCT < str2.GetLength(); intCT++ ) { if( intCT%16 == 0 ) TRACE("\n"); TRACE("%02X " , str2[intCT]); } TRACE("\n "); BOOL ConvSJistoUtf8( BYTE* pSource, BYTE* pDist, int* pSize ) { *pSize = 0; //ShiftJISからUTF-16へ変換 const int nSize = ::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)pSource, -1, NULL, 0 ); BYTE* buffUtf16 = new BYTE[ nSize * 2 + 2 ]; ::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)pSource, -1, (LPWSTR) buffUtf16, nSize ); //UTF-16からShift-JISへ変換 const int nSizeUtf8 = ::WideCharToMultiByte( CP_UTF8, 0, (LPCWSTR) buffUtf16, -1, NULL, 0, NULL, NULL ); if( !pDist ){ *pSize = nSizeUtf8; delete buffUtf16; return TRUE; } BYTE* buffUtf8 = new BYTE[ nSizeUtf8 * 2 ]; ZeroMemory( buffUtf8, nSizeUtf8 * 2 ); ::WideCharToMultiByte( CP_UTF8, 0, (LPCWSTR)buffUtf16, -1, (LPSTR) buffUtf8, nSizeUtf8, NULL, NULL ); *pSize = lstrlen( (char*)buffUtf8 ); memcpy( pDist, buffUtf8, *pSize ); delete buffUtf16; delete buffUtf8; return TRUE; }

  • UNICODE対応ってどういうことなのかわかりません

    VC++とかでUNICODE対応というと文字列をwchar_t型で扱うことなのかなと思うのですが、その場合UTF-8ってどういう扱いになっているのでしょうか? ウィキペディアを見ると、インターネットではUTF-8が主流であるようなことが書かれています。 UTF-8はアスキー文字セットとも互換性があるようなので、char型で文字列を扱うのかなと思いました。 それなのに、VC++でUNICODE対応の設定にするとwchar_tで文字列を扱うようなので、UTF-8がどういう扱いになっているのかよくがわからないのです。 どなたかお答え頂けないでしょうか。 よろしくお願いします。

  • CString型からdouble型への変換

    C++は初心者です。VC4.0を使っていますがMFCなどは使っていません。 CString型の変数をint型やlong型への変換はなんとかできたのですが、double型へ変換することができずに困っています。atofを使えばいいのだと思い下記のように記述したのですが、コンパイルするとエラーがでます。   CString sample = "0.234";   double i;   i = atof((const char*)sample); error C2440: 'type cast' : cannot convert from 'class CString' to 'const char *' どう直せば無事にdouble i に0.234を格納できるのでしょうか?よろしくお願いします。

  • VC++2005で、CString型に16進文字列を入れたいのですが・・

    VC++2005で、CString型に16進文字列を入れたいのですが・・・ 次のようなエラーが出ます。 void ATL::CStringT<BaseType,StringTraits>::Format(const wchar_t *,...)' : 1 番目の引数を 'const char [5]' から 'const wchar_t *' に変換できません。 プログラムは次の通りです。 CString strBuff; CString strWork; TCHAR tszBuff[80]; UINT unLength; UINT un1; unLength = 5; strBuff = "12345"; _tcscpy(tszBuff, strBuff); strWork = ""; for(un1 = 0; un1 < unLength; un1++) { strWork = strWork + strBuff.Format("%02x", tszBuff[un1]); ←ここにエラーがあると言われています。 } 結果は、strWorkに、"3132333435"となるようにしたい! ネットで探したら、 >UNICODEを使われているのだと思われます。 >T("")マクロを使ってワイドキャラクタに変換するように指示すれば動くと思います。 とあったので、 strWork = strWork + strBuff.Format(_T("%02x"), tszBuff[un1]); としてみたのですが、 二項演算子 '+' : 型 'void' の右オペランドを扱う演算子が見つかりません (または変換できません)。 というエラーが表示されました。 VC++6.0を半年かじり、今日、初めてVC++2005に触った程度の初心者です。 どなたか助言を頂ければ幸いです。 環境  Windows XP Pro SP3  Visual C++ 2005(MFC) 以上、よろしくお願いします。

  • CString から LPCTSTRの型に変換

    visual studio 2013 VC++を使用していますが、WINDOWSの関数に渡すためにCString からLPCTSTRに変換する必要があります。実際にどのようにするのかわかりません。 例えば、以下のサンプルは他の質問コーナーの回答をアレンジしたものです CString str = _T("ABC"); int siz = str.GetLength()+1; LPCTSTR pszFName = new TCHAR[siz]; _tcscpy_s( pszFName, siz, str ); で変換するのですが LPCTSTRからwchar_t*へ変換できませんとエラーがでます _tcscpy_s()は使用できないのでしょうか

  • strcat関数

    学校の課題で strcat関数と全く同じ働きをするmy_strcatを実装せよ という課題がでています。 strcatは char* strcat(char *dest, const char *str) で表され、文字列 strを文字列 dest に合成して 合成された新しい文字列として dest を返します。 例えば、dest = Japan, str = Korea だったら, 関数処理後に、 dest = JapanKorea を戻り値とします。 ********************************************* my_strcat実装について 実装段階で一番の問題になるのが、文字列のサイズです。 とりあえず、私の書いたコードを示します↓ char* my_strcat(char *dest, const char *src) { int i=0; int j=0; while(*dest) { dest++; i++; } while(*src) { *(dest+i) = src[0]; i++; src++; } *(dest+j) = src[0]; //put null at the end of dest return dest; } 試しにdest=Japan,str=Koreaでやってみたのですが、動きませんでした。 原因はdest の文字サイズを無視した無理やりなりな実装だと考えます。 C言語では文字のサイズを一度宣言したら、変えられないと思うので、困っています。 どなたかアドバイスをいただけないでしょうか。 よろしくお願いします

  • ■文字コード判定■

    あるバッファに入っている文字列の文字コード(ANSI、SJIS、UNICODEなど)を判定したいのですが、色々と調べたのですが、解決しませんでした。 ANSIでもUNICODEでもきちんと文字列を扱えるアプリケーションを開発しています、問題となる例です↓ (メッセージボックス) int MessageBox_OK( HWND hWnd, LPCTSTR lpCaption, LPCTSTR lpText ) { int ret; int len_w; LPWSTR wCaption, wText; //変換後の、UNICODE文字列取得バッファ //コンパイル設定がUNICODEの時に、ANSIをUNICODEに変換する #ifdef UNICODE //ここで文字コードを判定したいです|・ω・`) //UNICODEでなかったらUNICODEに変換する len_w = AnsiToUnicode_Size( lpCaption ); len_w = len_w * sizeof(WCHAR); wCaption = (LPWSTR)malloc( len_w + 1 ); AnsiToUnicode_Convert( lpCaption, wCaption ); //ここで文字コードを判定したいです|・ω・`) len_w = AnsiToUnicode_Size( lpText ); len_w = len_w * sizeof(WCHAR); wText = (LPWSTR)malloc( len_w + 1 ); AnsiToUnicode_Convert( lpText, wText ); #else return MessageBox( hWnd, lpText, lpCaption, MB_OK ); #endif return MessageBox( hWnd, wText, wCaption, MB_OK ); } //ANSI→UNICODE (必要サイズ(文字数)) int AnsiToUnicode_Size( LPCSTR strAnsi ); //ANSI→UNICODE (変換) BOOL AnsiToUnicode_Convert( LPCSTR strAnsi, LPWSTR strUnicode ); よろしくお願いします。

  • c++ CString char* BSTR textbox.text

    c++ 文字列CStringとchar*の変換問題(unicode) _________________________________________________________ Excel   string -> セールの文字列をVC++側に渡すため  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ↓ ______________________________________________________________ VC++   char * -> Excelから引数として渡される文字列  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ↓ __________________________________________________________ VC++   system::string -> FormのTextBox.Textとしてセット  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ↓ ______________________________________________________________ VC++   char * -> FormのDataGridから受け取る文字列  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ↓ ______________________________________________________________ VC++   CString -> VC++からExcelに渡すためBSTR前処理  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ↓ __________________________________________________________ VC++   BSTR -> VC++からExcelに渡すため  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ↓ __________________________________________________________ Excel   string -> Excelのある処理に使う  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ 漢字やひらがなも文字化けないように変換できると思いますが、文字化けしたり変換が困難な状況です。 どうぞよろしくお願いします

専門家に質問してみよう