zoukankan      html  css  js  c++  java
  • C++fstream文件流处理对中文字符不支持的解决办法

      今天由于要写代码规总,提交文档。由于文件太多一个个复制觉得麻烦,就想着自己写一个程序完成这项任务。

      任务目标:就是把指定文件夹里的所有简单文档的内容全部写入到一个文档内!!!

    【以下内容转自:我住包子山 让VS2005中的fstream支持中文路径文件打开 】

      前几天发了这篇《用fstream对二进制文件的读写》,有朋友指出了VS2005的fstream对于中文路径支持不好的bug。我想大概是因为VS2005更加重视了对字符串的全球化支持,所以鼓励我们使用unicode编码的字符串,对于MBCS之类的支持可能就疏忽了吧。

      我搜索了一下这个问题的解决,参考了如下资料写了演示代码。

       我综合了以上的内容,总结了3种方法,能够较好解决大家的困扰,包括可能无法使用cout的问题。

      PS: 补充一下,第一种方法,如果不是静态字符串当作路径的话,记得传入TCHAR*类型字符串作为路径,应该就没问题了。

    View Code
    /********************************************************************
    *    created:    2008/05/10
    *    created:    10:5:2008   23:56
    *    filename:     k:\sj\fstreamTest\fstreamTest\main.cpp
    *    file path:    k:\sj\fstreamTest\fstreamTest
    *    file base:    main
    *    file ext:    cpp
    *    author:        Gohan
    *********************************************************************/
    #include <tchar.h>
    #include <fstream>
    #include <iostream>
    using namespace std;
    int main()
    {
        /************************************************************************/
        /* 方法1,使用_TEXT()宏定义将字符串常量指定为TCHAR*类型                 */
        /* 如果是我,首选此类型                                                 */
        /************************************************************************/
        fstream file;
        file.open(_TEXT("c:\\测试\\测试文本.txt"));
        cout<<file.rdbuf();
        file.close();
    
        /************************************************************************/
        /* 方法2,使用STL中的locale类的静态方法指定全局locale                   */
        /* 使用该方法以后,cout可能不能正常输出中文,十分蹊跷                    */
        /* 我发现了勉强解决的方法:不要在还原区域设定前用cout或wcout 输出中文   */
        /* 否则后果就是还原区域设定后无法使用cout wcout输出中文                 */
        /************************************************************************/
        locale::global(locale(""));//将全局区域设为操作系统默认区域
        file.open("c:\\测试\\测试文本2.txt");//可以顺利打开文件了
        locale::global(locale("C"));//还原全局区域设定
        cout<<file.rdbuf();
        file.close();
    
        /************************************************************************/
        /* 方法3,使用C函数setlocale,不能用cout输出中文的问题解决方法同上      */
        /************************************************************************/
        setlocale(LC_ALL,"Chinese-simplified");//设置中文环境
        file.open("c:\\测试\\测试文本3.txt");//可以顺利打开文件了
        setlocale(LC_ALL,"C");//还原
        cout<<file.rdbuf();
        file.close();
    }

    运行结果

    【我的编写结果和结论】

      前面的对错暂且不论。(事实上我用过其中的方法,大致是可行的,而且从代码风格和严谨的布局注释来看,作者必成牛人!)
      1. C++流处理是不支持中文字符的。包括标准以及非标准流输入、输出、以读、写方式打开文件名、以及操作文件的路径。
      2. C++的流处理以二进制读写,“endl” 符号用txt打开后,只能看见一个黑方块。
      3. C++文件以单个字符方式读写,会把换行符丢失。

    【code 1】测试code1

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <locale>
    
    #include <windows.h>
    
    using namespace std;
    int main()
    {
        locale &loc=locale::global(locale(locale(),"",LC_CTYPE));  // 不论以输出文件流还是输入文件流,此操作应放在其两边 
        ifstream ofs(".\\op\\工作所得.txt");
        wifstream wofs(L".\\op\\工作所得1.txt"); // 当前目录开始
        locale::global(loc);  
    
        string bs;
        char ba[1024];
        ofs.getline(ba, 1024);
        cout << ba;
    
        //ofs<<"test测试"<<1234<<endl;
        //wofs<<L"Another test还是测试"<<1234<<endl;
        return 0;
    }

    【code2】 这个是我最终的成果的简单版本。(为我解决一大概40M的总代码汇总,分开汇总零散的运行近30分钟)

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <locale>
    
    #include <windows.h>
    
    using namespace std;
    
    int main(int argc, _TCHAR* argv[])
    {
        WIN32_FIND_DATA FindFileData;
        HANDLE hFind = FindFirstFile(_T(".\\op\\*.*"), &FindFileData); // 查找当前目录下op目录里的所有文件
        if (hFind == INVALID_HANDLE_VALUE) 
        {        cout << "find file err" << endl;    return 0;    } 
        else 
        {    
            FindNextFile(hFind, &FindFileData); // . 点目录
            FindNextFile(hFind, &FindFileData); // .. 两点目录。 放在循环外面
            do{
                char tempchar[1024];
                string cs_infilename = ".\\op\\" ;
                cs_infilename += FindFileData.cFileName;
                
                // 此操作放在打开操作两侧。(我原来是把out放在程序最前头,只打开一次。in放在中间每循环一次打开一次。当时没成功!!!后来改成了追加模式)
                locale &loc=locale::global(locale(locale(),"",LC_CTYPE));  
                ofstream out("unicom.txt", ios_base::app);
                ifstream in(cs_infilename.c_str());
                locale::global(loc); 
    
                cout <<"// " << cs_infilename.c_str()<<endl;    // 在控制台显示操作效果
                out <<"// " << cs_infilename.c_str()<<endl;        // 文件内注释文件名
    
                if (!in.is_open()) 
                { 
                    cout << "Error opening in file: " << cs_infilename <<endl; 
                    exit (1);
                }
                string infilebuffer;
                while (getline(in,infilebuffer))
                {
                    out << infilebuffer <<endl;
                    cout << infilebuffer <<endl;
                }
                out <<"// END: " << cs_infilename.c_str()<<endl; // END:文件内注释文件名
    
                out.close();
                in.close();
            }while (FindNextFile(hFind, &FindFileData) != 0);
        }
        FindClose(hFind);
        return 0;
    }
    世界如此的美好,江山如此的多娇! ---阳光正能量--->>>>>>>>>>>>>>>
  • 相关阅读:
    UVa 839 -- Not so Mobile(树的递归输入)
    UVa 548 -- Tree
    UVA 122 -- Trees on the level (二叉树 BFS)
    UVa679 小球下落(树)
    POJ 2255 -- Tree Recovery
    POJ 1451 -- T9
    POJ 2513 -- Colored Sticks
    STL -- heap结构及算法
    nginx利用try_files实现多个源
    nginx location的优先级
  • 原文地址:https://www.cnblogs.com/upendi/p/3072195.html
Copyright © 2011-2022 走看看