分享

C++读取文本文件

 无云666 2014-11-15

 

写在开始

最近在做一个东东,遇到文件读取的问题,遂开始研究,使用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

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多