linux C/C++获取文件编码格式+输出目标编码格式文档

入社会,首先接触的一个任务就是,获取.csv文件内容,将其解析出来。其中的附加项就是获取文件的编码格式进行判断。而我,理解错意思了,理解成了要获取编码格式并将其修改。不过,我完成了。现在分享一下。

1、首先,获取.csv文件的编码。

获取文件编码,需要使用到一个第三方库。网上很多资料说判断编码格式都不全面,不能完整的获取编码格式。我找到了一个能够获取完整编码格式的库。附上链接:https://github.com/lml123-1/uchardet

1、拉取下来后放到任意有权限的目录。如下图所示:

2、 可以打开 INSTALL文件查看编译命令。或者输入以下命令进行编译。

mkdir build; cd build
#需要说明的是下面的 /usr 可以换成其它的目录,不过运行程序时要链接到库才可以跑
cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release
make #编译
sudo make install #生成动态静态库到'/usr'目录下

3、 接下来我们就可以编写获取编码的程序了:

#include <uchardet.h>

void MyCsv::DetectFile(int iFIndex, string &strUchar) 
{
    char *cStr;
    uchardet_t handle = uchardet_new();

    // m_iFiles[iFIndex]:相当于文件描述符    m_files[iFIndex]:相当于文件名
    m_iFiles[iFIndex].open(m_files[iFIndex].c_str(), std::ios::in); 

    m_iFiles[iFIndex].seekg(0, std::ios::end);
    long long llLen = m_iFiles[iFIndex].tellg(); //获取文件长度
    cStr = new char[llLen];
    memset(cStr, 0, llLen);

    m_iFiles[iFIndex].seekg(std::ios::beg);
    m_iFiles[iFIndex].read(cStr, llLen);
    m_iFiles[iFIndex].close();

    if (uchardet_handle_data(handle, cStr, llLen) != 0)
    {
        APP_INFO_EX("handle data error");
        delete[] cStr;
        return;
    }

    uchardet_data_end(handle);
    const char *cStrset = uchardet_get_charset(handle); //得到文件的编码格式
    if (*cStrset)
    {
        strUchar = cStrset;
    }
    else
    {
        strUchar = "unknown";
    }
    APP_INFO_EX("[{}]", strUchar); //这是一个打印信息的宏

    delete[] cStr;
}

2、转换编码

需要清楚iconv这个转换编码的库。是linux自带的开源库。

#include <iostream>
#include <iconv.h>
#include <fstream>
#include <string.h>
#include <cstdio>

using namespace std;

bool CodeToCsvCode()
{
    char *buffer;
    char *nbuffer;
    size_t inLen = 65536;
    size_t llLen;
    string strRet = "GB18030";

    fstream f1;
    iconv_t ct = iconv_open("UTF-8", strRet.c_str());
    if (ct == (iconv_t) - 1)
    {
        cout << "1\n";
        return false;
    }

    buffer = new char[inLen];
    nbuffer = new char[inLen];

    cout << "2\n";
    f1.open("test.txt", std::ios::in);
    f1.seekg(0, std::ios::end);
    llLen = f1.tellg();
    f1.seekg(0, std::ios::beg);
    memset(buffer, 0, 65536);
    memset(nbuffer, 0, 65536);
    f1.read(buffer, llLen = llLen > 65536 ? 65536 : llLen);
    f1.close();

    char *oldstr = buffer;
    char *newstr = nbuffer;

    cout << strlen(buffer) << "  " << llLen << "   3\n";
    if (oldstr == NULL || &oldstr == nullptr || newstr == NULL || &newstr == nullptr)
    {
        delete [] buffer;
        delete [] nbuffer;
        cout << "5\n";
        return false;
    }
    cout << oldstr << "---" << newstr;

    //下面这个函数如果参数传错了很容易死机,内存越界
    if (iconv(ct, &oldstr, &llLen, &newstr, &inLen) == (size_t) - 1)
    {
        cout << "4 " << oldstr << newstr;
        delete [] buffer;
        delete [] nbuffer;

        iconv_close(ct);
        return false;
    }
    cout << "6\n";
    cout << nbuffer << "----" << buffer  << "\n";
    f1.open("test2.txt", std::ios::out | std::ios::trunc);
    f1 << nbuffer;
    f1.close();
    iconv_close(ct);
    delete [] buffer;
    delete [] nbuffer;
    return true;
}


int main()
{
    CodeToCsvCode();
    return 0;
}

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值