關於以前excel記憶體開啟操作函式的使用說明。
為方便讀者使用excel記憶體開啟檔案,對於使用方法做如下解釋,注意彩色字型提示。
第一步。
.h標頭檔案包含
extern "C" { #include "InjectExcel.h" }
.cpp中操作
_cUnpAbaoExcel a(new _cMyExcel(true));
。。。。
CString SqlStr; if(a->CreateNewApp()==FALSE) { BOOST_THROW_EXCEPTION( _cMyExceptionImpl(_T("Application建立失敗,請確保正確安裝了非精簡excel 2003或excel 2007版本!"),this)); }
。。。。。。 if(IsXLSFile(m_TongYongTongJiExcelFile)==false)//判斷是否是excel檔案 。。。。。。
_cUnpAbaoExcel aMoBan(new _cMyExcel(a->m_unpApp->m_lpDispatch));
。。。。。。
DWORD ProcId; GetWindowThreadProcessId((HWND)aMoBan->m_unpApp->get_Hwnd(), &ProcId); if(FALSE==SetHookCreateFileFuncNewVersion(ProcId,autoDel.chFileName,autoDel.chStreamName, autoDel.chSecFileName,autoDel.chSecStreamName,&CurrentExcelProcHandle,oldcode)) { BOOST_THROW_EXCEPTION( _cMyExceptionImpl(_T("設定附加程式失敗!"),this)); }
中間步驟
BOOL CFormViewFormatTrans::DoSomethingByUsingExcelApp( _cUnpAbaoExcel& aMoBan, const unique_ptr<_cLstOfLstsFilteredMultCos>&filteredLst, unique_ptr<_cDataBaseCommonVar>& pUniq_ptr_DBCommVar, const unique_ptr<_sMaxMinMonth>&pMaxMinMonth,bool IsMerged )
最後一步。
if(FALSE==FreeHookCreateFileFunc(CurrentExcelProcHandle,oldcode)) { BOOST_THROW_EXCEPTION(_cMyExceptionImpl(_T("釋放&*(667失敗!"),this)); }
。。。。。。
}catch(std::exception & exp ) { if(CurrentExcelProcHandle!=NULL) { FreeHookCreateFileFunc(CurrentExcelProcHandle,oldcode); } exp.what(); return FALSE; }
補充:
對於記憶體開啟檔名需要專門的命名規則,以保證開啟其他檔案不受影響。
wcscpy_s(chFileName,15,L"[email protected]#$140816.xls"); wcscpy_s(chStreamName,28,L"[email protected]#$140816.xls:Stream:$DATA"); wcscpy_s(chSecFileName,15,L"[email protected]#$140816.xls"); wcscpy_s(chSecStreamName,28,L"[email protected]#$140816.xls:Stream:$DATA");
hSecStream=0; hStream=0; memset(hTmpStream,0,sizeof(HANDLE)*12); CString strStreamName=theApp.strTempPathFullName+_T("\\")+chStreamName; TCHAR diskChar=strStreamName.GetAt(0); TCHAR lpVolumeNameBuffer[1024]; //硬碟卷標名稱 DWORD dwVolumeSerialNumber; //序列號 DWORD dwMaximumComponentLength; //檔名最大長度 DWORD FileSystemFlags; //檔案系統標誌 TCHAR lpFileSystemNameBuffer[1024];//檔案系統名稱
CString strDisk; strDisk.Format(_T("%c:\\\\"),diskChar);
if(!GetVolumeInformation(strDisk, lpVolumeNameBuffer,1024, &dwVolumeSerialNumber, &dwMaximumComponentLength, &FileSystemFlags, lpFileSystemNameBuffer,1024)) { BOOST_THROW_EXCEPTION(_cMyExceptionImpl(_T("判斷檔案系統失敗!"),m_OwnerPtr)); } CString tmpFileSystemName=lpFileSystemNameBuffer; if(tmpFileSystemName!=_T("NTFS")) { BOOST_THROW_EXCEPTION(_cMyExceptionImpl(_T("失敗,請將本程式及附帶列表檔案放在NTFS分割槽上,不要放在")+ tmpFileSystemName+_T("盤上!"),m_OwnerPtr)); } if(PathFileExists(strStreamName)) { if(DeleteFile(strStreamName)==FALSE) { BOOST_THROW_EXCEPTION(_cMyExceptionImpl(_T("刪除臨時檔案失敗,請手動刪除本程式temp資料夾下的檔案,可能需要手動到程序管理器終止excel.exe應用程式!"),m_OwnerPtr)); //return FALSE; } } hStream = CreateFile( strStreamName, // Filename GENERIC_WRITE|GENERIC_READ, // Desired access FILE_SHARE_WRITE|FILE_SHARE_READ, // Share flags NULL, // Security Attributes CREATE_ALWAYS, // Creation Disposition 0, // Flags and Attributes NULL ); // OVERLAPPED pointer if( hStream == INVALID_HANDLE_VALUE ) {
BOOST_THROW_EXCEPTION(_cMyExceptionImpl(_T("生成臨時檔案失敗!"),m_OwnerPtr)); } CString strSecStreamName=theApp.strTempPathFullName+_T("\\")+chSecStreamName; if(PathFileExists(strSecStreamName)) { if(DeleteFile(strSecStreamName)==FALSE) { BOOST_THROW_EXCEPTION(_cMyExceptionImpl(_T("刪除臨時檔案失敗,請手動刪除本程式temp資料夾下的檔案,可能需要手動到程序管理器終止excel.exe應用程式!"),m_OwnerPtr)); //return FALSE; } } hSecStream = CreateFile( strSecStreamName, // Filename GENERIC_WRITE|GENERIC_READ, // Desired access FILE_SHARE_WRITE|FILE_SHARE_READ, // Share flags NULL, // Security Attributes CREATE_ALWAYS, // Creation Disposition 0, // Flags and Attributes NULL ); // OVERLAPPED pointer if( hSecStream == INVALID_HANDLE_VALUE ) { BOOST_THROW_EXCEPTION(_cMyExceptionImpl(_T("生成臨時檔案失敗!"),m_OwnerPtr)); }
關於xml檔案的生成:
BOOL CFormViewFormatTrans::WriteListToTmpXmlFile( const unique_ptr<_cLstOfLstsFilteredMultCos>&filteredLst ,unique_ptr<_cDataBaseCommonVar>& pUniq_ptr_DBCommonVar, const CString &LieBiaoXlsFileName,HANDLE& hStream,HANDLE &hSecStream, XmlContentInfo& xmlInfoObj, CString &outStrXmlTmpFileFullName,bool isVLst) {
CString SheetName2,strTmp; CString SheetName; //long TimeSum=0; CString strTmp3=_T(""),strTmp4=_T(""),strTmp5=_T(""); COleSafeArray saRet,saRetComment; COleSafeArray saRetRS; DWORD numElements[2]; DWORD numElementsComment[2]; //long t1=::GetTickCount(); CStringA TmpUTF8CStr; CString SheetNamePrefix; if(isVLst==true) { SheetNamePrefix.Format(_T("%d-"),VIndex); VIndex++; } else { SheetNamePrefix=_T(""); } try{ CString strFileName; int nPos=LieBiaoXlsFileName.ReverseFind('.'); if(nPos!=-1) { strFileName=LieBiaoXlsFileName.Left(nPos); // 結尾沒有 '\' } strFileName=_T("[email protected]")+strFileName+_T(".xml"); CString XMLFileName=::GetAppPath(); XMLFileName+=_T("\\")+strFileName; outStrXmlTmpFileFullName=XMLFileName; //moBanFile.Open(XMLFileName,CFile::modeCreate|CFile::modeWrite); char *TmpUTF8CStrCh=UnicodeToUtf8(xmlInfoObj.m_TmplCStrFileHeader); TmpUTF8CStr=TmpUTF8CStrCh; free(TmpUTF8CStrCh); DWORD BytesWritten; WriteFile(hStream,TmpUTF8CStr.GetBuffer(), TmpUTF8CStr.GetLength(),&BytesWritten,NULL); TmpUTF8CStr.ReleaseBuffer(); list<shared_ptr< _cListOfOneCompanyDBRows >>::const_reverse_iterator it__cListOfOneCompanyDBRows; it__cListOfOneCompanyDBRows=filteredLst->m_pSmartList->crbegin();
numElements[0] = 12; numElements[1] = m_TaiZhangMoBanFormat.ColumnFormatMap->size();
numElementsComment[0] = 12; numElementsComment[1] = numElements[1];
int commentColumn=0; CString strTmpQitaShui; list<shared_ptr< _cOneDBRowOfCompany >>::const_iterator it__cOneDBRowOfCompany;
COleVariant vOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR), vTrue((short)TRUE), vFalse((short)FALSE), vLookAt((long)xlWhole);
CString SqlStr; //最好不用recordset 的getrecordcount方法,因為會不準確 SqlStr.Format(_T("select Count(*) as rscount from %s") ,filteredLst->m_TBLName); int rscount=0; pUniq_ptr_DBCommonVar->pRs->Open(SqlStr); pUniq_ptr_DBCommonVar->pRs->GetFieldValue(_T("rscount"),rscount); if(rscount<=0) { BOOST_THROW_EXCEPTION(_cMyExceptionImpl(_T("計算公司數量失敗!"),this)); } SqlStr.Format(_T("select F1,F2,F3,F4,F5 from %s") ,filteredLst->m_TBLName); pUniq_ptr_DBCommonVar->pRs->Open(SqlStr);
saRetRS.Attach(pUniq_ptr_DBCommonVar->pRs->m_pRecordset->GetRows(rscount)); VARIANT (*pbstr)[5]=NULL; saRetRS.AccessData((LPVOID*)&pbstr);
long lUBoundX; long lUBoundY;
saRetRS.GetUBound(1,&lUBoundX); saRetRS.GetUBound(2,&lUBoundY);
CString strNaShuiRenBianMa; CString StrMingChen; CString strDengJiZhuCeLeiXing; int tmpFirstSheetEnd=0; for(int i=0;i<CompanyNum&& it__cListOfOneCompanyDBRows!=filteredLst->m_pSmartList->crend(); i++,++it__cListOfOneCompanyDBRows)//CompanyNum { ::PostMessage(m_pDialogProgress->m_hWnd,MY_MACRO_WM_USER_THREAD_UPDATE_PROGRESS,i,CompanyNum); strNaShuiRenBianMa=_T(""); int OneCompanyDataCount=(*it__cListOfOneCompanyDBRows)->m_pSmartList->size(); it__cOneDBRowOfCompany= (*it__cListOfOneCompanyDBRows)->m_pSmartList->begin(); StrMingChen=(*it__cOneDBRowOfCompany)->NaShuiRenMingChen; //CString Str if(FindInMuLu(pbstr,lUBoundY, (*it__cOneDBRowOfCompany)->NaShuiRenMingChen, SheetName,strNaShuiRenBianMa)==FALSE) { BOOST_THROW_EXCEPTION(_cMyExceptionImpl(_T("建立sheet名稱失敗"),this)); } SheetName=SheetNamePrefix+SheetName;
saRet.Clear(); saRet.Create(VT_VARIANT,2,numElements); saRetComment.Clear(); saRetComment.Create(VT_BSTR,2,numElementsComment); if(m_IsProduceBudLvl==TRUE||m_IsExcludedLateFee==TRUE) { FillCOleSafeArray_ProduceSetting(it__cOneDBRowOfCompany, saRet,saRetComment,OneCompanyDataCount); } else { FillCOleSafeArray(it__cOneDBRowOfCompany, saRet,saRetComment,OneCompanyDataCount); }
CreateOneSheetXml(saRet,saRetComment,SheetName, strNaShuiRenBianMa,StrMingChen,(*it__cListOfOneCompanyDBRows)->m_strMultZheCeLeiXing, hStream,hSecStream,xmlInfoObj,i,isVLst);
} saRetRS.UnaccessData(); TmpUTF8CStrCh=UnicodeToUtf8(xmlInfoObj.m_TmplCStrFileFooter); TmpUTF8CStr=TmpUTF8CStrCh; free(TmpUTF8CStrCh); WriteFile(hStream,TmpUTF8CStr.GetBuffer(), TmpUTF8CStr.GetLength(),&BytesWritten,NULL); TmpUTF8CStr.ReleaseBuffer();
}catch(std::exception & exp ) { exp.what(); return FALSE; } catch(_com_error &e) { dump_com_error(e); return FALSE; } catch(...) { ShowMessageDialog(_T("執行緒異常型別4:CException"),_T("錯誤!"),this); return FALSE; } return TRUE; }
關於XmlContentInfo類:
struct XmlContentInfo { XmlContentInfo(); XmlElementInfo m_TmplWholeFile; XmlElementInfo m_TmplWorkSheetElement; XmlElementInfo m_TmplColumnElement; XmlElementInfo m_TmplFirstRowElement; XmlElementInfo m_TmplSecondRowElement; XmlElementInfo m_TmplMiddleRowElement; XmlElementInfo m_TmplSumRowElement; XmlElementInfo m_TmplLeftRowElement; XmlElementInfo m_TmplTableElement; XmlElementInfo m_SecRwCellElement; XmlElementInfo m_MidRwFirstCellElement; XmlElementInfo m_MidRwSecondCellElement; XmlElementInfo m_MidRwSecCelFirstDataElement; XmlElementInfo m_MidRwSecCelCommentElement; XmlElementInfo m_SmRwFirstCellElement; XmlElementInfo m_SmRwSecondCellElement; XmlElementInfo m_SmRwSecCelFirstDataElement; XmlElementInfo m_FstRwFirstCellElement; XmlElementInfo m_FstRwSecondCellElement; XmlElementInfo m_FstRwThirdCellElement; CString m_TmplCStrColumnArea; CString m_TmplCStrFileHeader; static const CString m_TmplCStrFileFooter; static const CString CStrRowHeader; static const CString CStrRowFooter; CString m_TmplCStrSheetHeader; CString m_TmplCStrOrignalSheetName; CString m_TmplCStrSheetFooter; CString m_TmplCStrSumRowFormula; static const char m_UTF8Header[3]; CString m_CStrTableHeader; CString m_CStrColumnIndexField; };
#include "TemplateFileData.h" const char XmlContentInfo::m_UTF8Header[3]={(char)0xEF,(char)0xBB,(char)0xBF}; const CString XmlContentInfo::m_TmplCStrFileFooter=_T("</Workbook>"); const CString XmlContentInfo::CStrRowHeader=_T("<Row ss:AutoFitHeight=\"0\">"); const CString XmlContentInfo::CStrRowFooter=_T("</Row>");
const CString TaiZhangTemplateStr=_T("<?xml version=\"1.0\"?>\ <?mso-application progid=\"Excel.Sheet\"?>\ <Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\ xmlns:o=\"urn:schemas-microsoft-com:office:office\"\ xmlns:x=\"urn:schemas-microsoft-com:office:excel\"\ xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"\ xmlns:html=\"http://www.w3.org/TR/REC-html40\">\ <DocumentProperties xmlns=\"urn:schemas-microsoft-com:office:office\">\ <Author>XZG</Author>\ <LastAuthor>xxx</LastAuthor>\ <Created>2011-06-17T00:56:31Z</Created>\ <LastSaved>2014-07-05T09:09:42Z</LastSaved>\ <Company>阿盟地稅直屬局</Company>\ <Version>12.00</Version>\ </DocumentProperties>\ <ExcelWorkbook xmlns=\"urn:schemas-microsoft-com:office:excel\">\ <WindowHeight>7380</WindowHeight>\ <WindowWidth>15480</WindowWidth>\ <WindowTopX>1140</WindowTopX>\ <WindowTopY>645</WindowTopY>\ <ProtectStructure>False</ProtectStructure>\ <ProtectWindows>False</ProtectWindows>\ </ExcelWorkbook>\ <Styles>\ <Style ss:ID=\"Default\" ss:Name=\"Normal\">\ <Alignment ss:Vertical=\"Center\"/>\ <Borders/>\ <Font ss:FontName=\"宋體\" x:CharSet=\"134\" ss:Size=\"12\"/>\ <Interior/>\ <NumberFormat/>\ <Protection/>\ </Style>\ <Style ss:ID=\"s62\">\ <Protection ss:Protected=\"0\"/>\ </Style>\ <Style ss:ID=\"s64\">\ <Alignment ss:Horizontal=\"Center\" ss:Vertical=\"Center\"/>\ <Protection ss:Protected=\"0\"/>\ </Style>\ <Style ss:ID=\"s66\">\ <Alignment ss:Horizontal=\"Center\" ss:Vertical=\"Center\"/>\ <NumberFormat ss:Format=\"0\"/>\ <Protection ss:Protected=\"0\"/>\ </Style>\ <Style ss:ID=\"s68\">\ <Alignment ss:Vertical=\"Center\"/>\ <Font ss:FontName=\"宋體\" x:CharSet=\"134\" ss:Size=\"12\"/>\ <Protection ss:Protected=\"0\"/>\ </Style>\ <Style ss:ID=\"s69\">\ <Protection/>\ </Style>\ <Style ss:ID=\"s70\">\ <Font ss:FontName=\"宋體\" x:CharSet=\"134\" ss:Size=\"12\"/>\ <Protection ss:Protected=\"0\"/>\ </Style>\ </Styles>\ <Worksheet ss:Name=\"Sheet1\">\ <Table ss:ExpandedColumnCount=\"18\" ss:ExpandedRowCount=\"17\" x:FullColumns=\"1\"\ x:FullRows=\"1\" ss:StyleID=\"s62\" ss:DefaultColumnWidth=\"52.5\"\ ss:DefaultRowHeight=\"15.5625\">\ <Column ss:Index=\"2\" ss:StyleID=\"s62\" ss:AutoFitWidth=\"0\" ss:Width=\"75.75\"\ ss:Span=\"16\"/>\ <Row ss:AutoFitHeight=\"0\">\ <Cell ss:MergeAcross=\"5\" ss:StyleID=\"s64\"><Data ss:Type=\"String\">hhh</Data></Cell>\ <Cell ss:MergeAcross=\"5\" ss:StyleID=\"s66\"><Data ss:Type=\"String\">KKK</Data></Cell>\ <Cell ss:MergeAcross=\"3\" ss:StyleID=\"s68\"><Data ss:Type=\"String\">LLL</Data></Cell>\ </Row>\ <Row ss:AutoFitHeight=\"0\">\ <Cell><Data ss:Type=\"String\">月份</Data></Cell>\ </Row>\ <Row ss:AutoFitHeight=\"0\">\ <Cell><Data ss:Type=\"Number\">1</Data></Cell>\ <Cell ss:StyleID=\"s69\" ss:Formula=\"=x\"><Data ss:Type=\"Error\">#NAME?</Data><Comment><ss:Data\ xmlns=\"http://www.w3.org/TR/REC-html40\"><B><Font html:Face=\"Tahoma\"\ x:CharSet=\"134\" x:Family=\"Swiss\" html:Color=\"#000000\">sssss</Font></B></ss:Data></Comment></Cell>\ </Row>\ <Row ss:AutoFitHeight=\"0\">\ <Cell><Data ss:Type=\"String\">合計</Data></Cell>\ <Cell ss:StyleID=\"s69\" ss:Formula=\"=SUM(R[-1]C:R[1048564]C)\"><Data\ ss:Type=\"Error\">#NAME?</Data></Cell>\ </Row>\ <Row ss:Index=\"17\" ss:AutoFitHeight=\"0\">\ <Cell ss:Index=\"4\" ss:StyleID=\"s70\"><Data ss:Type=\"String\">此臺帳不能反映抵扣稅款情況,只能保證與當時的通用統計結果一致。個體掛企業名稱的也不反映。包含滯納金</Data></Cell>\ </Row>\ </Table>\ <WorksheetOptions xmlns=\"urn:schemas-microsoft-com:office:excel\">\ <Unsynced/>\ <Print>\ <ValidPrinterInfo/>\ <PaperSizeIndex>9</PaperSizeIndex>\ <HorizontalResolution>600</HorizontalResolution>\ <VerticalResolution>600</VerticalResolution>\ </Print>\ <Zoom>75</Zoom>\ <Selected/>\ <FreezePanes/>\ <FrozenNoSplit/>\ <SplitHorizontal>2</SplitHorizontal>\ <TopRowBottomPane>2</TopRowBottomPane>\ <SplitVertical>1</SplitVertical>\ <LeftColumnRightPane>1</LeftColumnRightPane>\ <ActivePane>0</ActivePane>\ <Panes>\ <Pane>\ <Number>3</Number>\ <ActiveRow>57</ActiveRow>\ <ActiveCol>7</ActiveCol>\ </Pane>\ <Pane>\ <Number>1</Number>\ <ActiveRow>57</ActiveRow>\ <ActiveCol>7</ActiveCol>\ </Pane>\ <Pane>\ <Number>2</Number>\ <ActiveRow>57</ActiveRow>\ <ActiveCol>7</ActiveCol>\ </Pane>\ <Pane>\ <Number>0</Number>\ <ActiveRow>1</ActiveRow>\ <RangeSelection>C2:C18</RangeSelection>\ </Pane>\ </Panes>\ <ProtectObjects>False</ProtectObjects>\ <ProtectScenarios>False</ProtectScenarios>\ <EnableSelection>UnlockedCells</EnableSelection>\ </WorksheetOptions>\ </Worksheet>\ </Workbook>\ ");
關於編碼轉換:
#include "UTFConverter.h"
/* ------------------------------------------------------------- 內碼轉換 ------------------------------------------------------------- */
// 轉換UCS4編碼到UTF8編碼 INT CUnicodeConverter::UCS4_To_UTF8( DWORD dwUCS4, BYTE* pbUTF8 ) { const BYTE abPrefix[] = {0, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC}; const DWORD adwCodeUp[] = { 0x80, // U+00000000 ~ U+0000007F 0x800, // U+00000080 ~ U+000007FF 0x10000, // U+00000800 ~ U+0000FFFF 0x200000, // U+00010000 ~ U+001FFFFF 0x4000000, // U+00200000 ~ U+03FFFFFF 0x80000000 // U+04000000 ~ U+7FFFFFFF };
INT i, iLen;
// 根據UCS4編碼範圍確定對應的UTF-8編碼位元組數 iLen = sizeof(adwCodeUp) / sizeof(DWORD); for( i = 0; i < iLen; i++ ) { if( dwUCS4 < adwCodeUp[i] ) { break; } }
if( i == iLen )return 0; // 無效的UCS4編碼
iLen = i + 1; // UTF-8編碼位元組數 if( pbUTF8 != NULL ) { // 轉換為UTF-8編碼 for( ; i > 0; i-- ) { pbUTF8[i] = static_cast<BYTE>((dwUCS4 & 0x3F) | 0x80); dwUCS4 >>= 6; }
pbUTF8[0] = static_cast<BYTE>(dwUCS4 | abPrefix[iLen - 1]); }
return iLen; }
// 轉換UTF8編碼到UCS4編碼 INT CUnicodeConverter::UTF8_To_UCS4( const BYTE* pbUTF8, DWORD& dwUCS4 ) { INT i, iLen; BYTE b;
if( pbUTF8 == NULL ) { // 引數錯誤 return 0; }
b = *pbUTF8++; if( b < 0x80 ) { dwUCS4 = b; return 1; }
if( b < 0xC0 || b > 0xFD ) { // 非法UTF8 return 0; }
if( b < 0xE0 ) { dwUCS4 = b & 0x1F; iLen = 2; } else if( b < 0xF0 ) { dwUCS4 = b & 0x0F; iLen = 3; } else if( b < 0xF8 ) { dwUCS4 = b & 7; iLen = 4; } else if( b < 0xFC ) { dwUCS4 = b & 3; iLen = 5; } else { dwUCS4 = b & 1; iLen = 6; }
for( i = 1; i < iLen; i++ ) { b = *pbUTF8++; if( b < 0x80 || b > 0xBF ) { // 非法UTF8 break; }
dwUCS4 = (dwUCS4 << 6) + (b & 0x3F); }
if( i < iLen ) { // 非法UTF8 return 0; } else { return iLen; } }
// 轉換UCS4編碼到UCS2編碼 INT CUnicodeConverter::UCS4_To_UTF16( DWORD dwUCS4, WORD* pwUTF16 ) { if( dwUCS4 <= 0xFFFF ) { if( pwUTF16 != NULL ) { *pwUTF16 = static_cast<WORD>(dwUCS4); }
return 1; } else if( dwUCS4 <= 0xEFFFF ) { if( pwUTF16 != NULL ) { pwUTF16[0] = static_cast<WORD>( 0xD800 + (dwUCS4 >> 10) - 0x40 ); // 高10位 pwUTF16[1] = static_cast<WORD>( 0xDC00 + (dwUCS4 & 0x03FF) ); // 低10位 }
return 2; } else { return 0; } }
// 轉換UCS2編碼到UCS4編碼 INT CUnicodeConverter::UTF16_To_UCS4( const WORD* pwUTF16, DWORD& dwUCS4 ) { WORD w1, w2;
if( pwUTF16 == NULL ) { // 引數錯誤 return 0; }
w1 = pwUTF16[0]; if( w1 >= 0xD800 && w1 <= 0xDFFF ) { // 編碼在替代區域(Surrogate Area) if( w1 < 0xDC00 ) { w2 = pwUTF16[1]; if( w2 >= 0xDC00 && w2 <= 0xDFFF ) { dwUCS4 = (w2 & 0x03FF) + (((w1 & 0x03FF) + 0x40) << 10); return 2; } }
return 0; // 非法UTF16編碼 } else { dwUCS4 = w1; return 1; } }
// 轉換UTF8字串到UTF16字串 INT CUnicodeConverter::UTF8Str_To_UTF16Str( const BYTE* pbszUTF8Str, WORD* pwszUTF16Str ) { INT iNum, iLen; DWORD dwUCS4;
if( pbszUTF8Str == NULL ) { // 引數錯誤 return 0; }
iNum = 0; // 統計有效字元個數 while( *pbszUTF8Str ) { // UTF8編碼轉換為UCS4編碼 iLen = UTF8_To_UCS4( pbszUTF8Str, dwUCS4 ); if( iLen == 0 ) { // 非法的UTF8編碼 return 0; }
pbszUTF8Str += iLen;
// UCS4編碼轉換為UTF16編碼 iLen = UCS4_To_UTF16( dwUCS4, pwszUTF16Str ); if( iLen == 0 ) { return 0; }
if( pwszUTF16Str != NULL ) { pwszUTF16Str += iLen; }
iNum += iLen; }
if( pwszUTF16Str != NULL ) { *pwszUTF16Str = 0; // 寫入字串結束標記 }
return iNum; }
// 轉換UTF16字串到UTF8字串 INT CUnicodeConverter::UTF16Str_To_UTF8Str( const WORD* pwszUTF16Str, BYTE* pbszUTF8Str ) { INT iNum, iLen; DWORD dwUCS4;
if( pwszUTF16Str == NULL ) { // 引數錯誤 return 0; }
iNum = 0; while( *pwszUTF16Str ) { // UTF16編碼轉換為UCS4編碼 iLen = UTF16_To_UCS4( pwszUTF16Str, dwUCS4 ); if( iLen == 0 ) { // 非法的UTF16編碼 return 0; }
pwszUTF16Str += iLen;
// UCS4編碼轉換為UTF8編碼 iLen = UCS4_To_UTF8( dwUCS4, pbszUTF8Str ); if( iLen == 0 ) { return 0; }
if( pbszUTF8Str != NULL ) { pbszUTF8Str += iLen; }
iNum += iLen; }
if( pbszUTF8Str != NULL ) { *pbszUTF8Str = 0; // 寫入字串結束標記 }
return iNum; }
/* ------------------------------------------------------------- C檔案寫入操作 ------------------------------------------------------------- */
// 向檔案中輸出UTF8編碼 UINT CUnicodeConverter::Print_UTF8_By_UCS4( FILE* out, DWORD dwUCS4 ) { INT iLen; BYTE abUTF8[8];
if( out == NULL ) { return 0; }
iLen = UCS4_To_UTF8( dwUCS4, abUTF8 ); if( iLen == 0 )return 0;
fwrite( abUTF8, 1, iLen, out );
return iLen; }
// 向檔案中輸出UTF16編碼 UINT CUnicodeConverter::Print_UTF16_By_UCS4( FILE* out, DWORD dwUCS4, BOOL isBigEndian ) { INT i, iLen; WORD wCode, awUTF16[2];
if( out == NULL ) { return 0; }
iLen = UCS4_To_UTF16( dwUCS4, awUTF16 ); if( iLen == 0 )return 0;
for( i = 0; i < iLen; i++ ) { wCode = awUTF16[i]; if( isBigEndian ) { fputc( wCode >> 8, out ); // 輸出高位 fputc( wCode & 0xFF, out ); // 輸出低位 } else { fputc( wCode & 0xFF, out ); // 輸出低位 fputc( wCode >> 8, out ); // 輸出高位 } }
return (iLen << 1); }
// 將UTF16字串以UTF8編碼輸出到檔案中 UINT CUnicodeConverter::Print_UTF8Str_By_UTF16Str( FILE* out, const WORD* pwszUTF16Str ) { INT iCount, iLen; DWORD dwUCS4;
if( (out == NULL) || (pwszUTF16Str == NULL) ) { return 0; }
iCount = 0; while( *pwszUTF16Str ) { // 將UTF16編碼轉換成UCS4編碼 iLen = UTF16_To_UCS4( pwszUTF16Str, dwUCS4 ); if( iLen == 0 ) { break; }
pwszUTF16Str += iLen;
// 向檔案中輸出UTF8編碼 iCount += Print_UTF8_By_UCS4( out, dwUCS4 ); }
return iCount; // 輸出的位元組數 }
// 將UTF8字串以UTF16編碼輸出到檔案中 UINT CUnicodeConverter::Print_UTF16Str_By_UTF8Str( FILE* out, const BYTE* pbszUTF8Str, BOOL isBigEndian ) { INT iCount, iLen; DWORD dwUCS4;
if( (out == NULL) || (pbszUTF8Str == NULL) ) { return 0; }
iCount = 0; while( *pbszUTF8Str ) { // 將UTF16編碼轉換成UCS4編碼 iLen = UTF8_To_UCS4( pbszUTF8Str, dwUCS4 ); if( iLen == 0 ) { break; }
pbszUTF8Str += iLen;
// 向檔案中輸出UTF8編碼 iCount += Print_UTF16_By_UCS4( out, dwUCS4, isBigEndian ); }
return iCount; // 輸出的位元組數 }
// 向檔案中輸出UTF8位元組序標記 UINT CUnicodeConverter::Print_UTF8_BOM( FILE* out ) { if( out == NULL ) { return 0; }
fputc( 0xEF, out ); fputc( 0xBB, out ); fputc( 0xBF, out );
return 3; }
// 向檔案中輸出UTF16位元組序標記 UINT CUnicodeConverter::Print_UTF16_BOM( FILE* out, BOOL isBigEndian ) { if( out == NULL ) { return 0; }
if( isBigEndian ) { fputc( 0xFE, out ); fputc( 0xFF, out ); } else { fputc( 0xFF, out ); fputc( 0xFE, out ); }
return 2; }
/* ------------------------------------------------------------- C++流輸出操作 ------------------------------------------------------------- */
// 向流中輸出UTF8編碼 UINT CUnicodeConverter::Print_UTF8_By_UCS4( ostream& os, DWORD dwUCS4 ) { INT iLen; BYTE abUTF8[8];
if( !os )return 0;
iLen = UCS4_To_UTF8( dwUCS4, abUTF8 ); if( iLen == 0 )return 0;
os.write( reinterpret_cast<CHAR*>(abUTF8), iLen );
return iLen; }
// 向流中輸出UTF16編碼 UINT CUnicodeConverter::Print_UTF16_By_UCS4( ostream& os, DWORD dwUCS4, BOOL isBigEndian ) { INT i, iLen; WORD wCode, awUTF16[2];
if( !os )return 0;
iLen = UCS4_To_UTF16( dwUCS4, awUTF16 ); if( iLen == 0 )return 0;
for( i = 0; i < iLen; i++ ) { wCode = awUTF16[i]; if( isBigEndian ) { os.put( wCode >> 8 ); // 輸出高位 os.put( wCode & 0xFF ); // 輸出低位 } else { os.put( wCode & 0xFF ); // 輸出低位 os.put( wCode >> 8 ); // 輸出高位 } }
return (iLen << 1); }
// 將UTF16字串以UTF8編碼輸出到流中 UINT CUnicodeConverter::Print_UTF8Str_By_UTF16Str( ostream& os, const WORD* pwszUTF16Str ) { INT iCount, iLen; DWORD dwUCS4;
if( !os || (pwszUTF16Str == NULL) )return 0;
iCount = 0; while( *pwszUTF16Str ) { // 將UTF16編碼轉換成UCS4編碼 iLen = UTF16_To_UCS4( pwszUTF16Str, dwUCS4 ); if( iLen == 0 ) { break; }
pwszUTF16Str += iLen;
// 向流中輸出UTF8編碼 iCount += Print_UTF8_By_UCS4( os, dwUCS4 ); }
return iCount; // 輸出的位元組數 }
// 將UTF8字串以UTF16編碼輸出到流中 UINT CUnicodeConverter::Print_UTF16Str_By_UTF8Str( ostream& os, const BYTE* pbszUTF8Str, BOOL isBigEndian ) { INT iCount, iLen; DWORD dwUCS4;
if( !os || (pbszUTF8Str == NULL) )return 0;
iCount = 0; while( *pbszUTF8Str ) { // 將UTF16編碼轉換成UCS4編碼 iLen = UTF8_To_UCS4( pbszUTF8Str, dwUCS4 ); if( iLen == 0 ) { break; }
pbszUTF8Str += iLen;
// 向流中輸出UTF8編碼 iCount += Print_UTF16_By_UCS4( os, dwUCS4, isBigEndian ); }
return iCount; // 輸出的位元組數 }
// 向流中輸出UTF8位元組序標記 UINT CUnicodeConverter::Print_UTF8_BOM( ostream& os ) { if( !os )return 0;
os.put( 0xEF ); os.put( 0xBB ); os.put( 0xBF );
return 3; }
// 向流中輸出UTF16位元組序標記 UINT CUnicodeConverter::Print_UTF16_BOM( ostream& os, BOOL isBigEndian ) { if( !os )return 0;
if( isBigEndian ) { os.put( 0xFE ); os.put( 0xFF ); } else { os.put( 0xFF ); os.put( 0xFE ); }
return 2; }
/* ------------------------------ END ------------------------------ */
關於最後的編碼轉換,本人因為該程式開發過去不少時間,編碼轉換到底用不用的上,不好說,一併貼出來,供大家參考。