当前位置: 首页 > news >正文

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文件进行处理&#xff0c;结果读入一个带中文的文件时&#xff0c;出错了。当然程序还能运行&#xff0c;但编译器一直报错&#xff0c;而且XML解析也不正确 单步调试发现读入的内容出现乱码&#xff0c;具体逻辑&#xff1a; String FileAccess::get_as_text…...

Linux 中使用 verdaccio 搭建私有npm 服务器

安装 Node Linux中安装Node 安装verdaccio npm i -g verdaccio安装完成 输入verdaccio,出现下面信息代表安装成功&#xff0c;同时输入verdaccio后verdaccio已经处于运行状态&#xff0c;当然这种启动时暂时的&#xff0c;我们需要通过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&#xff0c;那么执行DB01.TB_ORDER时就会报错&#xff0c;必须用use切换逻辑库以后才能进行查询。 sqlMaxLimit如果未指定limit进行查询&#xff0c;列表查询模式默认为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. 回文子串 题目链接 思路&#xff1a;对于字符串cabac&#xff0c;其中a,b,c,aba,cabac&#xff0c;都是回文子串&#xff0c;如果当前的字串是回文字串&#xff0c;那么它的字串中也会有回文…...

django 优化方式

前言 对于网站和Web APP来说&#xff0c;相同的类型的产品&#xff0c;响应速度越好&#xff0c;那么用户量就越高。不可否认的是&#xff0c;响应速度是用户黏粘性最好的方式之一&#xff0c;但往往不知道如何下手解决&#xff0c;希望这篇文章可以给予你一些思路 对于网站和…...

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文件里

项目背景&#xff1a;由于公司网络不连接公网&#xff0c;所以在绘制地图大屏项目时&#xff0c;需要我们将边界线数据包也部署起来&#xff0c;来获取边界线数据 解决方案&#xff1a; 1.让后端写个接口或者找个地方将数据包放到服务器即可 2.将数据包放到vue项目的public文…...

监控Redis的关键指标

Redis 也是一个对外服务&#xff0c;所以 Google 的四个黄金指标同样适用于 Redis。 1、延迟 在软件工程架构中&#xff0c;之所以选择 Redis 作为技术堆栈的一员&#xff0c;大概率是想要得到更快的响应速度和更高的吞吐量&#xff0c;所以延迟数据对使用 Redis 的应用程序至…...

Openlayers和leaflet如何选用?

在地图处理这块,Openlayers和Leaflet是非常有名的两个开源的JS框架,他们各有各的优势和劣势,对于刚刚步入此行业的开发者而言怎么选择框架呢? 作者做过一定的探索,在这里将成果分享给大家。 Openlayers 简介 Openlayers是一个基于Javacript开发,免费、开源的前端地图开…...

跟我学C++中级篇——三五法则

一、三五法则 三五法则&#xff0c;这个叫着有点上头&#xff0c;说实话&#xff0c;这个三五法则&#xff0c;未来会不会变成三六或者四七法则&#xff0c;没人知道&#xff0c;反正现在是三五法则。在《cPrimer》第四版中&#xff0c;叫三法则&#xff0c;在第五版第13.1.4章…...

aardio:用 WebView 模仿 mdict 界面

aardio&#xff1a;用 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&#xff08;Language Integrated Query&#xff09;是一种用于.NET平台的查询语言&#xff0c;用于查询和操作各种数据源&#xff0c;如集合、数据库和XML。LINQ提供了一组标准查询操作符&#xff0c;用于执行各种查询操作。 LINQ&#xff08;Language Integrated Query&…...

数据结构【哈夫曼树】

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

SpringMVC基于SpringBoot的最基础框架搭建——包含数据库连接

SpringMVC基于SpringBoot的最基础框架搭建——包含数据库连接 背景目标依赖配置文件如下项目结构如下相关配置如下启动代码如下Controller如下启动成功接口调用成功 背景 工作做了一段时间&#xff0c;回忆起之前有个公司有线下笔试&#xff0c;要求考生做一个什么功能&#x…...

deepspeed zero3

zero3。它是纵向切分权重&#xff08;intra-layer&#xff0c;每一层的权重切成n块&#xff09;。但是这样会增加通讯时间。你可以根据自己的模型&#xff0c;估算下切分后的通讯量和通讯时间。其次&#xff0c;pipeline并行一般指横向切分权重&#xff08;inter-layer&#xf…...

代驾小程序怎么做

代驾小程序是一款专门为用户提供代驾服务的手机应用程序。它具有以下功能&#xff1a; 1. 预约代驾&#xff1a;代驾小程序允许用户在需要代驾服务时提前进行预约。用户可以选择出发地点、目的地以及预计用车时间&#xff0c;系统会自动匹配最合适的代驾司机&#xff0c;并确保…...

探索 AJAX 技术:实现动态数据交互的前端利器

简介&#xff1a; AJAX&#xff08;Asynchronous JavaScript and XML&#xff09;技术在 Web 前端开发中扮演着重要的角色&#xff0c;它通过异步通信和动态内容更新&#xff0c;为用户带来更好的交互体验。本篇笔记将详细探索 AJAX 技术&#xff0c;并通过生动的代码演示来展示…...

Stitches项目架构分析:RequireJS模块化设计与Grunt构建流程完全指南 [特殊字符]

Stitches项目架构分析&#xff1a;RequireJS模块化设计与Grunt构建流程完全指南 &#x1f680; 【免费下载链接】stitches HTML5 Sprite Sheet Generator 项目地址: https://gitcode.com/gh_mirrors/sti/stitches Stitches是一个基于HTML5的雪碧图生成器&#xff0c;它采…...

Win10系统清理避坑指南:你的BAT脚本真的安全吗?盘点那些不能乱删的文件

Win10系统清理避坑指南&#xff1a;BAT脚本安全操作手册每次看到那些号称"一键清理系统垃圾"的BAT脚本在技术论坛被疯狂转发&#xff0c;我的工程师朋友老张就会忍不住摇头。上周他刚帮一位设计师修复了崩溃的Photoshop——原因正是某个清理脚本删除了Adobe的临时工作…...

搞定这 5 个全栈电商项目,面试别再用 Todo-List 凑数了

找独立开发练手项目或者写简历项目时&#xff0c;最忌讳两件事&#xff1a;一是太简单&#xff08;纯前端 Mock 数据&#xff0c;点两下就没了&#xff09;&#xff0c;二是太假&#xff08;一上来就硬套微服务、消息队列、高并发&#xff0c;结果自己根本Hold不住&#xff09;…...

电容损坏深度诊断,从外观到 ESR精准区分容衰与漏电

在 PCB 故障中&#xff0c;电容损坏占比超 40%&#xff0c;是当之无愧的 “头号杀手”。很多工程师仅靠 “鼓包漏液” 判断电容好坏&#xff0c;殊不知80% 的电容损坏是隐性的—— 外观平整但容值衰减、ESR 升高、轻微漏电&#xff0c;导致供电不稳、系统重启、噪声增大&#x…...

基于Arduino的智能蓝调节拍器:DIY音乐练习伴侣

1. 项目概述&#xff1a;一个能“演奏”蓝调的低成本节拍器玩乐器的人&#xff0c;对节拍器这东西又爱又恨。它像一位严厉的监工&#xff0c;用单调的“嘀嗒”声强迫你跟上节奏。但你想过没有&#xff0c;这个监工其实可以很有趣&#xff1f;几年前&#xff0c;我在练习蓝调吉他…...

CANoe诊断测试没CDD文件怎么办?手把手教你用Fault Memory窗口和CAPL脚本读取解析DTC故障码

CANoe诊断测试无CDD文件的实战解决方案&#xff1a;从Fault Memory到CAPL脚本全解析当CDD文件缺失或定义不清晰时&#xff0c;诊断测试工程师常常陷入困境。本文将深入探讨如何利用Fault Memory窗口的基础功能&#xff0c;并通过CAPL脚本实现更灵活、更强大的故障码读取与解析方…...

百度文心一言开发者如何通过Taotoken低成本接入多模型API

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 百度文心一言开发者如何通过Taotoken低成本接入多模型API 对于已经熟悉并正在使用百度文心一言等国产大模型API的开发者而言&#…...

收藏干货|2026 版企业 AI 落地实操指南,程序员小白入门避坑必备

如今人工智能早已脱离概念炒作阶段&#xff0c;全面扎根企业实际业务场景&#xff0c;成为技术从业者与企业管理者无法回避的发展课题。各行各业都加速布局AI赛道&#xff0c;行业心态也从初期观望试探&#xff0c;彻底转变为实打实的落地攻坚。 不少企业高层主动牵头统筹AI规划…...

Autodesk Fusion 360在Linux上的技术实现与性能优化深度解析

Autodesk Fusion 360在Linux上的技术实现与性能优化深度解析 【免费下载链接】Autodesk-Fusion-360-for-Linux This is a project, where I give you a way to use Autodesk Fusion 360 on Linux! 项目地址: https://gitcode.com/gh_mirrors/au/Autodesk-Fusion-360-for-Linu…...

3分钟上手:NBTExplorer终极指南 - 可视化编辑Minecraft游戏数据的免费神器

3分钟上手&#xff1a;NBTExplorer终极指南 - 可视化编辑Minecraft游戏数据的免费神器 【免费下载链接】NBTExplorer A graphical NBT editor for all Minecraft NBT data sources 项目地址: https://gitcode.com/gh_mirrors/nb/NBTExplorer 你是否曾经想要修改Minecraf…...