【VS2019】【PyQt】 Warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。(附自己写的Python脚本完成文件编码批量转换)

【内容更新】

刚刚发现了大佬的做法 记visual studio2019中文乱码解决,在此啪啪啪地打自己脸。大佬的解决方法可以说是非常的舒服了,打脸打的心服口服。
博客的旧内容(扇脸)就不改了,感兴趣的可以看看下面的打脸内容,或者直接拉到文尾试用一下Python脚本。正常来说这脚本应该不会跑飞的,跑出意外的话多半是chardet.detect()判断编码出错导致转码失败。
疯狂打脸
虽然在VS2019里头添加新文件,其编码仍然为ANSI(也就是GB2312),不是utf-8,但这个问题可以去 扩展→管理扩展安装插件去解决。安装这个插件可能会出现这个问题 VS2019插件“Force UTF-8(No Bom)”造成输出乱码,这个我目前没啥好的解决方法,我在代码中加入简单粗暴的一句 system(“chcp 65001”) 修改程序当前代码页让程序不输出乱码。


我这里就不放出“有问题请留言”之类的话了,因为我也不是别人有提问就一定会去帮忙的大善人,而且万一别人的问题我还解决不了的话那就更打脸,所以想留言就留吧虽然我不一定会回。






这个问题,影响了我很长一段时间,很恶心很恶心,我用我那贫瘠的知识去分析,去想,去思考,这“当前代码页(936)”到底是个什么东西,到底在哪,为什么改不掉,为什么就不能让我选择代码页,我甚至在项目的属性页里头去设置了可能有用的东西,但还是不顶用,大半天在下饭都快把我自己给喂的撑死

项目属性配置尝试修改代码页修改失败






网上很多的垃圾办法是,在VS2019去设置 “高级保存选项” 去修改源文件的编码(而且十个至少六个是这种解决方法就非常的让人烦躁),说是垃圾办法,是因为这完全就治标不治本。
我当前情况是在VS2019撸码撸函数,然后把文件拖进QtCreator去跑去看实际运行结果。有时就会来个编码不正确的问题,一两次还好说,经常这样就很烦的了。
QtCreator编码错误
这就只能去改文件编码,那就去改吧,一个一个地全改成UTF-8-BOM(不改成utf-8是因为VS2019小天才在编译过程中并不能识别这份编码)。敲代码敲着敲着,感觉需要弄多几个类,于是在VS2019里头添加了新的文件。你猜猜那些新文件的编码是什么?没错,是GB2312,中文编码,厉害吧,(下面截图中的ANSI为系统编码,我也不太好说这就是中文编码,但至少它并不是utf-8编码)。
这就直接造成了项目文件的编码混乱:你的一个项目里,使用的编码至少有utf-8、UTF-8-BOM、GB2312,而GB2312编码的文件拖进QtCreator时会不识别要重新选合适的编码(上面那张图就是QtCreator不识别了)

VS2019添加新文件
NotePad++查看文件编码





扯的天南地北,回到标题。这里讨论下为什么会出现这个烦人到极致的C4819:
Windows的软件分为两类,一类是Unicode的,另一类是非Unicode的(这个说法是从别的地方看到的,但标签已经关了,也懒得去翻,就不标明出处了)
个人观点是VS2019是非Unicode软件,程序运行时采用的代码页已经锁死在936上了,这想改也不好改,因为这是和系统设置关联的。反复咀嚼官方给出的C4819的解决方法,直接得出结论:如果你的文件,编码是utf-8,那趁早改成别的编码,或者改用VSCode,因为VS2019不识别utf-8的文件。
修改区域设置
或者用别的说法:如果你有一份文件,里头用了阿拉伯语西班牙语之类的奇奇怪怪的语言,那么这份文件也只能在相对应的编码中才能正确识别,否则只会是乱码,所以这个文件如果直接拖进VS2019,那么势必是乱码的。那么,要是参考上图官方给出的做法,把“区域设置”的“中文”改成阿拉伯语之类的语言,那么会怎么样呢?这我没去尝试(改这东西有可能会翻车不敢乱动,顺便一说下面的Beta别去选,那是比鸡肋还鸡肋的无用之物),但猜测改了那个系统设置之后VS2019能够识别那份文件,也猜测VS2019的代码页从936 “成功” 改成了其他的值。为什么强调是“成功”呢? 因为这个代码页不是你自由选择的,是由系统设置决定的,而且最关键的是,你不能让它选为65001(utf-8编码) ,也就是这厮注定是识别不了utf-8编码的文件,或许有插件可以?没怎么了解过,所以才说自己知识贫瘠。





于是自己花了一天的时间去写了个py脚本(大部分时间花在了QT界面上),在需要的时候把文件编码批量转成UTF-8-BOM或者其他编码。虽然不怎么想把自己一天的劳动成果就这么放在博客上,但还是放上去好了,毕竟也参考过不少陌生人的博客、知乎。下面的Python脚本不出意外是可以正常执行的(需要Qt库,自己去装吧)

代码量很大,耦合度还算可以,设计了三个控件类一个主窗口类。
控件类可以直接使用,可以直接拖到有需要的地方(虽然封装的不怎么样)。XJ_TreeView(树视图)的话我觉得我写的还可以(蜜汁自信?),使用起来也比较方便,至少使用过程中不再去关心内容添加修改的细节了(只完成了少量功能,但对我来说够用了)。另外两个控件类就随便写写的,主要是为了减轻主窗口类的负担,让主窗口类的内部的逻辑清晰一点(但实际上还是很乱,至少变量名取的乱七八糟让人烦躁)。
主窗口类的内部耦合度可以说是很高很高的了,夹杂着的东西乱到让人怀疑人生,反正我已经完全不想去动这个类了。想从主窗口类里头剥离出单独的功能可以说不现实,像是想学习“py转换编码”、“文件读取保存”、“盒布局”的话还不如直接去查。
我也不认为有人会有耐心把我的代码仔细分析完。脚本代码量350左右,而我平时看别人博客超过二三十行代码我就没心情去翻

py脚本运行结果

'''
【XJ自制脚本】
这个脚本花了一整天完成的。
因为VS2019和QtCreator来回拖文件而且文件编码还不一致,导致了每次运行前都要手动选择编码(否则就显示乱码)。
一次两次就算了,但反复提示重选编码。实在受不了,就花了一天时间去写这个东西。
运行效果个人感觉还行,能跑,作为以后常用的工具使用。
'''

import chardet
import sys
import os
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt,QModelIndex,QItemSelectionModel
from PyQt5.QtGui import QStandardItemModel, QStandardItem,QFont
from PyQt5.QtWidgets import *


class XJ_TreeView(QTreeView):
    class XJ_Iter:
        def __init__(self,iter):
            self.__iter=iter

        def AppendRow(self,data):#添加数据(一个列表
            lst=[]
            for i in data:
                lst.append(QStandardItem(str(i)))
                lst[-1].setEditable(False)
            self.__iter.appendRow(lst)
            return XJ_TreeView.XJ_Iter(lst[0])
        
        def Copy(self):
            return XJ_TreeView.XJ_Iter(self.__iter)
            
        def Back(self):#返回上一级(返回失败则返回false
            if(type(self.__iter)==QStandardItemModel):
                return False
            if(self.__iter.parent()==None):
                self.__iter=self.__iter.model()
            else:
                self.__iter=self.__iter.parent()
            return True
            
        def Next(self,i):#进入下一级(进入失败则返回false
            if(0<=i<self.__iter.rowCount()):
                if(type(self.__iter)!=QStandardItemModel):
                    self.__iter=self.__iter.child(i,0)
                else:
                    self.__iter=self.__iter.itemFromIndex(self.__iter.index(i,0))
                return True
            else:
                return False
                
        def GetData(self):#获取数据(一个列表
            if(type(self.__iter)==QStandardItemModel):
                return None
            result=[]
            model=self.__iter.model()
            index=self.__iter.index()
            i=0
            while(index.isValid()):
                result.append(model.itemFromIndex(index).text())
                i+=1
                index=index.siblingAtColumn(i)
            return result
            
        def SetData(self,i,data):#设置第i个单元格的内容(设置失败则返回false
            if(type(self.__iter)=&
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值