简体   繁体   中英

Nulls after each character when writing CString to CFile using Write member

I'm currently studying MFC library CFile class and I have a problem with writing data to a file using Write method. When I pass char array as parameter it works perfectly fine:

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

Characters that were written to file:

Hello!

But when I try to pass CString object as an argument:

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

I get:

H e l

I also tried:

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

But the output is the same as above. What may be cause that conversion? Does it happen because text is stored in wide characters?

Problem:

The second parameter to CFile::Write is the number of bytes that the function will transfer from the first parameter (the buffer). You're passing cS.GetLength() , which would rather pass the number of characters in the string, and this is not the same as the number of bytes that the string itself may be composed of.

Solution:

You should change the line that writes the string into file to something like this:

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

sizeof(TCHAR) will yield a different number based on if you're building for Unicode or MBCS. This is because TCHAR is defined as wchar_t for Unicode builds, and as char for MBCS builds. As such, multiplying the length of string with the size of TCHAR will always equal the number of bytes the string is composed of regardless of if you're building for Unicode or not.

Other points to note:

You've no reason to call GetBuffer() and ReleaseBuffer() here, whatsoever.

This point is not a major, but the CFile::Write function takes a const void * as its first argument. So you should rather be casting your CString to LPCTSTR (which would automatically evaluate to LPCWSTR or LPCSTR based on if you're building with Unicode or MBCS).

One last thing: It's good to wrap string literals with the _T() macro so that you could compile for Unicode and MBCS alike without having to change your code.

Applying all changes, your whole code would look something like this:

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

That's because you're compiling with UNICODE defined, and CString is a string of wide characters, each of which occupies two bytes. What's getting written to your file is what you're seeing as the character byte, followed by a zero byte.

I have been developing in MFC, Visual C++ 6.0 to Visual C++ 2005 for about 4 years now professionally to support our companies applications.

In my experiences and what I know of the CString class objects, they are always NULL terminated. This can cause different behavior than using a character array, but is not the problem above.

I believe your problem to be related to the buffer you are passing in as an argument. LPWSTR is a 32-bit pointer to a string of 16-bit characters per this MSDN Reference .

From what I can tell based on what you posted, you are outputting 16 bit Unicode characters and viewing them as ANSI hence this behavior would be expected. If you were to open your notepad file as Unicode , you would not see the spaces.

Alternatively, if you build your project using ANSI character set, or convert to ANSI prior to writing to the file, the spaces should go away when you open the output in notepad.

try this

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

Write will write only number of bytes specified. charCount will be same as number of bytes for ASCII, but will be half the value for UNICODE.

Try changing above code for your type of text

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM