endl doesn't work with wstring (unicode)

2019-05-07 08:08发布

问题:

Here is the code:

  std::ofstream f("file1.txt");
  f<<"123"<<std::endl<<"456";           //(*1)

  /*std::stringstream ordinary_strstream; This works too
  ordinary_strstream<<"123"<<'\n'<<"456";
  f<<ordinary_strstream.str();*/

  std::wstringstream s;
  s<<L"123"<<std::endl<<L"456";         //(*2)
  s<<L"123"<<L"\n"<<L"456";             //(*3) 
  s<<"123"<<WCHAR(13)<<WCHAR(10)<<"456";//(*4)

  HANDLE h =CreateFileW(L"file2.txt", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

  ULONG l;
  WriteFile(h, s.str().c_str(), s.str().length() * 2, &l, NULL);

In the (*1) case there is a newline, in the (*2) and (*3) i see no newline in the file2.txt. In the (*3) there is a newline. I use notepad.exe for browsing. Hex editor shows no 0x0D byte, only 0x0A.

How should i properly put the newline in unicode text file? Thank you.

回答1:

That's expected: std::endl writes a L'\n' to a wide-char stream (and flushes it, but it's not relevant here), never L"\r\n". It's even more obvious when writing a literal L"\n". WriteFile doesn't perform any kind of newline substitution, neither does wstringstream (note that file streams do perform newline substitution when opened in text mode, and that's why you get a proper newline in (*1)). Therefore, in the file there will be no carriage return characters. If you want them, write them explicitely.



回答2:

Stringstreams don't do line-ending conversion. std::endl is exactly the same as \n (char or wchar, depending on context).

CreateFile doesn't do line-ending conversion; it's strictly binary.

So when you create a string with a stringstream and write it to a file with CreateFile, an endl will just be a newline (0x0A) character.

Notepad doesn't cope well with files whose line endings are just newlines instead of CR+LF.