ifstream 's mistake in vc8, correct in vc7.1

When I use ifstream 's constructor to open a text file,
the text file's filename contain chinese char,
and the filename is in Multi-Byte Character Set style (const char *),
I success in vc7.1 but fail in vc8.

Trace the library's source code, I found in vc8, the ifstream will call
mbstowcs_s to convert the input filename form MBCS to wide-char,
mbstowcs_s will call _mbstowcs_l_helper to do that, but it get
the wrong string in my english ver. OS.

I am so curious why to do that, it is total excrescent.

PS:
I use API MultiByteToWideChar can get the correct string.

    // Convert ANSI string to Unicode
    int result = MultiByteToWideChar( CP_ACP, 0, src,
        src_len, wchar_buf,  
        BUF_LEN);



----------------- test code ------------------------------

#include "stdafx.h"
#include <iostream>
#include <fstream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    ifstream ifs("c:/事.txt");

    if (!ifs)
    {
        return -1;
    }

    return 0;
}



Answer this question

ifstream 's mistake in vc8, correct in vc7.1

  • Dhirendra

    Interesting, thanks for the info, I was trying on a Chinese machine (i.e. system locale, or language for non-Unicode programs set to Chinese in regional settings) and it worked.
  • Roundtwoit

    As you see in the code, it uses the CRT's current locale setting (a global state setting set to "C" by default)   As I said before you just need to call

    setlocale(LC_CTYPE, "")

    once at the beginning of your program. 

    Then all will work properly.




  • chipscap

    You first need to call setlocale(LC_CTYPE, "") otherwise it will use the "C" locale (look at C:\Program Files\Microsoft Visual Studio 8\VC\crt\src\mbstowcs.c and look for _CLOCALEHANDLE )




  • Tatjana

    Thanks, Ted. I'm not very familiar with Unicode stuff.
    The problem occurs when I switch my app from mbcs to Unicode. So in mbcs mode(which i use ifstream), it works well (except that I have to call _tsetlocale(LC_CTYPE,_T(".ACP")) as you suggested to make 2005 correctly handle mbcs filename). The issue appears when i turn to Unicode, then the problem is related to the following funciton (by the way, when using unicode, I need not use setlocale, the overloadded w_char ver of "open" can handle the unicode filename correctly):
    codecvt_base::do_in
    it use following code to test if the current char in buffer is partial
    switch (_Bytes = _Mbrtowc(_Mid2, _Mid1, _Last1 - _Mid1,
        &_State, &_Cvt))
    and it always return ok by default (in c locale, which _Cvt==0).
    And just call _tsetlocale(LC_CTYPE,_T(".ACP")) will not influence the value of _Cvt, so I have call locale::global(locale(".ACP",locale::ctype)) explicitly. It seems that the c & c++ locale setting function are not related

  • Satpal

     Ted. wrote:
    You first need to call setlocale(LC_CTYPE, "") otherwise it will use the "C" locale (look at C:\Program Files\Microsoft Visual Studio 8\VC\crt\src\mbstowcs.c and look for _CLOCALEHANDLE )





    Thx, I call setlocale( LC_ALL, ".ACP" ); first to solve this problem,
    But...... , I did not like the way MS change ifstream that much.

  • Gregor Bussmann

    I found that the default locale of fstream is "C"
    when i use the following code to read ansi file
    wifstream f(_T("E:\\Table1.txt"));
    wstring str;
    f>>str;
    then f will not correctly handle mbcs chars (for example, it will always treat one chinese character as two seperate chars. like read 0xb7 0x9a as L0xb7 L0x9a)
    so i have to add following code after every ifstream object
     f.imbue(locale(".ACP")); //my windows system is chinese
    Is there anyway to globally set the "default" locale used by fstream to ACP
    (i find that the default locale is set in the following code:
    basic_streambuf()
      : _Plocale(_NEW_CRT(locale))
    which in turn call _Getgloballocale
    it seems that just call _tsetlocale(LC_ALL,_T(".ACP")); doesn't take effect
    )

  • Pamish

    Thanks for your answer.
    but as i tried, just call setlocale will not take effect
    now i use "locale::global(locale(".ACP",locale::ctype))", that works well.

  • hoosierboy

    Please feel free to log a suggestion issue showing your opinion at http://lab.msdn.microsoft.com/productfeedback/default.aspx

    Thanks in advance for taking the time to share your views.

    Thanks,
      Ayman Shoukry
      VC++ Team

  • Andy Knight

    I encountered the same problem.
    ifstream cannot correctly handle MBCS filename in ANSI mode
    So I have to switch to use CFile instead

  • ifstream 's mistake in vc8, correct in vc7.1