本帖最后由 happyhhb 于 2010-02-23 16:56:29 编辑

解决方案 »

  1.   

    什么头都没有直接数据的就是ANSI类型,EF  BB  BF头的就是UTF-8类型,FF FE头的就是UNICODE类型的,FE FF头的就是UNICODE BIG ENDIAN类型的,然后根据类型确定用什么类型的变量保存内容
      

  2.   

    IsTextUnicode()??????????????
      

  3.   


    CFile file;
    file.Open(_T("D:\\d.txt"),CFile::modeRead,NULL); //路径改成你自己的文件路径
    wchar_t wcText;
    file.Read(&wcText,sizeof(wchar_t)); //读取文件头来判断是哪种类型
    if(wcText == 0xFEFF)
    {
    //UNICODE
    }
    else if(wcText == 0xFFFE)
    {
    //UNICODE BIG ENDINA
    }
    else if(wcText == 0xBBEF)
    {
    //UTF-8
    }
    else
    {
    //ANSI
    }
      

  4.   

    谢谢兄弟们了,可能我表述不清楚,我这边有一堆txt文件,有 utf-8 编码的,有 ansi 编码的,文件头部都是没有 0xBBEF 之类的标志的,有可就好办多了,换个说法就是,如果用 niuxiaojia09 兄的代码,所有文件都被判定为 ansi 编码很郁闷呢。
      

  5.   

    不会吧,如果没有头,你怎么确定你的那个文件是什么类型的,比如说你 怎么知道这个文件是UTF-8类型的.从哪里看的
      

  6.   

    utf8是自编码的,不需要头标识,你用utf8方法解码如果符合,那它就是utf8编码
      

  7.   

    文件头只限于 Windows 的 UTF-8 和 UTF-16 文本,UNIX 的都没有文件头。
    主要是排除法。一直往下读文件,在几种可能的编码中,发现一种编码的非法字符就排除一种,剩下的那种就认为是了,要是读完了文件还有两种以上为被排除那就当使用率高的显示。
      

  8.   

    回复 niuxiaojia09 兄:
    1 用记事本打开,菜单-文件-另存为,就可以看到其编码格式了
    2 在我的程序里,用 ansi 方式读取ansi 编码文件,正常
                    用 ansi 方式读取utf-8编码文件,乱码
                    用 utf-8方式读取ansi 编码文件,程序出错
                    用 utf-8方式读取utf-8编码文件,正常 
    baby393 兄,谢谢了,我不只是要判断它是什么编码,还要根据编码不同使用不同的代码读取并显示文件
      

  9.   

    给你一个完整的例子,下载这份代码http://www.vckbase.com/code/downcode.asp?id=2807
    看看pfx\src\pfxeditctrl.cpp里面的BOOL CPfxEditDoc::FileIsUtf8(LPCSTR pData, LONG cch)
    和pfx\inc\pfxeditctrl.h里面的class CPfxEditDoc::class CPfxEditDocUtf8Converter类,它是一个UTF8解码类, 可重复使用。
      

  10.   

    谢谢 baby393, jennyvenusbaby393 兄,我看了你介绍的代码,是 vc7 的代码,里面 LONG nSize = Utf8CharSize(static_cast<BYTE>(*pCur)); 中的 Utf8CharSize() 是什么功能的函数呢? 
      

  11.   

    它的意思是给定一个UTF8字符的第一个字节,由这个字节去判断出整个utf8字符有多少个字节(因为UTF8编码是可变长度的),也即是如果我要读下一个UTF8字符那么指针要指向那里,或者说如果我要申请缓冲区存放解码后的数据到底要多大的缓冲区才够用。
    例如LPSTR pFileData 是你的文本数据的第一个字节
    LPSTR pNextUtf8Character = pFileData + Utf8CharSize(pFileData);// 以此类推...
    pNextUtf8Character = pNextUtf8Character + Utf8CharSize(pNextUtf8Character);其实当你判断出文本数据是UTF8格式后,你可以用Utf8ToUnicode直接将数据转换成UNICODE再处理。
    要计算整快UTF8转换后需要多大的缓冲区可以使用//这时函数返回需要的缓冲区大小
    LONG nBufferSizeInUnicode = Utf8ToUnicode(pUtf8Data, nCountOfUtf8DataSizeInBytes, NULL, 0);//申请缓冲区。
    LPWSTR pUnicodeBuffer = new WCHAR[nBufferSizeInUnicode];//解码转换(它不一定是以NULL结尾的数据。)
    Utf8ToUnicode(pUtf8Data, nCountOfUtf8DataSizeInBytes, pUnicodeBuffer, nBufferSizeInUnicode);
    //现在pUnicodeBuffer里面的是UNICODE字符可以使用了。
      

  12.   

    送你一个我以前写的函数,如果一段以'\0'结尾的字符串满足以下条件,即返回TRUE,那么它就是UTF-8。(杯具的“联通”)BOOL IsUTF8(const BYTE* lpString)
    {
    BOOL ret = TRUE;
    while (*lpString != '\0')
    {
    if (*lpString < 0x80)
    lpString++;
    else if ((*lpString >= 0xC0) && (*lpString < 0xE0))
    {
    if (((BYTE)(lpString[1] - 0x80)) < 0x40)
    lpString += 2;
    else
    {
    ret = FALSE;
    break;
    }
    }
    else if ((*lpString >= 0xE0) && (*lpString < 0xF0))
    {
    if ((((BYTE)(lpString[1] - 0x80)) < 0x40) && (((BYTE)(lpString[2] - 0x80)) < 0x40))
    lpString += 3;
    else
    {
    ret = FALSE;
    break;
    }
    }
    else if ((*lpString >= 0xF0) && (*lpString < 0xF8))
    {
    if ((((BYTE)(lpString[1] - 0x80)) < 0x40) && (((BYTE)(lpString[2] - 0x80)) < 0x40) && (((BYTE)(lpString[3] - 0x80)) < 0x40))
    lpString += 4;
    else
    {
    ret = FALSE;
    break;
    }
    }
    else if ((*lpString >= 0xF8) && (*lpString < 0xFC))
    {
    if ((((BYTE)(lpString[1] - 0x80)) < 0x40) && (((BYTE)(lpString[2] - 0x80)) < 0x40) && (((BYTE)(lpString[3] - 0x80)) < 0x40) && (((BYTE)(lpString[4] - 0x80)) < 0x40))
    lpString += 5;
    else
    {
    ret = FALSE;
    break;
    }
    }
    else if ((*lpString >= 0xFC) && (*lpString < 0xFE))
    {
    if ((((BYTE)(lpString[1] - 0x80)) < 0x40) && (((BYTE)(lpString[2] - 0x80)) < 0x40) && (((BYTE)(lpString[3] - 0x80)) < 0x40) && (((BYTE)(lpString[4] - 0x80)) < 0x40) && (((BYTE)(lpString[5] - 0x80)) < 0x40))
    lpString += 6;
    else
    {
    ret = FALSE;
    break;
    }
    }
    }
    return ret;
    }
      

  13.   


    你这个函数是有重大BUG的。
      

  14.   

    我看你的涵数的书写格式好像是已经应用的正式的代码,所以才会提醒你。作为一个C程序员操作指针的时候最重要的是什么?你把这段文本输入到你的涵数试试?
    static const BYTE str[] = {0x41, 0x42, 0x43, 0xE4, 0xB8, 0xAD, 0xE5, 0x00};
    IsUTF8(str); // 不崩溃你告诉我!!!
      

  15.   


    没崩溃我告诉你,而且我不知道你为什么说会崩溃。
    ((BYTE)(lpString[1] - 0x80)) < 0x40)这个条件在最后0x00的时候是不满足条件的,&&后面lpString[2]根本不会被访问到,直接跳else去break出循环了。
      

  16.   

    确实有一个BUG,不过不是LSS说的原因,不会崩溃,而是会死循环。UTF-8编码格式我是从与这http://www.cppblog.com/kb/archive/2005/09/19/320.aspx相似内容的网页上找过来的,这网页编码表没提首字节是0x80-0xBF以及0xFF的情况,结果我也漏了这个判断。那段代码if-else最后还要再加一个else,内容是ret = FALSE, break。
    汗!
      

  17.   

    谢谢大家咯,大家的建议给了我一点启发,我用IsTextUnicode()的int返回参数暂时解决这个问题,揭帖咯