【示例程序:VC打开任意编码的文本文件】
用Visual C++ 2010写的示例程序:
常用代码页
437 英语
932 日语
936 简体中文(GB2312)
949 朝鲜语
950 繁体中文(Big-5)
54936 简体中文(GB18030)
65001 UTF-8
下载:
MfcMyGb18030.rar
687.84KB
RAR
22次下载
<code class="lang-cpp">#include "MyStringCP.h"
void CMfcMyGb18030Dlg::OnBnClickedSaveFile()
{
UpdateData(TRUE);
try {
CFileDialog dlg(FALSE, _T(".txt"), _T("result.txt"));
if (dlg.DoModal() != IDOK)
return;
CFile outfile(dlg.GetPathName(), CFile::modeWrite|CFile::modeCreate);
CPString strcp(m_dstcp, m_text, false);
outfile.Write((LPCSTR)strcp, strcp.GetLength());
outfile.Close();
} catch (CException *e) {
MessageBox(_T("文件保存错误!"));
}
}
void CMfcMyGb18030Dlg::OnBnClickedOpenFile()
{
UpdateData(TRUE);
try {
CFileDialog dlg(TRUE, _T(".txt"), _T("result.txt"));
if (dlg.DoModal() != IDOK)
return;
CFile infile(dlg.GetPathName(), CFile::modeRead);
CPString instr(m_srccp);
ULONGLONG inlength = infile.GetLength();
LPSTR inbuf = instr.GetBufferSetLength(inlength);
infile.Read(inbuf, inlength);
instr.ReleaseBuffer(inlength);
m_text = instr.Get();
infile.Close();
UpdateData(FALSE);
} catch (CException *e) {
MessageBox(_T("文件打开错误!"));
}
}</code>
【编码转换类】
这是一个字符串实现类,包装了CStringA和MultiByteToWideChar、WideCharToMultiByte函数,可以实现方便的编码互转,便于与各种蛋疼的编码问题打交道。
使用这个类时不建议编译ANSI(MBCS)应用程序,因为ANSI版WinAPI实际上仅支持DBCS双字节字符集(即仅支持GBK、Big5等2个字节的字符集,不支持GB18030、UTF-8等超过2个字节的字符集),对编码转换的兼容性会变差,并且也有额外的开销。
构造函数
CPString strloc(代码页, 字符串, 是否原始字符串);
CPString strloc1(); // 初始化空的UTF-8字符串
CPString strloc2(54936); // 初始化空的GB18030字符串
CPString strloc3(54936, _T("我是要转码的字符串\r\n")); // 初始化GB18030字符串,进行转码
CPString strloc4(54936, "我是要转码的字符串\r\n", true); // 初始化GB18030字符串,不进行转码
CPString strloc5(65001, strloc5); // 将strloc5转码成UTF-8
CPString strloc6(65001, strloc5, true); // 将strloc5的内容原封不动复制,并设定代码页为UTF-8
与使用UTF-16、ACP-ANSI的CString、其它CPString互转
CString str = XXXXXXXXXt(); // 转码到CString
XXXXXXXXXom(str); // 从CString转码
XXXXXXXXXXom(strloc); // 互相转码
复制、转换和赋值
CPString strloc2 = strloc; // 不转码,只是整体复制(包括代码页、内容等)
CStringA strraw = strloc; // 同上,不转码(只复制内容)
<code class="lang-cpp">// MyStringCP.h : 任意代码页字符串
#pragma once
#include <windows.h>
#ifndef _AFX
#include <atlstr.h>
#endif
// 任意MBCS字符集(代码页)字符串类,可转码
// 支持ANSI、GBK、Big-5、GB18030、UTF-8等C兼容字符集
// 不支持UTF-16和UTF-32
class CPString : public CStringA {
public:
UINT m_codepage; // 代码页
UINT m_dwflags; // 可选标志,传递给WinAPI的可选参数,建议保持NULL
LPCSTR m_lpdefaultchar; // 缺省字符,传递给WinAPI的可选参数,建议保持NULL
// 因为CStringA<->LPCSTR和CStringW<->LPCWSTR可以隐式转换
// 故参数中均以LPCSTR和LPCWSTR替换CStringA和CStringW
// 第一个参数ucp是代码页,默认为UTF-8(65001);
// 第二个参数str是字符串,默认为空字符串;
// 第三个参数israw指示是否是原始字符串,对于宽字符的情况,该参数不起作用;
// 后两个参数dwflags和lpdefchar是传递给WinAPI的可选参数,建议保持默认。
// 此类型必需要有代码页,不能由字符串直接转换而来,因此没有转换构造函数。
CPString(UINT ucp = CP_UTF8, LPCSTR str = NULL, bool israw = false,
UINT dwflags = 0, LPCSTR lpdefchar = NULL) {
m_codepage = ucp;
m_dwflags = dwflags;
m_lpdefaultchar = lpdefchar;
// 注意次序
if (str != NULL) {
if (israw)
CStringA::operator=(str);
else
FromA(str);
}
}
CPString(UINT ucp, LPCWSTR str, bool reserved1 = false,
UINT dwflags = 0, LPCSTR lpdefchar = NULL) {
m_codepage = ucp;
m_dwflags = dwflags;
m_lpdefaultchar = lpdefchar;
// 注意次序
FromW(str);
}
CPString(UINT ucp, const CPString &str, bool israw = false,
UINT dwflags = 0, LPCSTR lpdefchar = NULL) {
m_codepage = ucp;
m_dwflags = dwflags;
m_lpdefaultchar = lpdefchar;
// 注意次序
if (israw)
CStringA::operator=(str);
else
From(str);
}
bool From(LPCWSTR tstr) { return FromW(tstr); } // 转码到此对象所设定的代码页
bool From(LPCSTR tstr) { return FromA(tstr); } // 转码到此对象所设定的代码页
#ifdef UNICODE
CStringW Get() const { return GetW(); } // 从此对象所设定的代码页转码
#else
CStringA Get() const { return GetA(); } // 从此对象所设定的代码页转码
#endif
// 不同代码页互转
bool From(const CPString &cpstr) {
if (m_codepage == cpstr.m_codepage) { // 如果代码页相同则不进行转码
CStringA::operator=(cpstr);
return true;
} else {
return FromW(cpstr.GetW()); // 这样转换开销较大!
}
}
// =====================================================================
// 字符集限定的函数
// 写Unicode字符串,若两个皆为0,则返回需要的wchar_t缓冲区大小
int WriteW(LPWSTR outbuf, int bufsize) const {
return MultiByteToWideChar(m_codepage, m_dwflags, *this, -1, outbuf, bufsize);
}
// 从代码页转码到Unicode
CStringW GetW() const {
CStringW wstr;
int n = WriteW(NULL, 0);
WriteW(wstr.GetBufferSetLength(n), n);
wstr.ReleaseBuffer();
return wstr;
}
// 从Unicode转码到代码页
bool FromW(LPCWSTR wstr) {
int n = WideCharToMultiByte(m_codepage, m_dwflags, wstr, -1, NULL, 0, m_lpdefaultchar, NULL);
LPSTR buf = this->GetBufferSetLength(n);
if (!WideCharToMultiByte(m_codepage, m_dwflags, wstr, -1, buf, n, m_lpdefaultchar, NULL)) {
buf[0] = '\0'; // 转换不成功则置空
this->ReleaseBuffer();
return false;
}
this->ReleaseBuffer();
return true;
}
// 从代码页转码到ACP-ANSI(当前代码页),开销较大!
CStringA GetA() const {
if (GetACP() == m_codepage) {
return *this;
} else
return (CStringA)GetW(); // ANSI中这样转换开销较大!
}
// 从ACP-ANSI(当前代码页)转码到代码页,开销较大!
bool FromA(LPCSTR thestr) {
if (GetACP() == m_codepage) {
CStringA::operator=(thestr);
return TRUE;
} else
return FromW((CStringW)thestr); // ANSI中这样转换开销较大!
}
};</-></-></atlstr.h></windows.h></code>
200字以内,仅用于支线交流,主线讨论请采用回复功能。