将各种编码格式的⽂本⽂件转换为ANSI格式
⽇常⼯作中,我们可能会遇到处理不同格式编码的⽂本⽂件的需求,这个问题如果处理不好,就会有中⽂乱码等棘⼿的问题。
以下这个⽂章写的很不错:
阮⼀峰:字符编码笔记:ASCII,Unicode和UTF-8
理解这些编码知识后,我们就可以编写C++代码来完成任务了。下⾯的函数会把UTF-8, UNICODE Big-endian, UNICODE Little-endian 这三种格式编码的⽂本⽂件转换成ANSI⽂本⽂件。参数为⽂本⽂件路径。只⽤于Windows平台。
1/*
2 * 将路径fpath所指的⽂件从各种编码格式,转换为ANSI格式
3 *
4 * Copyright (c) 2013 赵⼦清, All rights reserved.
5 *
6*/
7
8#define CODE_FORMAT_ANSI        1
9#define CODE_FORMAT_UTF8        2
10#define CODE_FORMAT_UNICODE_LE  3
11#define CODE_FORMAT_UNICODE_BE  4
12
13 typedef int ErrorCode;
14#define    ERR_OK                  0
15#define    ERR_FILE_OPEN_FAILED    1001
16
17#define SWAP16(x) \
18    ((((x) & 0x00ff) << 8) | \
19    (((x) & 0xff00) >> 8) )
20
21#define SWAP32(x) \
22    ((((x) & 0x000000ff) << 24) | \
23    (((x) & 0x0000ff00) <<  8) | \
24    (((x) & 0x00ff0000) >>  8) | \
25    (((x) & 0xff000000) >> 24) )
26
27#define SAFE_DELETE(x) if((x)!=0) {delete[] (x); (x) = 0; }
28
29 ErrorCode  ConvertFormat(const char* fpath)
30 {
31 #ifdef _MSC_VER
32    assert(fpath != 0);
33
34    FILE* fp = ::fopen(fpath, "rb");
35if(fp == NULL)
36return ERR_FILE_OPEN_FAILED;
37
38int fmtFlag;
39int fmt = CODE_FORMAT_ANSI;
40    ::fread(&fmtFlag, sizeof(int), 1, fp);
41    ::fclose(fp);
42
43    fmtFlag = SWAP32(fmtFlag);
44if((fmtFlag & 0xffffff00) == 0xefbbbf00)
45        fmt = CODE_FORMAT_UTF8;
46else if((fmtFlag & 0xffff0000) == 0xfffe0000)
47        fmt = CODE_FORMAT_UNICODE_LE;
48else if((fmtFlag & 0xffff0000) == 0xfeff0000)
49        fmt = CODE_FORMAT_UNICODE_BE;
49        fmt = CODE_FORMAT_UNICODE_BE;
50
51
52if(fmt == CODE_FORMAT_ANSI)
53return ERR_OK;
54
55    fp = ::fopen(fpath, "rb");
56char* txt = 0;
57    wchar_t* wtxt = 0;
58long flen = 0L;
59    ::fseek(fp, 0L, SEEK_END);
unicode文件格式
60    flen = ftell(fp);
61    ::rewind(fp);
62if(fmt == CODE_FORMAT_UTF8)
63    {
64        txt = new char[flen+1];
65        ::fread(txt, 1, flen, fp);
66        txt[flen] = '\0';
67    }
68else if(fmt == CODE_FORMAT_UNICODE_LE || fmt == CODE_FORMAT_UNICODE_BE)
69    {
70        wtxt = new wchar_t[flen/2 +1];
71        ::fread(wtxt, 2, flen/2, fp);
72if(fmt == CODE_FORMAT_UNICODE_BE)
73        {
74for(int i=0; i < flen/2; i++)
75                wtxt[i] = SWAP16(wtxt[i]);
76        }
77        wtxt[flen/2] = L'\0';
78    }
79
80    ::fclose(fp);
81
82int nLen;
83    wchar_t* pwstr = 0;
84char* pstr = 0;
85switch (fmt)
86    {
87case CODE_FORMAT_UTF8:
88        nLen = ::MultiByteToWideChar(CP_UTF8, 0, txt+3, -1, NULL, 0);
89        pwstr = new wchar_t[nLen+1];
90        nLen = ::MultiByteToWideChar(CP_UTF8, 0, txt+3, -1, pwstr, nLen);
91        nLen = ::WideCharToMultiByte(CP_ACP, 0, pwstr, -1, NULL, 0, NULL, NULL);
92        pstr = new char[nLen];
93        ::memset(pstr, 0, nLen);
94        nLen = ::WideCharToMultiByte(CP_ACP, 0, pwstr, -1, pstr,
95                                nLen, NULL, NULL);
96break;
97case CODE_FORMAT_UNICODE_LE:
98case CODE_FORMAT_UNICODE_BE:
99        nLen = ::WideCharToMultiByte(CP_ACP, 0, wtxt+1, -1, NULL, 0, NULL, NULL);
100        pstr = new char[nLen];
101        ::memset(pstr, 0, nLen);
102        nLen = ::WideCharToMultiByte(CP_ACP, 0, wtxt+1, -1, pstr,
103                                        nLen, NULL, NULL);
104break;
105default:
106break;
107    }
108
109    fp = ::fopen(fpath, "wb");
110    ::fwrite(pstr, 1, nLen-1, fp);
111    ::fclose(fp);
112
113    SAFE_DELETE(txt);
114    SAFE_DELETE(wtxt);
114    SAFE_DELETE(wtxt); 115    SAFE_DELETE(pstr); 116    SAFE_DELETE(pwstr); 117
118#endif
119
120return ERR_OK;
121 }

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。