質問: '\0'; cout << L"FileRead Successed" << endl; cout << lpszbuf << endl; } CloseHandle(file); GlobalUnlock(hMemory); GlobalFree(hMemory); return 0; } ``` ### 質問 `lpszbuf`はポインターなのでしょうか? 確保した文字列がメモリ上で断続的だった場合の文字列はどうやって取り出せるのでしょうか? 取り出した値はバイナリになりますか?バイナリならどうやってUNICODE等に変換できるのでしょうか? あとコード上で使い方がおかしいものがあったらご指摘ください。 【追記】得たバイナリを`wcout`で吐き出すためにはどう記述するのが正しいのでしょうか ### 補足情報 Visual C++ VisualStudio 2017 Community Windows10 Pro メモリ:16GB
回答: ご質問に順番に回答させていただきます。 > > lpszbuf はポインターなのでしょうか? > > > ポインターです。`LPWSTR` は、`wchar_t*` をtypedef したものです。(実際はもう少しややこしいですが) Windows Data Types.aspx) SDKのヘッダーファイル winnt.h に定義があると思いますので、そちらも見てみましょう。 > > 確保した文字列がメモリ上で断続的だった場合の文字列はどうやって取り出せるのでしょうか? > > > データ構造によりますが、自分でがんばって探し、取り出すしか無いと思います。 > > 取り出した値はバイナリになりますか?バイナリならどうやってUNICODE等に変換できるのでしょうか? > > > `ReadFile`でファイルに書いてある内容そのままで指定のメモリに読み出しますので、その文字列のデータがシフトJISなり、ただのASCIIコードなり、UNICODEでないならば、プログラマー自身が変換する必要があります。 ネイティブのAPIとしてはWideCharToMultiByteやMultiByteToWideCharの文字コード変換用APIがありますが、勉強を目的とする以外でこれらを直接使うことは今ではほとんど無いと思います。もっと便利な方法があります。 方法: さまざまな文字列型間で変換する `WideCharToMultiByte`らの意味を理解したならば、これらの便利なものを使うことも検討しましょう。 > > あとコード上で使い方がおかしいものがあったらご指摘ください。 > > > そうですね、気がついたものとしては * `HANDLE file`や`LPWSTR lpszbuf`がグローバル変数である必然性が無い。 * `LPTSTR`(TCHAR配列のポインター)と`LPWSTR`(WCHAR/wchar_t配列のポインター)の意識が混在している。※`TCHAR`はマルチバイト(_MBCS)とUNICODE(_UNICODE)の双方で同じコードで書くためのものです。 * `ReadFile` の返り値は`BOOL` なので、 実行結果の判定として `!= 0`は不適切。 * `GlobalAlloc(GHND...)`~`GlobalLock`~ `GlobakUnlock`~`GlobaFree` の一連の流れは作法としては正しいのですが、短期間であるならば、Cランタイムの`malloc`~`free`で充分かと思います。`GHND`フラグ(`GMEM_MOVEABLE|GMEM_ZEROINIT`)を指定した`GlobalAlloc`の使用は、昔、PCのメモリが少なかった頃に有用だったもので、現在のPC+普通のアプリケーションで厳密に使い分けるほどに有用なものでもありません。 あと、問題がある部分としては * `GlobalAlloc`で取得したhMemoryが`NULL`であった場合でも、処理を続行している。 * `ReadFile`実行後、`lpszbuf[accbytes] = '\0';` でNULL文字を埋め込んでいるが、`lpszbuf`は`wchar_t`型のポインターなので、実際に読み込んだバイト長 * 2 の位置に`'\0'`を挿入してしまっている。(メモリを破壊している) また、`L'\0'` との表記の方がより適切。 * `cout`を使う部分ですが、`cout` では`L`で指定したワイド文字列(UNICODE)は出力できないです。`wcout` を使う必要があります。 です。