1. 程式人生 > >關於以前excel記憶體開啟操作函式的使用說明。

關於以前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 ------------------------------ */

關於最後的編碼轉換,本人因為該程式開發過去不少時間,編碼轉換到底用不用的上,不好說,一併貼出來,供大家參考。