C++读取文本文件

    技术2022-05-20  38

     

    写在开始

    最近在做一个东东,遇到文件读取的问题,遂开始研究,使用C++读取文本文件比较简单,也是一个很好的切入点,所以进行了一些小实验。

     

    这里仅仅举例,使用ANSI,UNICODE,UTF-8三种常用的文本文件作为示例

     

     

    关于文本文件的文件头

    第一 ANSI文件的文件头为空,不需要处理;

    第二 UNICODE文件的文件头为0xFF,0xFE共计两个字节,读取时需要偏移两个字节再行读取;

    第三 UTF-8文件的文件头为0xEF,0xBB,0xBF共计三个字节,读取时需要偏移三个字节后再行读取;

     

     

    关于文本文件类型的判断

    根据文本文件的文件头,可以判断文本文件的类型

    假设有如下文件类型定义:

    typedef enum FileType

    {

        ANSI = 0,

        UNICODE,

        UTF8,

    }FILETYPE;

     

    我们就可以根据上述特性,来判断文本文件的类型了,下面是一段示例代码:

    FILETYPE GetTextFileType(const std::string strFileName)

    {

        FILETYPE fileType = ANSI;

        std::ifstream file;

        file.open(strFileName.c_str(), std::ios_base::in);

     

        bool bUnicodeFile = false;

        if (file.good())

        {

            char szFlag[3] = {0};

            file.read(szFlag, sizeof(char) * 3);

            if ((unsigned char)szFlag[0] == 0xFF 

            && (unsigned char)szFlag[1] == 0xFE)

            {

                    fileType = UNICODE;

            }

            else if ((unsigned char)szFlag[0] == 0xEF 

            && (unsigned char)szFlag[1] == 0xBB 

            && (unsigned char)szFlag[2] == 0xBF)

            {

                fileType = UTF8;

            }

        }

     

        file.close();

     

        return fileType;

    }

     

     

    ANSI文本文件的读取

    ANSI文本文件不需要进行文件头的处理,可以直接读取。

    下面是简单示例:

    char szBuf[FBLOCK_MAX_BYTES];

    memset(szBuf, 0, sizeof(char) * FBLOCK_MAX_BYTES);

     

    std::string strMessage;

     

    FILE * fp = NULL;

    fp = fopen(strFileName.c_str(), "rb");

    if (fp != NULL)

    {

        // common file do not offset.

        while(fread(szBuf, sizeof(char), FBLOCK_MAX_BYTES, fp) > 0)

        {

            strMessage += szBuf;

            memset(szBuf, 0, sizeof(char) * FBLOCK_MAX_BYTES);

        }

    }

     

    std::cout << strMessage << std::endl;

     

    fclose(fp);

     

     

    UNICODE文本文件读取

    由于UNICODE普遍采用双字节来表示字符,因此读取时,当使用wchar_t类型来读取,使用fopen,fread来进行操作。

    下面是简单示例:

    wchar_t szBuf[FBLOCK_MAX_BYTES];

    memset(szBuf, 0, sizeof(wchar_t) * FBLOCK_MAX_BYTES);

     

    std::string strMessage;

     

    FILE * fp = NULL;

    fp = fopen(strFileName.c_str(), "rb");

    if (fp != NULL)

    {

        // Unicode file should offset wchar_t bits(2 byte) from start.

        fseek(fp, sizeof(wchar_t), 0);

        while(fread(szBuf, sizeof(wchar_t), FBLOCK_MAX_BYTES, fp) > 0)

        {

            char szTemp[FBLOCK_MAX_BYTES] = {0};

     

            UnicodeToANSI(szTemp, szBuf);

            strMessage += szTemp;

            memset(szBuf, 0, sizeof(wchar_t) * FBLOCK_MAX_BYTES);

        }

    }

     

    std::cout << strMessage << std::endl;

     

    fclose(fp);

     

     

    UTF8文本文件的读取

    UTF8是可变字节,使用单一字节读取比较合理,所以读取时,使用char作为基本类型。

    下面是简单示例代码:

    char szBuf[FBLOCK_MAX_BYTES];

    memset(szBuf, 0, sizeof(char) * FBLOCK_MAX_BYTES);

     

    std::string strMessage;

     

    FILE * fp = NULL;

    fp = fopen(strFileName.c_str(), "rb");

    if (fp != NULL)

    {

        // UTF-8 file should offset 3 byte from start position.

        fseek(fp, sizeof(char) * 3, 0);

        while(fread(szBuf, sizeof(char), FBLOCK_MAX_BYTES, fp) > 0)

        {

            strMessage += szBuf;

            memset(szBuf, 0, sizeof(char) * FBLOCK_MAX_BYTES);

        }

    }

     

    std::cout << strMessage << std::endl;

     

    fclose(fp);

     

     

     

    后记

    文本文件的读取并非一个大的问题,但是使用的较多,而各个开发部门一般使用成熟的库,开发人员很少可以接触到低层的东东。

    当无力支持购买成熟库的时候,就需要自己来做些东西了,这里仅仅是一个开始。

     

    附录:测试源代码

    #include <assert.h> #include <windows.h> #include <iostream> #include <fstream> #include <string> const int FBLOCK_MAX_BYTES = 256; // File Type. typedef enum FileType { ANSI = 0, UNICODE, UTF8, }FILETYPE; FILETYPE GetTextFileType(const std::string & strFileName); int UnicodeToANSI(char * pDes, const wchar_t * pSrc); void main() { // file test. std::string strFileANSI = "C://Hello_ANSI.txt"; std::string strFileUNICODE = "C://Hello_UNICODE.txt"; std::string strFileUTF8 = "C://Hello_UTF8.txt"; // please change the file name to test. std::string strFileName = strFileUTF8; FILETYPE fileType = GetTextFileType(strFileName); if (UNICODE == fileType) { wchar_t szBuf[FBLOCK_MAX_BYTES]; memset(szBuf, 0, sizeof(wchar_t) * FBLOCK_MAX_BYTES); std::string strMessage; FILE * fp = NULL; fp = fopen(strFileName.c_str(), "rb"); if (fp != NULL) { // Unicode file should offset wchar_t bits(2 byte) from start. fseek(fp, sizeof(wchar_t), 0); while(fread(szBuf, sizeof(wchar_t), FBLOCK_MAX_BYTES, fp) > 0) { char szTemp[FBLOCK_MAX_BYTES] = {0}; UnicodeToANSI(szTemp, szBuf); strMessage += szTemp; memset(szBuf, 0, sizeof(wchar_t) * FBLOCK_MAX_BYTES); } } std::cout << strMessage << std::endl; fclose(fp); } else if (UTF8 == fileType) { char szBuf[FBLOCK_MAX_BYTES]; memset(szBuf, 0, sizeof(char) * FBLOCK_MAX_BYTES); std::string strMessage; FILE * fp = NULL; fp = fopen(strFileName.c_str(), "rb"); if (fp != NULL) { // UTF-8 file should offset 3 byte from start position. fseek(fp, sizeof(char) * 3, 0); while(fread(szBuf, sizeof(char), FBLOCK_MAX_BYTES, fp) > 0) { strMessage += szBuf; memset(szBuf, 0, sizeof(char) * FBLOCK_MAX_BYTES); } } std::cout << strMessage << std::endl; fclose(fp); } else { char szBuf[FBLOCK_MAX_BYTES]; memset(szBuf, 0, sizeof(char) * FBLOCK_MAX_BYTES); std::string strMessage; FILE * fp = NULL; fp = fopen(strFileName.c_str(), "rb"); if (fp != NULL) { // common file do not offset. while(fread(szBuf, sizeof(char), FBLOCK_MAX_BYTES, fp) > 0) { strMessage += szBuf; memset(szBuf, 0, sizeof(char) * FBLOCK_MAX_BYTES); } } std::cout << strMessage << std::endl; fclose(fp); } #ifdef _DEBUG getchar(); #endif } FILETYPE GetTextFileType(const std::string & strFileName) { FILETYPE fileType = ANSI; std::ifstream file; file.open(strFileName.c_str(), std::ios_base::in); bool bUnicodeFile = false; if (file.good()) { char szFlag[3] = {0}; file.read(szFlag, sizeof(char) * 3); if ((unsigned char)szFlag[0] == 0xFF && (unsigned char)szFlag[1] == 0xFE) { fileType = UNICODE; } else if ((unsigned char)szFlag[0] == 0xEF && (unsigned char)szFlag[1] == 0xBB && (unsigned char)szFlag[2] == 0xBF) { fileType = UTF8; } } file.close(); return fileType; } int UnicodeToANSI(char * pDes, const wchar_t * pSrc) { assert(pDes != NULL); assert(pSrc != NULL); int nLen = ::WideCharToMultiByte(CP_ACP, 0, pSrc, -1, NULL, 0, NULL, NULL); if (nLen == 0) { return -1; } return ::WideCharToMultiByte(CP_ACP, 0, pSrc, -1, pDes, nLen, NULL, NULL); }

     

     


    最新回复(0)