现在的位置: 首页 > 综合 > 正文

读取ANSI文件存入UNICODE编码的CString——“Ansi转UNICODE”及“UNICODE转Ansi” .

2013年03月11日 ⁄ 综合 ⁄ 共 22836字 ⁄ 字号 评论关闭

[-]

  1. Ansi转UNICODE
  2. 将Ansi编码的文本文件读取存入UNICODE编码的CString
  3. UNICODE转Ansi
  4. 标签替换工具源码

最近在用MFC写一个小的工具,从一个读取一个带特殊标签的文件并将里面的标签替换成对应的数据,然后写入另一个生成文件里。由于输入输出文件是Ansi编码的,程序当中CString类存储格式却是UNICODE编码的,所以不得不解决编码转换的问题。

Ansi转UNICODE

这个部分需要调用MutibyteToWideChar函数,参考http://msdn.microsoft.com/en-us/library/bb202786.aspx
不过有人已经写了可靠的转换函数,建议直接使用下面的这两个函数:
  1. /***************************/  
  2. /* ansi-unicode conversion */  
  3. /***************************/  
  4.   
  5. BOOL AnsiToUnicode16(CHAR *in_Src, WCHAR *out_Dst, INT in_MaxLen)  
  6. {  
  7.     /* locals */  
  8.     INT lv_Len;  
  9.   
  10.   // do NOT decrease maxlen for the eos
      
  11.   if (in_MaxLen <= 0)  
  12.     return FALSE;  
  13.   
  14.   // let windows find out the meaning of ansi
      
  15.   // - the SrcLen=-1 triggers MBTWC to add a eos to Dst and fails if MaxLen is too small.
      
  16.   // - if SrcLen is specified then no eos is added
      
  17.   // - if (SrcLen+1) is specified then the eos IS added
      
  18.   lv_Len = MultiByteToWideChar(CP_ACP, 0, in_Src, -1, out_Dst, in_MaxLen);  
  19.   
  20.   // validate   
  21.   if (lv_Len < 0)  
  22.     lv_Len = 0;  
  23.   
  24.   // ensure eos, watch out for a full buffersize
      
  25.   // - if the buffer is full without an eos then clear the output like MBTWC does
      
  26.   //   in case of too small outputbuffer
      
  27.   // - unfortunately there is no way to let MBTWC return shortened strings,
      
  28.   //   if the outputbuffer is too small then it fails completely
      
  29.   if (lv_Len < in_MaxLen)  
  30.     out_Dst[lv_Len] = 0;  
  31.   else if (out_Dst[in_MaxLen-1])  
  32.     out_Dst[0] = 0;  
  33.   
  34.   // done   
  35.   return TRUE;  
  36. }  
  37.   
  38.   
  39. BOOL AnsiToUnicode16L(CHAR *in_Src, INT in_SrcLen, WCHAR *out_Dst, INT in_MaxLen)  
  40. {  
  41.     /* locals */  
  42.     INT lv_Len;  
  43.   
  44.   
  45.   // do NOT decrease maxlen for the eos
      
  46.   if (in_MaxLen <= 0)  
  47.     return FALSE;  
  48.   
  49.   // let windows find out the meaning of ansi
      
  50.   // - the SrcLen=-1 triggers MBTWC to add a eos to Dst and fails if MaxLen is too small.
      
  51.   // - if SrcLen is specified then no eos is added
      
  52.   // - if (SrcLen+1) is specified then the eos IS added
      
  53.   lv_Len = MultiByteToWideChar(CP_ACP, 0, in_Src, in_SrcLen, out_Dst, in_MaxLen);  
  54.   
  55.   // validate   
  56.   if (lv_Len < 0)  
  57.     lv_Len = 0;  
  58.   
  59.   // ensure eos, watch out for a full buffersize
      
  60.   // - if the buffer is full without an eos then clear the output like MBTWC does
      
  61.   //   in case of too small outputbuffer
      
  62.   // - unfortunately there is no way to let MBTWC return shortened strings,
      
  63.   //   if the outputbuffer is too small then it fails completely
      
  64.   if (lv_Len < in_MaxLen)  
  65.     out_Dst[lv_Len] = 0;  
  66.   else if (out_Dst[in_MaxLen-1])  
  67.     out_Dst[0] = 0;  
  68.   
  69.   // done   
  70.   return TRUE;  
  71. }  

将Ansi编码的文本文件读取存入UNICODE编码的CString

虽然不进行类型转换也可以把读取到的Ansi文本交给CString去处理,但这样CString里面的查找函数是不能正确工作的,因为编码格式不对。所以在做这个操作时,要把编码格式转换一下(本人由于之前没有转换就出现了问题,替换不成功,并且输出文件出现乱码)

以下代码将Ansi文件全部读入并存到成员变量CString m_strTemplate中。代码中动态分配内存,请注意delete。

  1. BOOL HtmlGenerator::LoadTemplate(CString strPath)  
  2. {  
  3.     CFile cfile;  
  4.     CFileException ex;  
  5.   
  6.     char *pBuf = NULL;  
  7.     TCHAR *pTcBuf = NULL;  
  8.   
  9.     UINT nFileLen  = 0;  
  10.   
  11.     // 打开文件   
  12.     if (!cfile.Open(strPath, CFile::modeRead | CFile::shareDenyWrite, &ex))  
  13.     {  
  14.         TCHAR szError[1024];  
  15.         ex.GetErrorMessage(szError, 1024);  
  16.         TRACE1("Couldn't open source file: %1024s\n", szError);  
  17.         return FALSE;  
  18.     }  
  19.   
  20.     // 获得文件长度   
  21.     nFileLen = (int)cfile.GetLength();  
  22.   
  23.     // 分配内存进行读取   
  24.     pBuf = new char[nFileLen + 1];  
  25.     pTcBuf = new TCHAR[nFileLen + 1];  
  26.   
  27.     cfile.Read(pBuf, nFileLen);  
  28.     pBuf[nFileLen] = '\0';    // 将字符串结尾标记为'\0'
      
  29.   
  30.     // 将Ansi编码转为UNICODE   
  31.     AnsiToUnicode16L(pBuf, nFileLen, pTcBuf, nFileLen);  
  32.   
  33.     // 将读取的模板文件保存到成员变量中
      
  34.     m_strTemplate = pTcBuf;  
  35.     m_strHtmlContent = m_strTemplate;  
  36.   
  37.     // 回收动态分配的内存   
  38.     delete [] pBuf;  
  39.     delete [] pTcBuf;  
  40.     cfile.Close();  
  41.   
  42.     return TRUE;  
  43. }  

UNICODE转Ansi

这个部分可以调用WideCharToMultiByte来完成,但是如果使用CString的话,有一种更简单的解决办法:

  1. // 将UNICODE转回Ansi编码   
  2. CStringA strAnsi(m_strHtmlContent.GetBuffer(0));  
  3.   
  4. cfile.Write(strAnsi.GetBuffer(), strAnsi.GetLength());  

上述代码中

CStringA strAnsi(m_strHtmlContent.GetBuffer(0));将以UNICODE编码的CString m_strHtmlContent转成了ANSI格式编码的CStringA strAnsi,要获取Ansi格式编码的字符串,只需要调用strAnsi.GetBuffer()就可以了。

标签替换工具源码

HtmlGenerator.h

  1. #pragma once   
  2. class HtmlGenerator  
  3. {  
  4. public:  
  5.     HtmlGenerator(void);  
  6.     ~HtmlGenerator(void);  
  7.   
  8.     BOOL LoadTemplate(CString strPath);    // 装载HTML模板
      
  9.     BOOL WriteHtml(CString strPath);       // 将处理好的HTML写入文件
      
  10.     int ReplaceTag(CString strTag, CString strValue);       // 替换标签,返回值表示替换掉的标签个数
      
  11.     void Restore(void){m_strHtmlContent = m_strTemplate;}   // 将修改过的HTML恢复成与模板相同
      
  12. private:  
  13.     CString m_strTemplate;  
  14.     CString m_strHtmlContent;  
  15. };  
  16.   
  17. BOOL AnsiToUnicode16(CHAR *in_Src, WCHAR *out_Dst, INT in_MaxLen);  
  18. BOOL AnsiToUnicode16L(CHAR *in_Src, INT in_SrcLen, WCHAR *out_Dst, INT in_MaxLen);  

HtmlGenerator.cpp

  1. #include "StdAfx.h"   
  2. #include "HtmlGenerator.h"   
  3.   
  4.   
  5. HtmlGenerator::HtmlGenerator(void)  
  6. {  
  7. }  
  8.   
  9.   
  10. HtmlGenerator::~HtmlGenerator(void)  
  11. {  
  12. }  
  13.   
  14. BOOL HtmlGenerator::LoadTemplate(CString strPath)  
  15. {  
  16.     CFile cfile;  
  17.     CFileException ex;  
  18.   
  19.     char *pBuf = NULL;  
  20.     TCHAR *pTcBuf = NULL;  
  21.   
  22.     UINT nFileLen  = 0;  
  23.   
  24.     // 打开文件   
  25.     if (!cfile.Open(strPath, CFile::modeRead | CFile::shareDenyWrite, &ex))  
  26.     {  
  27.         TCHAR szError[1024];  
  28.         ex.GetErrorMessage(szError, 1024);  
  29.         TRACE1("Couldn't open source file: %1024s\n", szError);  
  30.         return FALSE;  
  31.     }  
  32.   
  33.     // 获得文件长度   
  34.     nFileLen = (int)cfile.GetLength();  
  35.   
  36.     // 分配内存进行读取   
  37.     pBuf = new char[nFileLen + 1];  
  38.     pTcBuf = new TCHAR[nFileLen + 1];  
  39.   
  40.     cfile.Read(pBuf, nFileLen);  
  41.     pBuf[nFileLen] = '\0';    // 将字符串结尾标记为'\0'
      
  42.   
  43.     // 将Ansi编码转为UNICODE
      
  44.     AnsiToUnicode16L(pBuf, nFileLen, pTcBuf, nFileLen);  
  45.   
  46.     // 将读取的模板文件保存到成员变量中   
  47.     m_strTemplate = pTcBuf;  
  48.     m_strHtmlContent = m_strTemplate;  
  49.   
  50.     // 回收动态分配的内存   
  51.     delete [] pBuf;  
  52.     delete [] pTcBuf;  
  53.     cfile.Close();  
  54.   
  55.     return TRUE;  
  56. }  
  57.   
  58. BOOL HtmlGenerator::WriteHtml(CString strPath)  
  59. {  
  60.   CFile cfile;  
  61.   CFileException ex;  
  62.   
  63.   if (!cfile.Open(strPath, CFile::modeCreate | CFile::modeReadWrite, &ex))  
  64.   {  
  65.         TCHAR szError[1024];  
  66.         ex.GetErrorMessage(szError, 1024);  
  67.         TRACE1("Couldn't open dest file: %1024s\n", szError);  
  68.         return FALSE;  
  69.   }  
  70.   
  71.   // 将UNICODE转回Ansi编码   
  72.   CStringA strAnsi(m_strHtmlContent.GetBuffer(0));  
  73.   
  74.   cfile.Write(strAnsi.GetBuffer(), strAnsi.GetLength());  
  75.   cfile.Flush();  
  76.   cfile.Close();  
  77.   return TRUE;  
  78. }  
  79.   
  80. int HtmlGenerator::ReplaceTag(CString strTag, CString strValue)  
  81. {  
  82.     return m_strHtmlContent.Replace(strTag, strValue);  
  83. }  
  84.   
  85.   
  86. /***************************/  
  87. /* ansi-unicode conversion */  
  88. /***************************/  
  89.   
  90. BOOL AnsiToUnicode16(CHAR *in_Src, WCHAR *out_Dst, INT in_MaxLen)  
  91. {  
  92.     /* locals */  
  93.     INT lv_Len;  
  94.   
  95.   // do NOT decrease maxlen for the eos
      
  96.   if (in_MaxLen <= 0)  
  97.     return FALSE;  
  98.   
  99.   // let windows find out the meaning of ansi
      
  100.   // - the SrcLen=-1 triggers MBTWC to add a eos to Dst and fails if MaxLen is too small.
      
  101.   // - if SrcLen is specified then no eos is added
      
  102.   // - if (SrcLen+1) is specified then the eos IS added
      
  103.   lv_Len = MultiByteToWideChar(CP_ACP, 0, in_Src, -1, out_Dst, in_MaxLen);  
  104.   
  105.   // validate   
  106.   if (lv_Len < 0)  
  107.     lv_Len = 0;  
  108.   
  109.   // ensure eos, watch out for a full buffersize
      
  110.   // - if the buffer is full without an eos then clear the output like MBTWC does
      
  111.   //   in case of too small outputbuffer
      
  112.   // - unfortunately there is no way to let MBTWC return shortened strings,
      
  113.   //   if the outputbuffer is too small then it fails completely
      
  114.   if (lv_Len < in_MaxLen)  
  115.     out_Dst[lv_Len] = 0;  
  116.   else if (out_Dst[in_MaxLen-1])  
  117.     out_Dst[0] = 0;  
  118.   
  119.   // done   
  120.   return TRUE;  
  121. }  
  122.   
  123.   
  124. BOOL AnsiToUnicode16L(CHAR *in_Src, INT in_SrcLen, WCHAR *out_Dst, INT in_MaxLen)  
  125. {  
  126.     /* locals */  
  127.     INT lv_Len;  
  128.   
  129.   
  130.   // do NOT decrease maxlen for the eos
      
  131.   if (in_MaxLen <= 0)  
  132.     return FALSE;  
  133.   
  134.   // let windows find out the meaning of ansi
      
  135.   // - the SrcLen=-1 triggers MBTWC to add a eos to Dst and fails if MaxLen is too small.
      
  136.   // - if SrcLen is specified then no eos is added
      
  137.   // - if (SrcLen+1) is specified then the eos IS added
      
  138.   lv_Len = MultiByteToWideChar(CP_ACP, 0, in_Src, in_SrcLen, out_Dst, in_MaxLen);  
  139.   
  140.   // validate   
  141.   if (lv_Len < 0)  
  142.     lv_Len = 0;  
  143.   
  144.   // ensure eos, watch out for a full buffersize
      
  145.   // - if the buffer is full without an eos then clear the output like MBTWC does
      
  146.   //   in case of too small outputbuffer
      
  147.   // - unfortunately there is no way to let MBTWC return shortened strings,
      
  148.   //   if the outputbuffer is too small then it fails completely
      
  149.   if (lv_Len < in_MaxLen)  
  150.     out_Dst[lv_Len] = 0;  
  151.   else if (out_Dst[in_MaxLen-1])  
  152.     out_Dst[0] = 0;  
  153.   
  154.   // done   
  155.   return TRUE;  
  156. }  

最近在用MFC写一个小的工具,从一个读取一个带特殊标签的文件并将里面的标签替换成对应的数据,然后写入另一个生成文件里。由于输入输出文件是Ansi编码的,程序当中CString类存储格式却是UNICODE编码的,所以不得不解决编码转换的问题。

Ansi转UNICODE

这个部分需要调用MutibyteToWideChar函数,参考http://msdn.microsoft.com/en-us/library/bb202786.aspx
不过有人已经写了可靠的转换函数,建议直接使用下面的这两个函数:
  1. /***************************/  
  2. /* ansi-unicode conversion */  
  3. /***************************/  
  4.   
  5. BOOL AnsiToUnicode16(CHAR *in_Src, WCHAR *out_Dst, INT in_MaxLen)  
  6. {  
  7.     /* locals */  
  8.     INT lv_Len;  
  9.   
  10.   // do NOT decrease maxlen for the eos
      
  11.   if (in_MaxLen <= 0)  
  12.     return FALSE;  
  13.   
  14.   // let windows find out the meaning of ansi
      
  15.   // - the SrcLen=-1 triggers MBTWC to add a eos to Dst and fails if MaxLen is too small.
      
  16.   // - if SrcLen is specified then no eos is added
      
  17.   // - if (SrcLen+1) is specified then the eos IS added
      
  18.   lv_Len = MultiByteToWideChar(CP_ACP, 0, in_Src, -1, out_Dst, in_MaxLen);  
  19.   
  20.   // validate   
  21.   if (lv_Len < 0)  
  22.     lv_Len = 0;  
  23.   
  24.   // ensure eos, watch out for a full buffersize
      
  25.   // - if the buffer is full without an eos then clear the output like MBTWC does
      
  26.   //   in case of too small outputbuffer
      
  27.   // - unfortunately there is no way to let MBTWC return shortened strings,
      
  28.   //   if the outputbuffer is too small then it fails completely
      
  29.   if (lv_Len < in_MaxLen)  
  30.     out_Dst[lv_Len] = 0;  
  31.   else if (out_Dst[in_MaxLen-1])  
  32.     out_Dst[0] = 0;  
  33.   
  34.   // done   
  35.   return TRUE;  
  36. }  
  37.   
  38.   
  39. BOOL AnsiToUnicode16L(CHAR *in_Src, INT in_SrcLen, WCHAR *out_Dst, INT in_MaxLen)  
  40. {  
  41.     /* locals */  
  42.     INT lv_Len;  
  43.   
  44.   
  45.   // do NOT decrease maxlen for the eos
      
  46.   if (in_MaxLen <= 0)  
  47.     return FALSE;  
  48.   
  49.   // let windows find out the meaning of ansi
      
  50.   // - the SrcLen=-1 triggers MBTWC to add a eos to Dst and fails if MaxLen is too small.
      
  51.   // - if SrcLen is specified then no eos is added
      
  52.   // - if (SrcLen+1) is specified then the eos IS added
      
  53.   lv_Len = MultiByteToWideChar(CP_ACP, 0, in_Src, in_SrcLen, out_Dst, in_MaxLen);  
  54.   
  55.   // validate   
  56.   if (lv_Len < 0)  
  57.     lv_Len = 0;  
  58.   
  59.   // ensure eos, watch out for a full buffersize
      
  60.   // - if the buffer is full without an eos then clear the output like MBTWC does
      
  61.   //   in case of too small outputbuffer
      
  62.   // - unfortunately there is no way to let MBTWC return shortened strings,
      
  63.   //   if the outputbuffer is too small then it fails completely
      
  64.   if (lv_Len < in_MaxLen)  
  65.     out_Dst[lv_Len] = 0;  
  66.   else if (out_Dst[in_MaxLen-1])  
  67.     out_Dst[0] = 0;  
  68.   
  69.   // done   
  70.   return TRUE;  
  71. }  

将Ansi编码的文本文件读取存入UNICODE编码的CString

虽然不进行类型转换也可以把读取到的Ansi文本交给CString去处理,但这样CString里面的查找函数是不能正确工作的,因为编码格式不对。所以在做这个操作时,要把编码格式转换一下(本人由于之前没有转换就出现了问题,替换不成功,并且输出文件出现乱码)

以下代码将Ansi文件全部读入并存到成员变量CString m_strTemplate中。代码中动态分配内存,请注意delete。

  1. BOOL HtmlGenerator::LoadTemplate(CString strPath)  
  2. {  
  3.     CFile cfile;  
  4.     CFileException ex;  
  5.   
  6.     char *pBuf = NULL;  
  7.     TCHAR *pTcBuf = NULL;  
  8.   
  9.     UINT nFileLen  = 0;  
  10.   
  11.     // 打开文件   
  12.     if (!cfile.Open(strPath, CFile::modeRead | CFile::shareDenyWrite, &ex))  
  13.     {  
  14.         TCHAR szError[1024];  
  15.         ex.GetErrorMessage(szError, 1024);  
  16.         TRACE1("Couldn't open source file: %1024s\n", szError);  
  17.         return FALSE;  
  18.     }  
  19.   
  20.     // 获得文件长度   
  21.     nFileLen = (int)cfile.GetLength();  
  22.   
  23.     // 分配内存进行读取   
  24.     pBuf = new char[nFileLen + 1];  
  25.     pTcBuf = new TCHAR[nFileLen + 1];  
  26.   
  27.     cfile.Read(pBuf, nFileLen);  
  28.     pBuf[nFileLen] = '\0';    // 将字符串结尾标记为'\0'
      
  29.   
  30.     // 将Ansi编码转为UNICODE   
  31.     AnsiToUnicode16L(pBuf, nFileLen, pTcBuf, nFileLen);  
  32.   
  33.     // 将读取的模板文件保存到成员变量中
      
  34.     m_strTemplate = pTcBuf;  
  35.     m_strHtmlContent = m_strTemplate;  
  36.   
  37.     // 回收动态分配的内存   
  38.     delete [] pBuf;  
  39.     delete [] pTcBuf;  
  40.     cfile.Close();  
  41.   
  42.     return TRUE;  
  43. }  

UNICODE转Ansi

这个部分可以调用WideCharToMultiByte来完成,但是如果使用CString的话,有一种更简单的解决办法:

  1. // 将UNICODE转回Ansi编码   
  2. CStringA strAnsi(m_strHtmlContent.GetBuffer(0));  
  3.   
  4. cfile.Write(strAnsi.GetBuffer(), strAnsi.GetLength());  

上述代码中

CStringA strAnsi(m_strHtmlContent.GetBuffer(0));将以UNICODE编码的CString m_strHtmlContent转成了ANSI格式编码的CStringA strAnsi,要获取Ansi格式编码的字符串,只需要调用strAnsi.GetBuffer()就可以了。

标签替换工具源码

HtmlGenerator.h

  1. #pragma once   
  2. class HtmlGenerator  
  3. {  
  4. public:  
  5.     HtmlGenerator(void);  
  6.     ~HtmlGenerator(void);  
  7.   
  8.     BOOL LoadTemplate(CString strPath);    // 装载HTML模板
      
  9.     BOOL WriteHtml(CString strPath);       // 将处理好的HTML写入文件
      
  10.     int ReplaceTag(CString strTag, CString strValue);       // 替换标签,返回值表示替换掉的标签个数
      
  11.     void Restore(void){m_strHtmlContent = m_strTemplate;}   // 将修改过的HTML恢复成与模板相同
      
  12. private:  
  13.     CString m_strTemplate;  
  14.     CString m_strHtmlContent;  
  15. };  
  16.   
  17. BOOL AnsiToUnicode16(CHAR *in_Src, WCHAR *out_Dst, INT in_MaxLen);  
  18. BOOL AnsiToUnicode16L(CHAR *in_Src, INT in_SrcLen, WCHAR *out_Dst, INT in_MaxLen);  

HtmlGenerator.cpp

  1. #include "StdAfx.h"   
  2. #include "HtmlGenerator.h"   
  3.   
  4.   
  5. HtmlGenerator::HtmlGenerator(void)  
  6. {  
  7. }  
  8.   
  9.   
  10. HtmlGenerator::~HtmlGenerator(void)  
  11. {  
  12. }  
  13.   
  14. BOOL HtmlGenerator::LoadTemplate(CString strPath)  
  15. {  
  16.     CFile cfile;  
  17.     CFileException ex;  
  18.   
  19.     char *pBuf = NULL;  
  20.     TCHAR *pTcBuf = NULL;  
  21.   
  22.     UINT nFileLen  = 0;  
  23.   
  24.     // 打开文件   
  25.     if (!cfile.Open(strPath, CFile::modeRead | CFile::shareDenyWrite, &ex))  
  26.     {  
  27.         TCHAR szError[1024];  
  28.         ex.GetErrorMessage(szError, 1024);  
  29.         TRACE1("Couldn't open source file: %1024s\n", szError);  
  30.         return FALSE;  

抱歉!评论已关闭.