Discuz! Board

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2230|回复: 1
打印 上一主题 下一主题

如何解决:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbc in positio...

[复制链接]

1272

主题

2067

帖子

7958

积分

认证用户组

Rank: 5Rank: 5

积分
7958
跳转到指定楼层
楼主
发表于 2020-3-12 11:27:51 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
如何解决:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbc in position 0: invalid start byte
含有中文的cpp和h文件,在python中报上面错误
用Notpad++不能直接转为utf-8
可先用记事本转成utf-8 bom 再用notpad++转成utf-8

回复

使用道具 举报

1272

主题

2067

帖子

7958

积分

认证用户组

Rank: 5Rank: 5

积分
7958
沙发
 楼主| 发表于 2020-3-12 11:29:28 | 只看该作者
vs下,GBK格式的.h .cpp 编译时,自动转换为UTF-8

转自

http://suool.net/


在VS下面开发Cocos程序的时候,他的默认编码是GBK的,但是在迁移或者是编译调试的时候要求UTF的编码更为方便。因此便有了将C++文件的编码格式转换为UTF-8的需求问题。

这个问题,当然可以在建立文件保存的时候选择高级保存选择,然后选择保存的格式。


但是,显然,在项目文件很多的时候,这个不是一个聪明的选择。所以,就要想办法如何批量的转化处理。
在Linux下面有专门的命令可以实现这个功能。
在Windows下面要如何做呢?
当然,借助于我们万能的C++一样可以很方便的解决它,经过一番查找资料,现在共享一下我的解决方法,首先,要在VS里面建立一个VC的控制台程序项目。
然后新建一个convert源文件。代码如下:
  1. //  定义控制台应用程序的入口点。  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <afxwin.h>  
  6. #include <string>  
  7. #include <iostream>  
  8.   
  9. #ifdef _DEBUG  
  10. #define new DEBUG_NEW  
  11. #endif  
  12.   
  13. #define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1  
  14.   
  15. // 唯一的应用程序对象  
  16.   
  17. CWinApp theApp;  
  18.   
  19. using namespace std;  
  20.   
  21. void recursiveFile(CString strFileType);  
  22. void convertGBToUTF8(CString strWritePath, const char* gb2312);  
  23.   
  24. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])  
  25. {  
  26.     int nRetCode = 0;  
  27.   
  28.     // 初始化 MFC 并在失败时显示错误  
  29.     if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))  
  30.     {  
  31.         // TODO: 更改错误代码以符合您的需要  
  32.         _tprintf(_T("错误: MFC 初始化失败\n"));  
  33.         nRetCode = 1;  
  34.     }  
  35.     else  
  36.     {  
  37.         /*for(int i = 0; i < argc; i++)
  38.         {
  39.         MessageBox(NULL, argv[i], L"Arglist contents", MB_OK);
  40.         }*/  
  41.         //声明一个CFileFind类变量,以用来搜索  
  42.   
  43.         //接受一个参数作为源代码文件的根目录  
  44.         TCHAR *lpszDirName = argv[1];  
  45.         CString strFileType;  
  46.         strFileType.Format(_T("%s\\*.*"), lpszDirName);  
  47.         //递归此目录下的.h文件和.cpp文件,如果发现不是utf8编码则转换为utf8编码  
  48.         recursiveFile(strFileType);  
  49.   
  50.     }  
  51.   
  52.     return nRetCode;  
  53. }  
  54.   
  55. void recursiveFile(CString strFileType)  
  56. {  
  57.     CFileFind finder;  
  58.     BOOL isFinded = finder.FindFile(strFileType);//查找第一个文件  
  59.     while (isFinded)  
  60.     {  
  61.         isFinded = finder.FindNextFile(); //递归搜索其他的文件  
  62.         if (!finder.IsDots()) //如果不是"."目录  
  63.         {  
  64.             CString strFoundFile = finder.GetFilePath();  
  65.             if (finder.IsDirectory()) //如果是目录,则递归地调用  
  66.             {  
  67.                 CString strNextFileType;  
  68.                 strNextFileType.Format(_T("%s\\*.*"), strFoundFile);  
  69.                 recursiveFile(strNextFileType);  
  70.             }  
  71.             else  
  72.             {  
  73.                 //如果是头文件或cpp文件  
  74.                 if (strFoundFile.Right(4) == _T(".cpp") || strFoundFile.Right(2) == _T(".h")) {  
  75.                     CFile fileReader(strFoundFile, CFile::modeRead);  
  76.                     byte head[3];  
  77.                     fileReader.Read(head, 3);  
  78.                     //判断是否带有BOM文件头  
  79.                     if (head[0] == 0xef && head[1] == 0xbb && head[2] == 0xbf)  
  80.                     {  
  81.                         fileReader.Close();  
  82.                         continue;  
  83.                     }  
  84.                     fileReader.SeekToBegin();  
  85.   
  86.                     int bufLength = 256;  
  87.                     char *buf = new char[bufLength];  
  88.                     ZeroMemory(buf, bufLength);  
  89.                     int nReadLength;  
  90.                     std::string strContent;  
  91.                     while ((nReadLength = fileReader.Read(buf, bufLength)))  
  92.                     {  
  93.                         strContent.append(buf, nReadLength);  
  94.                         ZeroMemory(buf, nReadLength);  
  95.                     }  
  96.                     delete buf;  
  97.                     fileReader.Close();  
  98.                     convertGBToUTF8(strFoundFile, strContent.c_str());  
  99.   
  100.                     TCHAR* fileName = new TCHAR[strFoundFile.GetLength() + 1];  
  101.                     //wcscpy_s(*fileName, strFoundFile);  
  102.   
  103.                     // 中文路径存在问题,可以将下面的输出屏蔽,程序将静默运行  
  104.                     printf("%S已经转换为UTF-8编码", strFoundFile.GetBuffer(0));  
  105.                     cout << endl;  
  106.   
  107.                     if (_tcslen(fileName) >0)  
  108.                     {  
  109.                         delete[] fileName;  
  110.                     }  
  111.                 }  
  112.             }  
  113.         }  
  114.     }  
  115.     finder.Close();  
  116. }  
  117.   
  118. void convertGBToUTF8(CString strWritePath, const char* gb2312)  
  119. {  
  120.     CFile fp;  
  121.     fp.Open(strWritePath, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary, NULL);  
  122.     int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);  
  123.     wchar_t* wstr = new wchar_t[len + 1];  
  124.     memset(wstr, 0, len + 1);  
  125.     MultiByteToWideChar(CP_ACP, 0, gb2312, -1, wstr, len);  
  126.     len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);  
  127.     char* str = new char[len + 1];  
  128.     memset(str, 0, len + 1);  
  129.     len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);  
  130.     if (wstr) delete[] wstr;  
  131.     str[len] = '\n';  
  132.     const unsigned char aryBOM[] = { 0xEF, 0xBB, 0xBF };  
  133.     fp.Write(aryBOM, sizeof(aryBOM));  
  134.     fp.Write(str, len);  
  135.     delete[] str;  
  136.     fp.Close();  
  137. }  
复制代码
如果编译出现错误请点击,项目--属性--一般------MFC的使用选择共享DLL的方式。

然后将编译成功的.exe文件放在项目的目录下,比如:

然后选择项目,属性的与生成事件,将要转换的源码目录放在.exe 的后面即可,这样虽然在您编写的时候保存的是GBK,但是在项目进行编译之前会把指定目录下的所有C++源码文件转换为UTF-8的格式,具体格式如下:

当然,您也可以直接在cmd中运行该exe文件,在后面加上要转换的目录即可。格式为: convert.exe Dir
这样在编译之前就会先将源码文件格式转换为UTF-8的格式。

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|firemail ( 粤ICP备15085507号-1 )

GMT+8, 2024-11-23 08:17 , Processed in 0.058298 second(s), 19 queries .

Powered by Discuz! X3

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表