[經驗總結]利用MFC的CFile物件輸出utf-8和ansi編碼的文字
阿新 • • 發佈:2019-01-26
// 今天寫了一段輸出文字到檔案的程式碼,一開始用CFile輸出中文,總是出現亂碼,又是百度(Google被牆了)一番,網上的教程基本是隻知其一不知其二,大多隻講了輸出檔案位元組序標記和計算寬字元長度這兩個注意點,卻沒有提到字元轉換這個最關鍵的一步。下面的程式碼分別輸出UTF-8和ANSI(簡體中文Windows上是GBK編碼)兩種編碼的文字檔案。
//
// 寫UTF-8文字
// 下列檔案類操作中可能丟擲一個CFileException異常
try {
CStdioFile hfile( strFilePath, CFile::modeReadWrite);
if (hfile.m_hFile)
{
DWORD dwFileLen = hfile.GetLength();
if (0 == dwFileLen) // 檔案為空時寫入UTF位元組序標記
{
const unsigned char LeadBytes[] = {0xEF, 0xBB , 0xBF};
hfile.Write(LeadBytes, sizeof(LeadBytes));
}
int nSrcLen = (int)wcslen(lpstrWord);
CStringA utf8String(lpstrWord);
int nBufLen = (nSrcLen+1) * 6;
LPSTR buffer = utf8String.GetBufferSetLength(nBufLen);
// 將UNICODE 轉換成UTF8
// 需要函式AtlUnicodeToUTF8 標頭檔案: <atlenc.h>
int nLen = AtlUnicodeToUTF8(lpstrWord, nSrcLen, buffer, nBufLen); // int nLen = utf8String.GetLength();
buffer[nLen] = 0;
utf8String.ReleaseBuffer();
//寫檔案
hfile.SeekToEnd();
hfile.Write((LPCSTR)utf8String, nLen);
hfile.Write("/r/n", 2);
hfile.Close();
}
}
catch(CFileException* pException)
{
CString strMsg;
TCHAR szErrorMessage[512];
if (pException->GetErrorMessage(szErrorMessage,
sizeof(szErrorMessage)/sizeof(*szErrorMessage), 0))
strMsg.Format(_T("(%s:%d)/n%s"), _T(__FILE__), __LINE__, szErrorMessage);
else
strMsg.Format(_T("(%s:%d)"), _T(__FILE__), __LINE__);
AfxMessageBox(strMsg);
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// 寫ANSI文字:
try {
CStdioFile hfile( strHeiMaiUsrLibPath, CFile::modeReadWrite);
if(hfile.m_hFile)
{
// 將Unicode字串賦給Ansi格式的CStringA,實現Unicode=>Ansi轉換
CStringA utf8String(lpstrWord);
int nLen = utf8String.GetLength();
// 寫檔案
hfile.SeekToEnd();
hfile.Write((LPCSTR)utf8String, nLen);
hfile.Write("/r/n", 2);
hfile.Close();
}
}
catch(CFileException* pException)
{
CString strMsg;
TCHAR szErrorMessage[512];
if (pException->GetErrorMessage(szErrorMessage, sizeof(szErrorMessage)/sizeof(*szErrorMessage), 0))
strMsg.Format(_T("(%s:%d)/n%s"), _T(__FILE__), __LINE__, szErrorMessage);
else
strMsg.Format(_T("(%s:%d)"), _T(__FILE__), __LINE__);
AfxMessageBox(strMsg);
}
//
// 寫UTF-8文字
// 下列檔案類操作中可能丟擲一個CFileException異常
try {
CStdioFile hfile( strFilePath, CFile::modeReadWrite);
if
{
DWORD dwFileLen = hfile.GetLength();
if (0 == dwFileLen) // 檔案為空時寫入UTF位元組序標記
{
const unsigned char LeadBytes[] = {0xEF, 0xBB
hfile.Write(LeadBytes, sizeof(LeadBytes));
}
int nSrcLen = (int)wcslen(lpstrWord);
CStringA utf8String(lpstrWord);
int nBufLen = (nSrcLen+1) * 6;
LPSTR buffer = utf8String.GetBufferSetLength(nBufLen);
// 將UNICODE 轉換成UTF8
// 需要函式AtlUnicodeToUTF8 標頭檔案: <atlenc.h>
int nLen = AtlUnicodeToUTF8(lpstrWord, nSrcLen, buffer, nBufLen); // int nLen = utf8String.GetLength();
buffer[nLen] = 0;
utf8String.ReleaseBuffer();
//寫檔案
hfile.SeekToEnd();
hfile.Write((LPCSTR)utf8String, nLen);
hfile.Write("/r/n", 2);
hfile.Close();
}
}
catch(CFileException* pException)
{
CString strMsg;
TCHAR szErrorMessage[512];
if (pException->GetErrorMessage(szErrorMessage,
sizeof(szErrorMessage)/sizeof(*szErrorMessage), 0))
strMsg.Format(_T("(%s:%d)/n%s"), _T(__FILE__), __LINE__, szErrorMessage);
else
strMsg.Format(_T("(%s:%d)"), _T(__FILE__), __LINE__);
AfxMessageBox(strMsg);
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// 寫ANSI文字:
try {
CStdioFile hfile( strHeiMaiUsrLibPath, CFile::modeReadWrite);
if(hfile.m_hFile)
{
// 將Unicode字串賦給Ansi格式的CStringA,實現Unicode=>Ansi轉換
CStringA utf8String(lpstrWord);
int nLen = utf8String.GetLength();
// 寫檔案
hfile.SeekToEnd();
hfile.Write((LPCSTR)utf8String, nLen);
hfile.Write("/r/n", 2);
hfile.Close();
}
}
catch(CFileException* pException)
{
CString strMsg;
TCHAR szErrorMessage[512];
if (pException->GetErrorMessage(szErrorMessage, sizeof(szErrorMessage)/sizeof(*szErrorMessage), 0))
strMsg.Format(_T("(%s:%d)/n%s"), _T(__FILE__), __LINE__, szErrorMessage);
else
strMsg.Format(_T("(%s:%d)"), _T(__FILE__), __LINE__);
AfxMessageBox(strMsg);
}