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>

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/82896.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【肌电图信号分析】通道肌电图并查找收缩周期的数量、振幅、最大值和持续时间(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

React源码解析18(2)------ FilberNode,FilberRootNode结构关系

摘要 在上一篇&#xff0c;我们实现了通过JSX转换为ReactElement的方法&#xff0c;也看到了转换后React元素的结构。但是这个React元素&#xff0c;并不能很清楚的表达组件之间的关系&#xff0c;以及属性的处理。 所以在React内部&#xff0c;会将所有的React元素转换为Fil…

【Linux】详解进程状态之僵尸进程——孤儿进程

目录 &#x1f31e;专栏导读 &#x1f31b;什么是进程 ⭐什么是PCB&#xff1f; &#x1f31b;查看进程 &#x1f31b;如何通过系统调用查看进程PID &#x1f31b;fork &#x1f31e;认识进程状态 &#x1f31b;查看进程状态 &#x1f31b;R状态 ⭐例如&#xff1a…

VMware Workstation及CentOS-7虚机安装

创建新的虚机&#xff1a; 选择安装软件&#xff08;这里选的是桌面版&#xff0c;也可以根据实际情况进行选择&#xff09; 等待检查软件依赖关系 选择安装位置&#xff0c;自主配置分区 ​​​​​​​ 创建一个普通用户 安装完成后重启 点击完成配置&#xff0c;进入登陆界面…

怎么进行流程图制作?用这个工具制作很方便

怎么进行流程图制作&#xff1f;流程图是一种非常有用的工具&#xff0c;可以帮助我们更好地理解和展示各种复杂的业务流程和工作流程。它可以将复杂的过程简化为易于理解的图形和文本&#xff0c;使得人们更容易理解和跟踪整个流程。因此&#xff0c;制作流程图是在日常工作中…

拆解与重构:慕云游首页组件化设计

目录 前言1 项目准备1.1 创建项目目录1.2 搭建项目开发环境 2 项目组件化2.1 在当前环境启动原有项目2.2 顶部组件2.3 幻灯片组件2.3.1 功能实现2.3.2 加载中组件2.3.3 结构和样式2.3.4 使用Ajax获取数据 2.4 机酒自由行组件2.5 拆分余下的css文件 3 项目完善4 源码 前言 在现代…

如何使Python Docker镜像安全、快速、小巧

一、说明 在微服务领域&#xff0c;拥有安全、高效和紧凑的 Docker 映像对于成功部署至关重要。本博客将探讨有助于构建此类映像的关键因素&#xff0c;包括不以 root 用户身份运行映像的重要性、在构建映像时更新和升级包、在编写 Dockerfile 指令时考虑 Docker 的层架构&…

岩土工程仪器多通道振弦传感器信号转换器应用于桥梁安全监测

岩土工程仪器多通道振弦传感器信号转换器应用于桥梁安全监测 桥梁作为交通运输的重要节点&#xff0c;其安全性一直备受关注。不同于其他建筑物&#xff0c;桥梁所处的环境复杂多变&#xff0c;同时&#xff0c;其所需承受的负荷也相对较大&#xff0c;这就需要对桥梁的安全进…

Windows 安装 pandoc 将 jupyter 导出 pdf 文件

Windows 安装 pandoc 将 jupyter 导出 pdf 文件 1. 下载 pandoc 安装文件2. 安装 pandoc3. 安装 nbconvert4. 使用 pandoc 1. 下载 pandoc 安装文件 访问 https://github.com/jgm/pandoc/releases&#xff0c;下载最新版安装文件&#xff0c;例如&#xff0c;3.1.6.1 版&#…

常见分布式ID解决方案总结:数据库、算法、开源组件

常见分布式ID解决方案总结 分布式ID分布式ID方案之数据库数据库主键自增数据库号段模式Redis自增MongoDB 分布式ID方案之算法UUIDSnowflake(雪花算法) 雪花算法的使用IdWorker工具类配置分布式ID生成器 分布式ID方案之开源组件uid- generator(百度)Tinyid&#xff08;滴滴&…

基于Java的体育网站的设计与实现(论文+源码)_kaic

基于Java的体育网站的设计与实现 摘 要&#xff1a;在网络应用的迅速发展与科技的不断进步的现代环境下&#xff0c;人们生活节奏越来越快&#xff0c;娱乐方式也多种多样&#xff0c;各种软件应用&#xff0c;各种娱乐&#xff0c;购物网站已经成为必不可少的伴随品&#xff…

《24海南大学835软件工程考研经验贴》

1.经验之谈 首先&#xff0c;我是一个二战的考生&#xff0c;一战给我带来的经验有几点。第一&#xff0c;数学、专业课这两门越早复习越好&#xff0c;越拖到后面你就会发现来不及了&#xff0c;这学不完&#xff0c;那学不完的。第二、我认为是比较关键的一点&#xff0c;一定…

Idea创建maven管理的web项目

如果你想在项目中添加一个传统的 src 目录来存放源代码&#xff0c;可以按照以下步骤操作&#xff1a; 1. 在项目视图中&#xff0c;右键单击项目名称&#xff0c;选择 “New” -> “Directory”。 2. 在弹出的对话框中&#xff0c;输入目录名称为 “src”&#xff0c;然后…

使用ffmpeg将m4a及wav等文件转换为MP3格式

要使用ffmpeg将m4a及wav等文件转换为MP3格式&#xff0c;您可以按照以下步骤进行操作&#xff1a; 安装 ffmpeg 确保您已经安装了ffmpeg软件。如果没有安装&#xff0c;请访问ffmpeg的官方网站https://ffmpeg.org/ 并按照说明进行安装。 Win10 / Win11 可以通过 winget 命令…

Vue自定义指令使用

本篇文章讲述使用Vue自定义指令&#xff0c;并在项目中完成相应功能。 在平常Vue脚手架项目中&#xff0c;使用到 自定义指令较少&#xff0c;一般都是使用的自带指令&#xff0c;比如 v-show 、v-if 、 v-for 、 v-bind 之类的。这些已经能够满足大多数项目使用。更多的可能也…

蚁剑antSword-maste下载-安装-使用-一句话木马

下载 https://github.com/AntSwordProject/antSword 一句话木马 hack.php脚本 <?php eval($_POST[attack]);?> 安装 1、安装完成后启动 2、初始化&#xff0c;选择有源码的目录 3、连接

SpringMVC的架构有什么优势?——视图与模型(二)

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…

c语言每日一练(2)

前言&#xff1a; 每日一练系列&#xff0c;每一期都包含5道选择题&#xff0c;2道编程题&#xff0c;博主会尽可能详细地进行讲解&#xff0c;令初学者也能听的清晰。每日一练系列会持续更新&#xff0c;暑假时三天之内必有一更&#xff0c;到了开学之后&#xff0c;将看学业情…

leetcode 63. 不同路径 II

2023.8.9 这题是不同路径I的升级版&#xff0c;在路径上增加了障碍物&#xff0c;有障碍物的地方无法通过。 我的思路依然还是使用动态规划&#xff0c;dp[i][j]的含义依然是到&#xff08;i&#xff0c;j&#xff09;这个位置的路径个数。只需要在dp数组中将有障碍物的地方赋为…

js案例:1.简单计算器

目录 一.效果图 二.实现思路 整体思路 ​ 1.关键是dom操作 ​ 2.设置点击事件 3.数据类型的隐式转换和赋值 三.完整代码 一.效果图 二.实现思路 整体思路 1.关键是dom操作 通过 document.getElementById(id) 获取html中的dom元素 每一个html标签都是一个对象&…