これ何て呼びますか Part2

VC++2010, MFCです。

参考ページ(↓)でできそうだったのですが、
http://www.sutosoft.com/oldroom/devdiary/2002050 …

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. …
//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 …

 //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 …
   || (::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*(ポインタ)
Cconst
TSTRTCHAR(char)
STRchar
WSTRWCHAR(ユニコード用:2byte)


ゆえに定義正体
LPSTRchar*
LPCSTRconst char*
LPTSTRTCHAR*
LPCTSTRconst TCHAR*
LPWSTRWCHAR*
LPCWSTRconst WCHAR*


となる。+/


できるだけスマートに記述したいです。エクセル版を作っていたときは、CreateObject("ADODB.Stream")を使っていたみたいです。ただ、VC++でどう書けばいいか、分かりませんυ

UTF8→UTF16→ShiftJIS ←これは、あまり、使いたくない 変換 です。

後は、これも参考になりそうですが、 http://www.softist.com/programming/sjis-utf8/sji …
bufUTF8を何型でどこで宣言すればいいのか?分かりません。

これも(↓)はてなです。
http://www.s-cradle.com/developer/sophiaframewor …

何回も試しましたが、TRUEが返ってきても、変換前と変換後をMessageBoxで比べてみても、変わりがなく、漢字や記号の羅列でしかありません。どうか教えてください。

A 回答 (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);
 }
}

この回答への補足

凄いです!こんなにスマートにかけるなんて、ご回答ありがとうございました m(_ _)m

後は、もう少し検証してから(土曜日あたりに)締め切らせてもらいます。

エクセルの方でも、バイナリ形式で処理するサンプルがありますので、そこら変ももう一度見てみます。
今回は全てコーディングしてもらいましたが、VC初心者を免罪符にしないようにしたいですが、正直、難しいです。。。(ΘoΘ;)

では。

補足日時:2011/08/01 23:11
    • good
    • 0
この回答へのお礼

分かりやすい説明と完全に動くソースコードまで、ありがとうございました!

うまく行きました。

(メディアプレイヤーのパラメータに、大量のファイルのフルパスを一個一個与えて再生しようとすると、全然再生されない(遅い?)ようです。パラメータの長さに限りがあるのでしょうか?)

(一度、プレイリスト(m3u)ファイルに出力して、そのファイルのフルパスをメディアプレイヤーのパラメータに与えると、早く処理されるようです。)

では、締め切らせていただきますね。m(_ _)m

お礼日時:2011/08/03 04:25

下記の回答は誤りです。

申し訳ありません。
--------------------
UTF8->ShiftJISは、

WideCharToMultiByte(CP_UTF8, .....);

で、UNICODEを経由しなくても、1回で変換できると思います。
第1引数をCP_UTF8にしてください。

この回答への補足

回答ありがとうございます。
誤り、分かりました。

今は、心が折れて(?)しまったので、水曜日以降、もうちょっと試行錯誤してみようと思います。
極力、コード表とにらめっこでコーディングする事をさけ(←バグを排除するためにです)、VCに用意された命令で、実現したいです。

でも検索したら、文字コードを変換するフリーソフトが沢山ヒットしました。
簡単に作れるなら、それらのツールは不要なわけで・・・と、ここで質問した事との矛盾は感じています。(だから、しばらく回答が0だったのかも知れませんねυ)

質問にあるとおり、 http://www.sutosoft.com/oldroom/devdiary/2002050 … から、コードをコピーしたら、引数の所で、型が合わないというエラーがでたので、型だけ無理やりあわせました。

(つじつま合わせの型変換は意味ないのでしょうか?)

値渡しか、参照渡しか、の意味は分かりますが、正確な表記方法は分からないかもしれません。

ちなみに、言い忘れましたが、プロジェクトの設定は、ちゃんとユニコード対応にしています。

どなたからヒントだけでもいいので、教えていただけると嬉しいです。
ではでは。

補足日時:2011/08/01 11:23
    • good
    • 0
この回答へのお礼

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

お礼日時:2011/08/03 04:14

UTF8->ShiftJISは、



WideCharToMultiByte(CP_UTF8, .....);

で、UNICODEを経由しなくても、1回で変換できると思います。
第1引数をCP_UTF8にしてください。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


おすすめ情報