关于c++的文件编码的研究

    今天很有成就感,倒不是做出了多牛的东西,而是终于可以动态的进行编码的各种转换了。

    其实这个用到的是网上一搜一大片的iconv,目前有windows版和linux版,linux下的很容易找到,直接装上就可以进行开发了,windows下的包可以通过这个链接下载:win-iconv-0.0.4.zip,直接将放入工程内,就可以使用了。

     下面给出我自己的测试代码(基于文件的):

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <fstream>
#include "include/iconv.h"

using namespace std;

int main(void)  
{
    string src("");
    char buf[4096];
    int fileLen = 0;
    ifstream file1("sohu.htm");
    while(!file1.eof())
    {
        memset(buf, 0, 4096);
        file1.read(buf, 4096);             
        int readLen = file1.gcount();
        buf[readLen] = '\0';
        printf("readline: \n %s\n", buf);     
        src.append(buf);
        fileLen += readLen;
    }
    
    file1.close();
    char *dest = new char[src.length() * 2 + 1]; /* 格式化转换后的字串 */  
    memset(dest, 0, src.length() * 2 + 1);
    size_t src_len = src.length();  
    size_t dst_len = src.length() * 2;          //注意:我用了一块2倍于源数据长度的buffer 
    const char *in = src.c_str();  
    char *out = dest;  
      
    iconv_t cd;
      
    cd = iconv_open("utf-8", "gb2312");         /* 将GB2312字符集转换为UTF-8字符集 */  
    if ((iconv_t)-1 == cd)
    {  
        printf("iconv_open err %d\n", errno);
        return -1;  
    }  
  
    if(iconv(cd, &in, &src_len, &out, &dst_len) == -1) /* 执行转换 */ 
    {  
        printf("iconv_open err %d\n", errno);
        return -1;  
    }  

    ofstream file2("out.txt");
    file2.write(dest, src.length() * 2 - dst_len);
    file2.close();
      
    iconv_close(cd); /* 执行清理 */  
    return 0;  
}  

 我在写代码的时候,遇到了两种错误:

(1)返回errno=7,即E2BIG

    问题原因:目的内存的大小不够

    解决办法:就是使用的分配2倍于源数据大小的空间,由于编码转换会导致数据量的变化

(2)返回errno=42,即ENOMSG

    问题原因:源数据的编码与iconv_open输入的源编码不同

    解决办法:就是找到源数据的真正编码,使用uchardet对字符串进行分析得出真正的编码格式

如何使用uchardet?

uchardet_t m_uchardet = uchardet_new();
if(m_uchardet)
{
    if(uchardet_handle_data(m_uchardet, m_content.c_str(), m_content.length()) == 0)
    {
         uchardet_data_end(m_uchardet);
         m_charSet.assign(uchardet_get_charset(m_uchardet));
    }
}
uchardet_delete(m_uchardet);

uchardet源码下载路径:

BYVoid-uchardet-56a4c0d.zip

类似的,对内存中的数据进行编码转换也可以用这个方法,最终输出的文件编码格式就是当初设置的目标编码格式。

posted @ 2012-08-29 15:58  Geek_Ma  阅读(2036)  评论(0编辑  收藏  举报