Search code examples
cwinapifile-ioutf-8carriage-return

fwprintf puts carriage-return before linefeed


My WinAPI program aims to take text from an Edit control and save it to a file.

When fopen creates the file in text mode "w", then fprintf makes linefeed LF character be preceded by a carriage-return CR.

HWND hEdit = CreateWindowA( "Edit", NULL, WS_CHILD|ES_MULTILINE, 0, 0, 100, 100, 
                            hWnd, (HMENU)ID_EDITORE, GetModuleHandle(NULL), NULL );
// Input in Edit control a single line break "\r\n"
int num = GetWindowTextLength(hEdit);
char buffer[num+1];
GetWindowText( hEdit, buffer, num+1 );
FILE* file = fopen( "test.txt", "w" );
fprintf( file, "%s", buffer );

Above code doesn't write CR LF in the file, but:

CR CR LF (0D 0D 0A)

I know here in the ANSI version the solution is to open the file in binary mode: "wb" instead of "w", that makes no CR LF translation or character conversion occur during output.

But I want to input Unicode characters in Edit control, and have the file encoded UTF-8 with BOM.
So what about the wide-character versions _wfopen and fwprintf?

HWND hEdit = CreateWindowW( L"Edit", ... );
// Input in Edit control a single line break "\r\n"
int num = GetWindowTextLength(hEdit);
wchar_t buffer[num+1];
GetWindowTextW( hEdit, buffer, num+1);
FILE* file = _wfopen( L"test.txt", L"w,ccs=UTF-8" );
fwprintf( file, L"%s", buffer );

Above code doesn't write ï » ¿ CR LF in the file, but:

ï » ¿ CR CR LF (EF BB BF 0D 0D 0A)

No way here to use the "b" binary mode to avoid the CR addition.

FILE* file = _wfopen( L"test.txt", L"wb,ccs=UTF-8" );

Writes in the file the expected \r\n but encoded UTF-16, without any BOM:

CR NUL LF NUL (0D 00 0A 00)

How avoid this CR proliferation for a UTF-8 file?
Am I forced to encode it UTF-16?

Thanks for any suggestion.


Solution

  • As suggested, a possible solution is remove all CRs before writing buffer into file.
    Then fwprintf cares to put a CR before each LF restoring the pairs \r\n.

    HWND hEdit = CreateWindowW( L"Edit", ... );
    int num = GetWindowTextLength(hEdit);
    wchar_t buffer[num+1];
    GetWindowTextW( hEdit, buffer, num+1 );
    
    for( int i=0, id=0; id<=num; i++, id++ ) {
        while( buffer[id]=='\r' )
            id++;
        buffer[i] = buffer[id]; 
    }
    
    FILE* file = fopen( "test.txt", "w,ccs=UTF-8" );    
    fwprintf( file, L"%s", buffer );
    fclose(file);