Godot 4 源码分析 - 文件读入编码处理
今天需要读入xml文件进行处理,结果读入一个带中文的文件时,出错了。当然程序还能运行,但编译器一直报错,而且XML解析也不正确
单步调试发现读入的内容出现乱码,具体逻辑:
String FileAccess::get_as_text(bool p_skip_cr) const {uint64_t original_pos = get_position();const_cast<FileAccess *>(this)->seek(0);String text = get_as_utf8_string(p_skip_cr);const_cast<FileAccess *>(this)->seek(original_pos);return text;
}String FileAccess::get_as_utf8_string(bool p_skip_cr, String encoding) const {encoding = encoding.to_lower();Vector<uint8_t> sourcef;uint64_t len = get_length();sourcef.resize(len + 1);uint8_t *w = sourcef.ptrw();uint64_t r = get_buffer(w, len);ERR_FAIL_COND_V(r != len, String());w[len] = 0;String s((const char *)w);s.parse_utf8((const char *)w, -1, p_skip_cr);return s;
}Error String::parse_utf8(const char *p_utf8, int p_len, bool p_skip_cr) {if (!p_utf8) {return ERR_INVALID_DATA;}String aux;int cstr_size = 0;int str_size = 0;/* HANDLE BOM (Byte Order Mark) */if (p_len < 0 || p_len >= 3) {bool has_bom = uint8_t(p_utf8[0]) == 0xef && uint8_t(p_utf8[1]) == 0xbb && uint8_t(p_utf8[2]) == 0xbf;if (has_bom) {//8-bit encoding, byte order has no meaning in UTF-8, just skip itif (p_len >= 0) {p_len -= 3;}p_utf8 += 3;}}bool decode_error = false;bool decode_failed = false;{const char *ptrtmp = p_utf8;const char *ptrtmp_limit = &p_utf8[p_len];int skip = 0;uint8_t c_start = 0;while (ptrtmp != ptrtmp_limit && *ptrtmp) {uint8_t c = *ptrtmp >= 0 ? *ptrtmp : uint8_t(256 + *ptrtmp);if (skip == 0) {if (p_skip_cr && c == '\r') {ptrtmp++;continue;}/* Determine the number of characters in sequence */if ((c & 0x80) == 0) {skip = 0;} else if ((c & 0xe0) == 0xc0) {skip = 1;} else if ((c & 0xf0) == 0xe0) {skip = 2;} else if ((c & 0xf8) == 0xf0) {skip = 3;} else if ((c & 0xfc) == 0xf8) {skip = 4;} else if ((c & 0xfe) == 0xfc) {skip = 5;} else {skip = 0;print_unicode_error(vformat("Invalid UTF-8 leading byte (%x)", c), true);decode_failed = true;}c_start = c;if (skip == 1 && (c & 0x1e) == 0) {print_unicode_error(vformat("Overlong encoding (%x ...)", c));decode_error = true;}str_size++;} else {if ((c_start == 0xe0 && skip == 2 && c < 0xa0) || (c_start == 0xf0 && skip == 3 && c < 0x90) || (c_start == 0xf8 && skip == 4 && c < 0x88) || (c_start == 0xfc && skip == 5 && c < 0x84)) {print_unicode_error(vformat("Overlong encoding (%x %x ...)", c_start, c));decode_error = true;}if (c < 0x80 || c > 0xbf) {print_unicode_error(vformat("Invalid UTF-8 continuation byte (%x ... %x ...)", c_start, c), true);decode_failed = true;skip = 0;} else {--skip;}}cstr_size++;ptrtmp++;}if (skip) {print_unicode_error(vformat("Missing %d UTF-8 continuation byte(s)", skip), true);decode_failed = true;}}if (str_size == 0) {clear();return OK; // empty string}resize(str_size + 1);char32_t *dst = ptrw();dst[str_size] = 0;int skip = 0;uint32_t unichar = 0;while (cstr_size) {uint8_t c = *p_utf8 >= 0 ? *p_utf8 : uint8_t(256 + *p_utf8);if (skip == 0) {if (p_skip_cr && c == '\r') {p_utf8++;continue;}/* Determine the number of characters in sequence */if ((c & 0x80) == 0) {*(dst++) = c;unichar = 0;skip = 0;} else if ((c & 0xe0) == 0xc0) {unichar = (0xff >> 3) & c;skip = 1;} else if ((c & 0xf0) == 0xe0) {unichar = (0xff >> 4) & c;skip = 2;} else if ((c & 0xf8) == 0xf0) {unichar = (0xff >> 5) & c;skip = 3;} else if ((c & 0xfc) == 0xf8) {unichar = (0xff >> 6) & c;skip = 4;} else if ((c & 0xfe) == 0xfc) {unichar = (0xff >> 7) & c;skip = 5;} else {*(dst++) = 0x20;unichar = 0;skip = 0;}} else {if (c < 0x80 || c > 0xbf) {*(dst++) = 0x20;skip = 0;} else {unichar = (unichar << 6) | (c & 0x3f);--skip;if (skip == 0) {if (unichar == 0) {print_unicode_error("NUL character", true);decode_failed = true;unichar = 0x20;}if ((unichar & 0xfffff800) == 0xd800) {print_unicode_error(vformat("Unpaired surrogate (%x)", unichar));decode_error = true;}if (unichar > 0x10ffff) {print_unicode_error(vformat("Invalid unicode codepoint (%x)", unichar));decode_error = true;}*(dst++) = unichar;}}}cstr_size--;p_utf8++;}if (skip) {*(dst++) = 0x20;}if (decode_failed) {return ERR_INVALID_DATA;} else if (decode_error) {return ERR_PARSE_ERROR;} else {return OK;}
}
其实已经读入到w里,但String::parse_utf8出错。
回头看了一下,原目标文件为GB2312编码。而Godot的FileAccess不支持别的编码。
那就加上,在不影响原有逻辑的基础上,小动一下:
ClassDB::bind_method(D_METHOD("get_as_text", "skip_cr", "encoding"), &FileAccess::get_as_text, DEFVAL(false), DEFVAL("utf-8"));String FileAccess::get_as_text(bool p_skip_cr, String encoding) const {uint64_t original_pos = get_position();const_cast<FileAccess *>(this)->seek(0);String text = get_as_utf8_string(p_skip_cr, encoding);const_cast<FileAccess *>(this)->seek(original_pos);return text;
}String FileAccess::get_as_utf8_string(bool p_skip_cr, String encoding) const {encoding = encoding.to_lower();Vector<uint8_t> sourcef;uint64_t len = get_length();sourcef.resize(len + 1);uint8_t *w = sourcef.ptrw();uint64_t r = get_buffer(w, len);ERR_FAIL_COND_V(r != len, String());w[len] = 0;if (encoding == "gb2312") {std::string str((const char *)w);String s(str);return s;}String s((const char *)w);s.parse_utf8((const char *)w, -1, p_skip_cr);return s;
}
GDScript中调用:
var xml : Xml = Xml.new("D:\\ExenObj\\Exe\\DrGraph\\Files\\Demo.sch")xml.Read("gb2312");class Xml:var RootNode: XmlNode = nullvar FileName: String = ""func _init(fileName: String) -> void:FileName = fileNamefunc Read(encoding: String = "utf-8") -> void:if FileAccess.file_exists(FileName): var fs = FileAccess.open(FileName, FileAccess.READ)var text = fs.get_as_text(false, encoding)var textStart = Helper.RegMatchAt(text, "<[^!?]")var pos = 0;if textStart.length() > 0:pos = text.find(textStart)if pos > 0:var header = text.substr(0, pos - 1) text = text.substr(pos)var from = 0while pos > 0:pos = header.find("<!", from)if pos == -1:breakfrom = pos + 1pos = header.find("\n", from)var str = header.substr(from, pos - from)var entityName = Helper.RegMatchAt(str, "Cbw.*?(?= )")var value = Helper.RegMatchAt(str, "(?<=').*?(?=')")if entityName.length() > 0 and value.length() > 0:print(entityName, " = ", value)RootNode = XmlNode.new("root");RootNode.xml = self;RootNode.from_string(text)fs.close()
如此,恢复正常。XML文本内容解析为图形效果
<CbwObjects><TLine name="Line967"><Points><Point x="258" y="868"/><Point x="606" y="1043"/></Points></TLine><TLine name="Line968"><Points><Point x="329" y="698"/><Point x="142" y="864"/></Points></TLine><TRectangle name="Rect147"><Points><Point x="433" y="804"/><Point x="712" y="917"/></Points></TRectangle><TRectangle name="Rect148"><Points><Point x="378" y="638"/><Point x="461" y="764"/></Points></TRectangle><TRectangle name="Rect149"><Points><Point x="105" y="651"/><Point x="201" y="826"/></Points></TRectangle><TRectangle name="Rect150"><Points><Point x="139" y="1011"/><Point x="341" y="866"/></Points></TRectangle><TRectangle name="Rect151"><Points><Point x="847" y="832"/><Point x="939" y="1043"/></Points></TRectangle><TRectangle name="Rect152"><Points><Point x="850" y="635"/><Point x="985" y="710"/></Points></TRectangle><TEllipse name="Ellipse74"><Points><Point x="551.451219512195" y="644.367464840815"/><Point x="788" y="762"/></Points></TEllipse><TLine name="Line799" pen="&CbwPen0;"><Points><Point x="230" y="46"/><Point x="417" y="284"/></Points></TLine>
</CbwObjects>
相关文章:

Godot 4 源码分析 - 文件读入编码处理
今天需要读入xml文件进行处理,结果读入一个带中文的文件时,出错了。当然程序还能运行,但编译器一直报错,而且XML解析也不正确 单步调试发现读入的内容出现乱码,具体逻辑: String FileAccess::get_as_text…...

Linux 中使用 verdaccio 搭建私有npm 服务器
安装 Node Linux中安装Node 安装verdaccio npm i -g verdaccio安装完成 输入verdaccio,出现下面信息代表安装成功,同时输入verdaccio后verdaccio已经处于运行状态,当然这种启动时暂时的,我们需要通过pm2让verdaccio服务常驻 ygiZ2zec61wsg…...
C++入门之stl六大组件--stack和queue源码深度剖析及模拟实现
目录 前言 一、stack的介绍和使用 1.stack的介绍 2.stack的使用 3.stack的模拟实现 二、queue的介绍和使用 1.queue的介绍 2.queue的使用 3.queue的模拟实现 三、priority_queue的介绍和使用 1.priority_queue的介绍 2.priority_queue的使用 3.priority_queue的模…...

MyCat配置文件schema.xml讲解
1.MyCat配置 1.1 schema标签 如果checkSQLschema配置的为false,那么执行DB01.TB_ORDER时就会报错,必须用use切换逻辑库以后才能进行查询。 sqlMaxLimit如果未指定limit进行查询,列表查询模式默认为100,最多只查询100条。因为用mycat后默认数…...

Grafana集成prometheus(2.Grafana安装)
查找镜像 docker search grafana下载指定版本 docker pull grafana/grafana:10.0.1启动容器脚本 docker run -d -p 3000:3000 --namegrafana grafana/grafana:10.0.1查看是否启动 docker ps防火墙开启 检查防火墙3000端口是否开启 默认用户及密码 admin/admin 登录 ht…...
代码随想录算法训练营第五十七天| 647. 回文子串 516.最长回文子序列
代码随想录算法训练营第五十七天| 647. 回文子串 516.最长回文子序列 一、力扣647. 回文子串 题目链接 思路:对于字符串cabac,其中a,b,c,aba,cabac,都是回文子串,如果当前的字串是回文字串,那么它的字串中也会有回文…...
django 优化方式
前言 对于网站和Web APP来说,相同的类型的产品,响应速度越好,那么用户量就越高。不可否认的是,响应速度是用户黏粘性最好的方式之一,但往往不知道如何下手解决,希望这篇文章可以给予你一些思路 对于网站和…...

IDEA中怎么使用git下载项目到本地,通过URL克隆项目(giteegithub)
点击 新建>来自版本控制的项目 点击后会弹出这样一个窗口 通过URL拉取项目代码 打开你要下载的项目仓库 克隆>复制 gitee github也是一样的 返回IDEA 将刚刚复制的URL粘贴进去选择合适的位置点击克隆 下载完成...

09. Docker Compose
目录 1、前言 2、安装Docker Compose 2.1、Docker Compose版本 2.2、下载安装 3、初试Docker Compose 3.1、传统方案部署应用 3.2、使用编排部署应用 3.3、其他命令 3.3.1、ps 3.3.2、images 3.3.3、depends_on 3.3.4、scale 4、小结 1、前言 随着应用架构的不段…...
如何在shell脚本将node_modules里的文件复制一份到public文件里
项目背景:由于公司网络不连接公网,所以在绘制地图大屏项目时,需要我们将边界线数据包也部署起来,来获取边界线数据 解决方案: 1.让后端写个接口或者找个地方将数据包放到服务器即可 2.将数据包放到vue项目的public文…...

监控Redis的关键指标
Redis 也是一个对外服务,所以 Google 的四个黄金指标同样适用于 Redis。 1、延迟 在软件工程架构中,之所以选择 Redis 作为技术堆栈的一员,大概率是想要得到更快的响应速度和更高的吞吐量,所以延迟数据对使用 Redis 的应用程序至…...
Openlayers和leaflet如何选用?
在地图处理这块,Openlayers和Leaflet是非常有名的两个开源的JS框架,他们各有各的优势和劣势,对于刚刚步入此行业的开发者而言怎么选择框架呢? 作者做过一定的探索,在这里将成果分享给大家。 Openlayers 简介 Openlayers是一个基于Javacript开发,免费、开源的前端地图开…...
跟我学C++中级篇——三五法则
一、三五法则 三五法则,这个叫着有点上头,说实话,这个三五法则,未来会不会变成三六或者四七法则,没人知道,反正现在是三五法则。在《cPrimer》第四版中,叫三法则,在第五版第13.1.4章…...

aardio:用 WebView 模仿 mdict 界面
aardio:用 WebView 模仿 mdict 界面 import win.ui; /*DSG{{*/ mainForm win.form(text"aardio2";right889;bottom467) mainForm.add( button{cls"button";text"go";left335;top22;right399;bottom41;z2}; button2{cls"button…...
linq中的操作符
LINQ(Language Integrated Query)是一种用于.NET平台的查询语言,用于查询和操作各种数据源,如集合、数据库和XML。LINQ提供了一组标准查询操作符,用于执行各种查询操作。 LINQ(Language Integrated Query&…...

数据结构【哈夫曼树】
哈夫曼树 哈夫曼树的概念哈夫曼树的构造构造算法的实现哈夫曼树应用哈夫曼编码哈夫曼编码的算法实现 哈夫曼树的概念 最优二叉树也称哈夫曼 (Huffman) 树,是指对于一组带有确定权值的叶子结点,构造的具有最小带权路径长度的二叉树。权值是指一个与特定结…...

SpringMVC基于SpringBoot的最基础框架搭建——包含数据库连接
SpringMVC基于SpringBoot的最基础框架搭建——包含数据库连接 背景目标依赖配置文件如下项目结构如下相关配置如下启动代码如下Controller如下启动成功接口调用成功 背景 工作做了一段时间,回忆起之前有个公司有线下笔试,要求考生做一个什么功能&#x…...
deepspeed zero3
zero3。它是纵向切分权重(intra-layer,每一层的权重切成n块)。但是这样会增加通讯时间。你可以根据自己的模型,估算下切分后的通讯量和通讯时间。其次,pipeline并行一般指横向切分权重(inter-layer…...

代驾小程序怎么做
代驾小程序是一款专门为用户提供代驾服务的手机应用程序。它具有以下功能: 1. 预约代驾:代驾小程序允许用户在需要代驾服务时提前进行预约。用户可以选择出发地点、目的地以及预计用车时间,系统会自动匹配最合适的代驾司机,并确保…...
探索 AJAX 技术:实现动态数据交互的前端利器
简介: AJAX(Asynchronous JavaScript and XML)技术在 Web 前端开发中扮演着重要的角色,它通过异步通信和动态内容更新,为用户带来更好的交互体验。本篇笔记将详细探索 AJAX 技术,并通过生动的代码演示来展示…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...

Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...