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 技术,并通过生动的代码演示来展示…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...

【免费数据】2005-2019年我国272个地级市的旅游竞争力多指标数据(33个指标)
旅游业是一个城市的重要产业构成。旅游竞争力是一个城市竞争力的重要构成部分。一个城市的旅游竞争力反映了其在旅游市场竞争中的比较优势。 今日我们分享的是2005-2019年我国272个地级市的旅游竞争力多指标数据!该数据集源自2025年4月发表于《地理学报》的论文成果…...