标题:”控制台输出多种格式文本不乱码“ 程序从Win11嫁到了XP 又乱码了
取消只看楼主
追梦人zmrghy
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:399
专家分:190
注 册:2021-4-9
结帖率:97.22%
已结贴  问题点数:20 回复次数:3 
”控制台输出多种格式文本不乱码“ 程序从Win11嫁到了XP 又乱码了
“控制台输出多种格式文本不乱码” 程序从Win11嫁到了XP 又乱码了!!!
这是咋回事呀!!!
啥都不是的玩意,,,,太让人生气了,程序从Win11嫁到了XP 5个txt文件只输出 3个,而且全是乱码。。。。


大家能不能告诉我什么原因,或者帮我分析一下是什么情况。。。。
不然,就凭我自己,10天半个月能找出原因,就不错了。。。。
就怕10天半个月也找不出原因!!!

麻烦大家,帮我分析一下什么原因。。。

[此贴子已经被作者于2022-9-16 14:26编辑过]

搜索更多相关主题的帖子: 输出 XP 格式 原因 乱码 
2022-09-16 14:24
追梦人zmrghy
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:399
专家分:190
注 册:2021-4-9
得分:0 
回复 2楼 纯蓝之刃
我看过了,在XP中控制台 编码是936 GBK
在win11中控制台 编码也是936 GBK

并且,我的程序就是把UTF-8 转成 ANSI 936 (GBK)

[此贴子已经被作者于2022-9-16 14:37编辑过]

2022-09-16 14:34
追梦人zmrghy
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:399
专家分:190
注 册:2021-4-9
得分:0 
越怕麻烦,就越麻烦。。。。。
俗话说的好呀,不入鼠穴,焉得鼠子。。。。
直截了当,不就是程序到了XP后,乱码了吗!!!
越想省事,结果可能越麻烦。。。。
直接在XP虚拟机上,安装VS2010,用源代码、DEBUG、加断点,找出原因。。。。




GBK、UTF-8是成乱码UTF-16可以显示。。。最后一篇只有一个字???





文件编码识别,没有问题。 问题在读取,转码,和输出 环节上。。。






cout和printf输出都是乱码。。。。
可以看到buffer中内容正确不是乱码,ANSI 是936 GBK 不需要转码, 问题出在输出环节上。




枯腾老树昏鸦,
小桥流水人家,
古道西风瘦马。
夕阳西下,断肠人在天涯。

为什么,只输出了一个“枯”字。。。
这首诗是 UTF-16 BE上一首诗是UTF-16 LE显示正常。
这首诗是 由UTF-16 BE转换UTF-16 LE 再显示。
捣腾半天,没有找出原因。自己重新写了一个UTF-16 BE转换UTF-16 LE 的函数。
自己写的函数,结果完全一样,还只有一个“枯”字。。。
这下子,傻掉了。。。。。。。。
最后发现在XP系统上UTF-16 LE编码 “腾” 0x7E81 就是这个字代码的问题。。。。

现在,问题找到答案了。。。。总算,结束了,几年的乱码历史了。。。。
有问题,可以绕路走。以后乱码,终于不必再绕路了。。。。。。。。

[此贴子已经被作者于2022-9-17 11:05编辑过]

2022-09-17 02:02
追梦人zmrghy
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:399
专家分:190
注 册:2021-4-9
得分:0 



原程序使用cout 输出BGK, 使用_wsetlocale(LC_ALL, L"chinese");  wcout输出UTF-16LE, UTF-16BE转换成UTF-16LE再输出。

乱码原因,在XP中wsetlocale(LC_ALL, L"chinese")设置 wcout输出“中文”后,cout再输出“中文”就会出现乱码!!!

“腾”0x7E81 代码又出了问题!!!
刚好不再使用,wsetlocale(LC_ALL, L"chinese"), wcout输出“中文”

全部使用GBK输出,即解决了 “腾”0x7E81 代码问题, 又解决了 设置 wcout输出“中文”后,cout再输出“中文”乱码的问题

程序代码:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include<locale.h>

#include"iconv.h"
#pragma comment(lib, "libiconv.lib")
#pragma warning(disable:4996)

using namespace std;

typedef unsigned int Uint32;

enum TEXT_TYPE
{
    TEXT_ANSI = 0,
    TEXT_UTF8 = 1,
    TEXT_UTF8_BOM = 2,
    TEXT_UTF16_LE = 3,
    TEXT_UTF16_BE = 4,
    TEXT_UNKNOW = 5,
};

class File {
public:
    File() { _ptr_file = nullptr; }
    File(const char* fn, const char* opr) {
        open(fn, opr);
    }
    ~File() { close(); }
    //读取文件到内存
    static char* read_file(Uint32& size, const char* fn) {
        File tmp_file;
        if (tmp_file.open(fn, "rb")) { return size = 0, nullptr; }
        size = tmp_file.get_file_size();
        char* buf = (char*)malloc(size + 4);///这里多分配几个字节做字符串结尾
        if (!buf) { return size = 0, nullptr; }
        memset(buf, 0, size + 4); ///内存填充0
        size = tmp_file.read_byte(buf, size);
        return buf;
    }
    ///获取文本文件类型
    ///文件类型:utf-8返回0
    /// utf8 bom 返回1
    /// ucs-2 BE大端字节序返回2
    /// USC-2 LE小端字节序返回3
    /// 文件不存在返回 -1
    /// 
    static int get_file_type(const char* fn) {
        File temp_file;
        if (temp_file.open(fn, "rb")) { return -1; }
        if (temp_file.get_file_size() <= 2) { return 0; }
        char en_buf[3] = { 0 };
        temp_file.read_byte(en_buf, 3);
        if (0 == memcmp(en_buf, "\xEF\xBB\xBF", 3)) { return 1; }
        else if (0 == memcmp(en_buf, "\xFE\xFF", 2)) { return 2; }
        else if (0 == memcmp(en_buf, "\xFF\xFE", 2)) { return 3; }
        return 0;
    }
    int open(const char* fn, const char* opr) {
        close();
        _ptr_file = fopen(fn, opr);
        if (!_ptr_file) { return-1; }
        return 0;
    }
    void close() {
        if (!_ptr_file) { return; }
        fclose((FILE*)_ptr_file);
    }
    ///获取文件大小
    Uint32 get_file_size() {
        int cur_pos = ftell((FILE*)_ptr_file);
        fseek((FILE*)_ptr_file, 0L, SEEK_END);
        Uint32 ret = ftell((FILE*)_ptr_file);
        fseek((FILE*)_ptr_file, cur_pos, SEEK_SET);
        return ret;
    }
    ///读取size个字节到dst///
    Uint32 read_byte(char* dst, Uint32 size) {
        Uint32 min_size = min(size, get_file_size());
        fread(dst, 1, min_size, (FILE*)_ptr_file);
        return min_size;
    }
private:
    void* _ptr_file;
    //DISALLOW_COPY_AND_ASSIGN(File)
private:
    File(File&);
    File& operator=(File&);
};

//检查是否为无BOM的UTF8
bool check_utf8_without_bom(const string& file_name)
{
    ifstream file_in;
    file_in.open(file_name, ios::in);

    if (!file_in.is_open())
    {
        cout << "打开文件失败" << endl;
        return false;
    }

    stringstream buffer;
    buffer << file_in.rdbuf();
    file_in.close();
    string text = buffer.str();

    size_t len = text.size();
    int n = 0;
    unsigned char ch;
    bool b_all_ascii = true;

    //0x00-0x7F为ASCII码范围

    for (size_t i = 0; i < len; ++i)
    {
        ch = text[i];

        if ((ch & 0x80) != 0)
        {
            b_all_ascii = false;
        }

        if (n == 0)
        {
            if (ch >= 0x80)
            {
                if (ch >= 0xFC && ch <= 0xFD)
                {
                    n = 6;
                }
                else if (ch >= 0xF8)
                {
                    n = 5;
                }
                else if (ch >= 0xF0)
                {
                    n = 4;
                }
                else if (ch >= 0xE0)
                {
                    n = 3;
                }
                else if (ch >= 0xC0)
                {
                    n = 2;
                }
                else
                {
                    return false;
                }
                n--;
            }
        }
        else
        {
            if ((ch & 0xC0) != 0x80)//在UTF-8中,以位模式10开始的所有字节是多字节序列的后续字节
            {
                return false;
            }
            n--;
        }
    }

    if (n > 0)
    {
        return false;
    }

    if (b_all_ascii)
    {
        return false;
    }

    return true;
}

//检查文本编码
TEXT_TYPE check_text_encode(const string& file_name)
{
    /*
    ANSI                     无格式定义                        对于中文编码格式是GB2312;
    Unicode little endian    文本里前两个字节为FF FE           字节流是little endian
    Unicode big endian       文本里前两个字节为FE FF           字节流是big endian
    UTF-8带BOM               前两字节为EF BB,第三字节为BF     带BOM
    UTF-8不带BOM             无格式定义,需另加判断               不带BOM
    */

    ifstream file_in(file_name, ios::binary);
    if (!file_in.is_open())
    {
        cout << "打开文件失败" << endl;;
        return TEXT_UNKNOW;
    }

    int head;
    unsigned char ch;
    file_in.read((char*)&ch, sizeof(ch));
    head = ch << 8;
    file_in.read((char*)&ch, sizeof(ch));
    head |= ch;

    file_in.close();
    TEXT_TYPE result_code;
    switch (head)
    {
    case 0xFFFE:
        result_code = TEXT_UTF16_LE;
        break;
    case 0xFEFF:
        result_code = TEXT_UTF16_BE;
        break;
    case 0xEFBB:
        result_code = TEXT_UTF8_BOM;
        break;
    default:
        if (check_utf8_without_bom(file_name))
            result_code = TEXT_UTF8;
        else
            result_code = TEXT_ANSI;
        break;
    }
    return result_code;
}
int code_convert(char* to_chatset, char* from_charset, const char* inbuf, size_t inlen, char* outbuf, rsize_t outlen)
{
    iconv_t cd, err = (iconv_t)-1;

    cd = iconv_open(to_chatset, from_charset);
    if (cd == err)return -1;

    int ret = iconv(cd, &inbuf, &inlen, &outbuf, &outlen);
    if (ret == -1)return -1;

    iconv_close(cd);
    return outlen;
}

void ReadFile(string filepath)
{
    Uint32 size;
    char* buffer = nullptr;
    char* newbuffer = nullptr;
    Uint32 newsize;
    TEXT_TYPE type = check_text_encode(filepath);
    if (type != TEXT_UNKNOW)
    {
        size = 0;
        buffer = File::read_file(size, filepath.c_str());
        switch (type)
        {
        case TEXT_ANSI:
            cout << std::string(buffer);
            break;
        case TEXT_UTF8:
            newsize = size;
            newbuffer = new char[newsize];
            memset(newbuffer, 0, newsize); 
            code_convert((char*)"GBK", (char*)"UTF-8", buffer, size, newbuffer, newsize);
            cout << std::string(newbuffer);
            free(newbuffer);
            break;
        case TEXT_UTF8_BOM:
            newsize = size;
            newbuffer = new char[newsize];
            memset(newbuffer, 0, newsize); 
            code_convert((char*)"GBK", (char*)"UTF-8", buffer + 3, size-3, newbuffer, newsize);
            cout << std::string(newbuffer);
            free(newbuffer);
            break;
        case TEXT_UTF16_LE:
            newsize = size;
            newbuffer = new char[newsize];
            memset(newbuffer, 0, newsize); 
            code_convert((char*)"GBK", (char*)"UTF-16LE", buffer+2, size-2, newbuffer, newsize);
            cout << std::string(newbuffer);
            free(newbuffer);
            break;
        case TEXT_UTF16_BE:
            newsize = size;
            newbuffer = new char[newsize];
            memset(newbuffer, 0, newsize); 
            code_convert((char*)"GBK", (char*)"UTF-16BE", buffer+2, size-2, newbuffer, newsize);
            cout << std::string(newbuffer);
            free(newbuffer);
            break;
        default:
            break;
        }
        free(buffer);
    }

}

int main(int argc, char* argv[])
{
    string File1 = "C:\\TestFile\\ANSI.txt";
    string File2 = "C:\\TestFile\\UTF-8.txt";
    string File3 = "C:\\TestFile\\UTF-8 BOM.txt";
    string File4 = "C:\\TestFile\\UTF-16 LE.txt";
    string File5 = "C:\\TestFile\\UTF-16 BE.txt";

    ReadFile(File1);
    ReadFile(File2);
    ReadFile(File3);
    ReadFile(File4);
    ReadFile(File5);
    return 0;
}


FileType.cpp (8.09 KB)

2022-09-17 10:51



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-510053-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.168392 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved