1

What has happened to wide char printf single characters? VS10 & MCBS:

#include<stdio.h>
#include <windows.h>
int const maxPathFolder = MAX_PATH - 3;
wchar_t const *delims = L"T";
wchar_t *testString = L"Codepage is: ";
int main()
{
FILE *stream = NULL;

    UINT CP = GetConsoleOutputCP();
    wchar_t *testName= (wchar_t *)calloc(maxPathFolder, sizeof(wchar_t));
    wcscat_s(testName, maxPathFolder, L"C:\\printemp.txt");
    stream = _wfopen(testName, L"w");

    if (fwprintf(stream, L"%s%i%c", testString, CP, delims) == EOF) wprintf(L"Problems writing to File.");
    fclose (stream);
    swprintf (testName, L"%s%i%c", testString, CP, delims);
    free (testName);
}

The output in printemp.txt is Codepage is: 850? and the delims variable in swprintf'd testName is the Han character 坠. According to Igor's comments in this post, wide streams looked a little broken.

The aim ultimately is to output to file arrays of wide char to file separated by a delimiter. Some way around it?

Laurie Stearn
  • 959
  • 1
  • 13
  • 34

1 Answers1

1

Code page is outdated for the most part, Unicode replaces it. The problem here is the same as before, trying to open Unicode file in Text/ANSI mode.

Since you have tagged this as c++ you can just use Standard Library, std::wstring and std::wfstream, avoiding the headache of c-string allocation.

#include <iostream>
#include <fstream>
#include <string>
#include <io.h> //for _setmode
#include <fcntl.h> //for _O_U16TEXT

int main()
{
    //optional: for non-local languages on console
    _setmode(_fileno(stdout), _O_U16TEXT);

    //write to file (overwrite old file if any)
    wchar_t wbuf[128];
    std::wofstream fout(L"path.txt", std::ios::binary);
    if (fout) 
    {
        fout.rdbuf()->pubsetbuf(wbuf, 128);
        fout << L"ελληνικά\n";
        fout << L"English\n";
        fout << 123 << "\n";
        fout.close();
    }

    std::wifstream fin(L"path.txt", std::ios::binary);
    if (fin) 
    {
        fin.rdbuf()->pubsetbuf(wbuf, 128);
        std::wstring wstr;
        while (getline(fin, wstr, L'\n')) std::wcout << wstr << L"\n";
        fin.close();
    }

    return 0;
}

To be compatible with other software like Notepad you have to add byte order mark at beginning of the file:

fout << L"\xFEFF";

Then skip the first character (first 2 bytes) when reading the file.

If std::wstring is not an option then use new/delete operator instead of malloc.

wchar_t *testName = new wchar_t[MAX_PATH];
...
delete[] testName;
Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
  • Thanks for that. At my stage of dev, it's best to keep the code as C - like as possible. The use of things like [ostream operators](http://www.cplusplus.com/reference/ostream/ostream/operator%3C%3C/) looks great, but it needs time. Is it possible to replicate the code unfortunately "with the headache of C string allocation" in a more C-like way? – Laurie Stearn Jan 25 '16 at 02:19
  • There's a fine [post](http://stackoverflow.com/questions/2113270/how-to-read-unicode-utf-8-binary-file-line-by-line) which covers all this. Never turned up in the SO related section on the RHS though. – Laurie Stearn Jan 25 '16 at 09:14