• 締切済み

CStringとCByteArrayの変換

いつもお世話になっています。 MFCのCStringクラスとCByteArrayを相互に変換したいと考えているのですが、どうもうまくいきません。 文字コードはユニコードを想定しています。 ====================================================== CByteArray data; CString cs1 = _T("あいうえお"); CString cs2; LPBYTE lpByte = (LPBYTE)(LPCTSTR)cs1.GetBuffer(); data.SetSize(cs1.GetLength() * sizeof(TCHAR)); CopyMemory(data.GetData(), lpByte, data.GetSize()); cs1.ReleaseBuffer(); cs2 = (LPCTSTR)data.GetData(); AfxMessageBox(cs2); ====================================================== (現在の出力状況) あいうえお・・・・ 文字は正しく出力されますが、語尾に文字化けしたようなものがつきます。 他に良い方法があればよろしくお願いします。

みんなの回答

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

MFCのバージョンが不明ですが…… >文字は正しく出力されますが、語尾に文字化けしたようなものがつきます。 一般的な文字列では、終端に'\0'が必要ですが、その分の領域はCByteArrayのdataにあるのでしょうか? >data.SetSize(cs1.GetLength() * sizeof(TCHAR)); 『文字数』*sizeof(TCHAR)で、'\0'分が無いように見えますが……。 そんなワケでdtaに入っているのものは、LPCTSTRで示す「文字列」とは見なされないでしょうから… CStringへのコピー時には『'\0'が見つかるまで』の領域をコピーする動作をするでしょう。 さて、'\0'が見つかるのはいったいドコでしょう……。

sho1get
質問者

お礼

自己解決しました。 改行文字はあまり関係なかったみたいです。 (補足) void CStoCBA(CString &cs, CByteArray &data) { LPBYTE lpData; int nLength; nLength = cs.GetLength(); lpData = reinterpret_cast<LPBYTE>(static_cast<LPTSTR>(cs.GetBuffer())); data.SetSize(cs.GetLength() * sizeof(TCHAR)); CopyMemory(data.GetData(), lpData, data.GetSize()); cs.ReleaseBuffer(); data.FreeExtra(); } void CBAtoCS(CByteArray &data, CString &cs) { cs.SetString(reinterpret_cast<LPTSTR>(data.GetData()), data.GetSize() / sizeof(TCHAR)); } CByteArray data; CString cs1 = _T("あいうえお"); CString cs2; // CStringからCByteArrayに変換 CStoCBA(cs1, data); AfxMessageBox(cs1); // CByteArrayからCStringに変換 CBAtoCS(data, cs2); AfxMessageBox(cs2);

sho1get
質問者

補足

返信ありがとうございます。 MFCのバージョンはVisual C++ 2008を使用しているのでMFC9.0です。

関連するQ&A

  • 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()は使用できないのでしょうか

  • CString データの文字数カウントができない

    VusualStudioのMFCでクリップボードのデータの文字数をカウントしようとしています。 Webにあったように以下のようなクラスを作成し、 =========================================================== CString CClipboard::GetClipboardText() { CString strText; strText.Empty(); // クリップボードにテキストデータが入っているかを調べる if( !::IsClipboardFormatAvailable(CF_UNICODETEXT) ) return strText; // クリップボードのオープン if( !::OpenClipboard(NULL) ) return strText; // クリップボードからデータを取得し、strTextへコピー HANDLE hMem = ::GetClipboardData(CF_UNICODETEXT); LPTSTR pMem = (LPTSTR)::GlobalLock(hMem); ::lstrcpy((LPTSTR)(LPCTSTR)strText, pMem); ::GlobalUnlock(hMem); ::CloseClipboard(); return strText; } =========================================================== 適当にメモ帳などでコピー操作をしたのち、 CClipboard board; CString a = board.GetClipboardText(); int b = a.GetLength(); 上記コードが含まれた操作を実行するとaという文字列自体はデバッガ上から"test"のように 認識されているのですが、bの値が0になってしまいます。 ちょっとわけがわからず途方に暮れています。 アドバイスがあればよろしくお願いします。

  • CStringWが 使えないので

    マルチバイト(Shift-JIS)を 使っているソースで                                                                                             DWORD   size;   CStringW   csw;;   csw =   filename;    size = csw.GetLength(); というコードで size の値は 以下のコードの  sizeと同じ値になりますか?                    DWORD size; CString cs; cs = filename; size = cs.GetLength() * sizeof(TCHAR); 表題にも書きましたが CStringW が、使えないので 宜しく お願い致します。                       

  • 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; }

  • CStringWの使われ方が判らないので‥‥

    { CString cs; CStringW ws; cs.Format("%-32s",(LPCSTR)m_VolumeLabel); ws = cs; ByteSwapCopy(pvd+0x28,(LPCWSTR)ws,32); } ***************************************************************** { CString cs; CString ws; cs.Format("%-32s",(LPCSTR)m_VolumeLabel); ws = cs; ByteSwapCopy(pvd+0x28,(LPCTSTR)ws,32); } 上のコードがあるのですが (抜粋です)下のように書き換えればよいのですか? 教えてください。

  • 文字列クラスをoperatorオーバーロードで実装したい

    ATLにCStringという文字列クラスがあり、それを参考に operatorによる演算子オーバーロードで同じようなものを開発していて 一つだけ分からないことがありました。 CStringだと関数に文字列を受け渡す時にこのようなことができます。 #include <windows.h> #include <tchar.h> #include <atlstr.h> void func( LPCTSTR String ) {   MessageBox( NULL, String, NULL, MB_OK ); } int main() {   CString cStr = _T("テスト");   func( cStr ); } 分からないのはfunc( cStr );の部分です。 このように関数に受け渡す時のオーバーロードはどのように書けば良いのでしょうか? 何かEffectiveC++の最初の方の簡単な例題にこれと同様なやり方が あった気がしますが手元に無いため確認が取れなくて困ってしまっています・・。

  • CSting を TCHAR [] に変換したい。

    Visual Sutdio 2010 , VC++ , MFC でファイルリスト一覧作成ソフトを作っている者です。 CSting 型の _T("~\0~\0\0") を TCHAR [] に変換したいです。 CSting 型の変数名は、DeleteFilePathです。 '\0' を他の文字に置換して確認した所、正しく入っています。 現在は、4096文字の文字列配列に入れています。 ゴミ箱に移動できる時とできない時があります。 _______________________________________________________________________________ ■現在のコード  index = -1;  while ((index = CFileListCreatorDlg::m_xcList.GetNextItem  (index, LVNI_ALL | LVNI_SELECTED)) != -1)  {   CString FullPathString = CFileListCreatorDlg::m_xcList.GetItemText(index,2);   if (FullPathString.Right(1) != _T("\\")){     ::SetFocus(::GetDlgItem(m_hWnd,IDC_LIST));    FullPathString.Replace(_T ("\\"),_T("\\\\"));    DeleteFilePath = DeleteFilePath + FullPathString + _T('\0');    CFileListCreatorDlg::m_xcList.DeleteItem(index);   }   index--;  }  DeleteFilePath = DeleteFilePath + _T('\0');  _TCHAR cszPath[4096];   // TCHAR型  _tcscpy(cszPath, DeleteFilePath);  // CString型→TCHAR型  SHFILEOPSTRUCT sfs;  memset ( &sfs, 0, sizeof ( SHFILEOPSTRUCT ) );  sfs.fFlags = FOF_NOERRORUI | FOF_SIMPLEPROGRESS | FOF_ALLOWUNDO;// ゴミ箱へ移動の確認をする場合 FOF_ALLOWUNDO をつける;  sfs.wFunc = FO_DELETE;  sfs.pFrom = cszPath;  if ( 0 != SHFileOperation ( &sfs ) )  {   MessageBox(_T("ゴミ箱に移動できませんでした"),_T("SHFileOperation 失敗"),MB_OK);   return 0;  } _________________________________________________________________________________________________________________________________________________ 5回に1回成功するので、不思議です。 ファイルのパスは、リストコントロールのアイテムに格納されていて、 削除したいアイテムを選択肢、Shift + Delete で、ゴミ箱に削除する ユーザー関数が呼び出されます。(ゴミ箱に移動するだけで、確認メッセージは出なくていいです。) 今まで、具体的した事を記すと以下のようになります。 cszPath = const_cast<LPTSTR>(static_cast<LPCTSTR>DeleteFilePath;  //ビルドエラー としたり、 _TCHAR cszPath[DeleteFilePath.GetLength()];  // TCHAR型 としたり、 TCHAR cszPath[256];  // TCHAR型 _tcscpy(cszPath, DeleteFilePath);  // CString型→TCHAR型 ・・・とやってみましたが、出来ません。 http://www.usefullcode.net/2006/12/post_13.html http://www5d.biglobe.ne.jp/~noocyte/Programming/Windows/WindowsTips.html#MoveToRecycleBin とかが参考になりそうです。 先程も書きましたが const _TCHAR cszPath[] = _TEXT ( "C:\\a.txt\0C:\\b.txt\0" ); の代入がうまく行きません。 ____________________________________________________________________________________________________________________________________ http://sysneitf.ifdef.jp/shell_filestotrash.html 以下、参考にした部分 // 複数ある場合は、パスを'\0'で区切る。終端は、'\0''\0'である必要がある  const _TCHAR cszPath[] = _TEXT ( "C:\\a.txt\0C:\\b.txt\0" ); // "c:\\a.txt"と"C:\\b.txt" をゴミ箱へファイルを移動するサンプル (シェルエミュレート)  SHFILEOPSTRUCT sfs;  memset ( &sfs, 0, sizeof ( SHFILEOPSTRUCT ) );  sfs.fFlags = FOF_NOERRORUI | FOF_SIMPLEPROGRESS | FOF_ALLOWUNDO;// ゴミ箱へ移動の確認をする場合  FOF_ALLOWUNDO をつける;  sfs.wFunc = FO_DELETE;  sfs.pFrom = cszPath;  if ( 0 != SHFileOperation ( &sfs ) )  {   MessageBox ( NULL,   _TEXT ( "SHFileOperation 失敗" ),   _TEXT ( "エラー" ),   MB_OK | MB_ICONSTOP );  } どなたか、お教え下さると嬉しいですm(_ _)m

  • UNICODEファイルが文字化けする

    どうしてもうまくいかず質問致します。 Visual Studio2008のMFCで、下記のコードでUnicodeファイルを読み込むと、文字化けします。  なぜでしょうか? 文字セットは、Unicodeにしています。 ログを調べているとsetlocaleや_wsetlocaleを使うとうまくいっているようですが、この環境では 解決しません。 CFileDialog seldel(TRUE, NULL,NULL, OFN_HIDEREADONLY,NULL); if(seldel.DoModal()==IDOK) { CString cpath=seldel.GetPathName(); CStdioFile cFile; cFile.Open(cpath,CFile::modeRead | CFile::shareDenyNone);// == FALSE) CString cs, cs_all; while(cFile.ReadString(cs)==TRUE) { cs_all+=cs; } ::AfxMessageBox(cs_all); } どうぞよろしくお願い致します。

  • 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で比べてみても、変わりがなく、漢字や記号の羅列でしかありません。どうか教えてください。

  • VC++でMFCアプリ作成中です。

    MFCの既存のフレームで、「最近使ったファイル」という欄があります。 これを選んだ際に、指定したプログラムでそのファイルを開きたいのですが、うまくいきません。 どうすればよろしいでしょうか? HogeView.cpp ...(省略) /*************************************** OnOpenRecentFileのオーバーライド ***************************************/ BOOL CWinApp::OnOpenRecentFile(UINT nID) { ASSERT_VALID(this); ASSERT(m_pRecentFileList != NULL); ASSERT(nID >= ID_FILE_MRU_FILE1); ASSERT(nID < ID_FILE_MRU_FILE1 + (UINT)m_pRecentFileList->GetSize()); int nIndex = nID - ID_FILE_MRU_FILE1; ASSERT((*m_pRecentFileList)[nIndex].GetLength() != 0);        /* 選んだファイルを表示 */ AfxMessageBox((*m_pRecentFileList)[nIndex]); CHogeView *myview = new CHogeView(); ★ myview->GetDocument()->SetFilePath((*m_pRecentFileList)[nIndex]); AfxMessageBox(myview->GetDocument()->GetFilePath()); myview->ReadFile((*m_pRecentFileList)[nIndex]); TRACE2("MRU オリジナル関数内: open file (%d) '%s'.\n", (nIndex) + 1, (LPCTSTR)(*m_pRecentFileList)[nIndex]); if (OpenDocumentFile((*m_pRecentFileList)[nIndex]) == NULL){ m_pRecentFileList->Remove(nIndex); } return TRUE; } /****************************************************************** ファイル読み込み ******************************************************************/ void CHogeViewerView::ReadFile(CString filename){ ...(省略) } コンパイルはできるのですが、どうやら★のところがうまく行かず、 Debug Assertion Failed! とエラーがでます。 何が原因なのでしょうか?

専門家に質問してみよう