2016-11-17 15 views
0

現在、MFCライブラリCFileクラスを学習していますが、Writeメソッドを使用してファイルにデータを書き込む際に問題があります。私は、パラメータとして文字列を渡すと、それは完全に正常に動作します:ファイルに書き込まれた書き込みメンバを使用してCStringをCFileに書き込むときに各文字の後のヌル

char c[] = "Hello!"; 
int size = sizeof(c)/sizeof(c[0]); 
myFile.Write(c, size) 

文字:

Hello! 

をしかし、私は、引数としてCStringオブジェクトを渡すしようとすると:

CString cS("Hello"); 
myFile.Write(cS, cS.GetLength()); 

入手方法:

H e l 

私も試しました:

CString cS("Hello"); 
LPWSTR c = cS.GetBuffer(); 
myFile.Write(c, cS.GetLength()); 
cS.ReleaseBuffer(); 

しかし出力は上記と同じです。その変換の原因は何ですか?テキストはワイド文字で保存されるために起こりますか?

+2

利用代わりに '' CString'のCStringA'ためのコード上で変更してみてください。 ASCII範囲のワイド文字は、1バイトのASCIIと1バイトのヌルバイトで構成されます。 –

答えて

3

問題:

CFile::Write 2番目のパラメータは、関数が最初のパラメータ(バッファ)から転送するバイト数です。 cS.GetLength()を渡していますが、これはむしろ文字列の文字数を渡します。これは、文字列自体が構成できるバイト数と同じではありません。

ソリューション:

あなたはこのような何かにファイルに文字列を書き込み、ライン変更する必要があります:あなたは、Unicodeのために構築している場合

myFile.Write(LPCTSTR(cS), cS.GetLength()*sizeof(TCHAR)); 

sizeof(TCHAR)はに基づいて異なる数が得られますまたはMBCS。これは、TCHARがUnicodeビルドではwchar_t、MBCSビルドではcharと定義されているためです。したがって、文字列の長さにTCHARのサイズを掛けると、常には、Unicode用に構築されているかどうかにかかわらず、文字列が構成されているバイト数と同じになります。注意すべき

その他の見所:

あなたは一切、ここGetBuffer()ReleaseBuffer()をコールする理由をしたん。

この点はメジャーではありませんが、CFile::Write関数の最初の引数はconst void *です。したがって、CStringLPCTSTRにキャストする必要があります(ユニコードまたはMBCSを使用している場合は、LPCWSTRまたはLPCSTRに自動的に評価されます)。

最後のこと:コードを変更せずにUnicodeとMBCSの両方でコンパイルできるように、_T()マクロで文字列リテラルをラップするとよいです。すべての変更を適用する

、あなたの全体のコードは次のようになります:

CString cS(_T("Hello")); 
myFile.Write(LPCTSTR(cS), cS.GetLength()*sizeof(TCHAR)); 
+0

意味的に、 'sizeof(TCHAR)'は 'sizeof(cS :: XCHAR)'でなければなりません。これは、すべての 'CStringT'由来の文字列型の定義済みの文字型です。私は明示的にキャスティングすることをお勧めします。変換演算子は暗黙的に呼び出されます。明示的にするには、代わりに 'GetString()'メンバと呼ぶことができます。これにより、誤って変換演算子が呼び出されることを防ぎます。 – IInspectable

+0

@IInspectable 'sizeof(cS :: XCHAR)'とタイプしてコンパイルしてもらえないと思います。私はあなたがおそらく 'sizeof(CString :: XCHAR)'を意味したと思いますが、それは 'sizeof(TCHAR)'とまったく同じことになります。また、 'LPCTSTR'は実際には演算子であることに注意してください:https://msdn.microsoft.com/en-us/library/aa300569(v=vs.60).aspx –

+0

*"おそらく 'sizeof(CString :: XCHAR) ''しかし、これは 'sizeof(TCHAR)'とまったく同じことになるでしょう。 "* - それは同じタイプを指定します。しかし、意味の違いがあります: 'TCHAR'は単なる無関係な型ですが、' XCHAR'は 'CString'の実装で使われている型です。* "また、' LPCTSTR'は実際には演算子 "*であることに注意してください。それでも暗黙のうちに呼び出されます。ドキュメントへの正しいリンクは、[ここ](https://msdn.microsoft.com/en-us/library/sddk80xf.aspx#csimplestringt__operator_pcxstr)です。 – IInspectable

0

これは、UNICODEで定義されているためです。CStringは、それぞれが2バイトを占めるワイド文字の文字列です。あなたのファイルに書かれているものは、あなたが文字バイトとして見ているもので、その後に0バイトが続きます。

+3

'GetLength'がバイト数ではなく文字数を返し、' Write'が必要とするものの半分を返すように明示的に編集する価値があります。 – user4581301

0

私はMFCのVisual C++ 6.0からVisual C++ 2005まで約4年間開発しています。これは現在、私たちの企業アプリケーションを専門的にサポートするためです。

私の経験では、CStringクラスオブジェクトについて知っていますが、それらは常にNULLで終了しました。これは、文字配列を使用する場合とは異なる動作を引き起こす可能性がありますが、上記の問題ではありません。

あなたの問題は、あなたが引数として渡しているバッファに関係していると思います。 LPWSTRは、このMSDN Referenceあたりの16ビット文字列への32ビットポインタです。

あなたが投稿した内容に基づいてわかることは、ANSIと表示されているため、16ビットのUnicode文字を表示しているため、この動作が予想されます。メモ帳ファイルをUnicodeとして開くと、スペースが表示されません。

ANSI文字セットを使用してプロジェクトをビルドするか、ファイルに書き込む前にANSIに変換すると、メモ帳で出力を開くときにスペースがなくなります。

0

この

TCHAR c[] = "Hello!"; 
int charCount = sizeof(c)/sizeof(c[0]); 
myFile.Write(c, charCount*sizeof(c[0])); 

書き込みが指定されたバイト数だけを書き込みますしてみてください。 charCountはASCIIのバイト数と同じですが、UNICODEの半分の値になります。

は、テキストのあなたのタイプ

https://msdn.microsoft.com/en-us/library/6337eske.aspx

関連する問題