Unity3d C#实现文件(json、txt、xml等)加密、解密和加载(信息脱敏)功能实现(含源码工程)
前言
在Unity3d工程中经常有需要将一些文件放到本地项目中,诸如json、txt、csv和xml等文件需要放到StreamingAssets和Resources文件夹目录下,在程序发布后这些文件基本是对用户可见的状态,造成信息泄露,甚至有不法分子会利用这些信息进行一定的破坏行为。在这种背景下是很有必要将本地的一些文件进行加密处理再存储,然后加载后进行解密,这就能规避本地文件带来的风险。而本文就是围绕这个功能实现的一个插件,能快速的对文件进行加密和解密修改。只需要进行简单的配置,然后选中文件进行加密,即可实现该功能。 该项目的Unity3d版本为2020.3.28f1c1 Personal,注意如果版本差异太大可能会无法正确打开使用。
效果
加密配置:

加密前后对比:

自定义加密:

批量直接加密:

加密至StreamingAssets:

自定义解密:

批量解密:

实现
加密的核心功能实现采用的是加密转换的基本操作,根据加密的配置Key和Code进行加密操作,这些配置在保存/修改时会进行修改存储。而Unity3d工程中的新增菜单和窗口采用Unity编辑器拓展MenuItem和EditorWindow来实现。
配置实现
在顶部的菜单栏中新建一个菜单选项“Tools > 加密配置窗口”:
[MenuItem("Tools/加密配置窗口")]
public static void ShowRegisterWindow()
{EncoderConfigWind wind = (EncoderConfigWind)EditorWindow.GetWindow(typeof(EncoderConfigWind));
}
点击后打开编辑器窗口,这个窗口EncoderConfigWind是继承了Unity的编辑器窗口(EditorWindow)。
然后编写当渲染UI的时候调用OnGUI函数,绘制出配置窗口的明细:
private void OnGUI(){GUILayout.BeginVertical(new GUILayoutOption[0]);GUILayout.Space(10f);GUILayout.Label("加密文件配置", new GUILayoutOption[0]);GUILayout.Space(10f);GUILayout.Label("加密KEY", new GUILayoutOption[0]);this.TempKey = EditorGUILayout.TextArea(this.TempKey, new GUILayoutOption[] { GUILayout.MinHeight(50f) });GUILayout.Space(10f);GUILayout.Label("加密Code", new GUILayoutOption[0]);this.LegalIVCode = EditorGUILayout.TextArea(this.LegalIVCode, new GUILayoutOption[] { GUILayout.MinHeight(50f) });GUILayout.Space(10f);GUILayout.Label("加密文件后缀", new GUILayoutOption[0]);this.EncodeSuffix = EditorGUILayout.TextArea(this.EncodeSuffix, new GUILayoutOption[] { GUILayout.MinHeight(20f) });GUILayout.Space(10f);GUILayout.Label("解密文件后缀", new GUILayoutOption[0]);this.DecodeSuffix = EditorGUILayout.TextArea(this.DecodeSuffix, new GUILayoutOption[] { GUILayout.MinHeight(20f) });GUILayout.Space(10f);if (GUILayout.Button("保存配置", new GUILayoutOption[0])){this.SaveConfigs(this.TempKey, this.LegalIVCode, this.EncodeSuffix, this.DecodeSuffix);}GUILayout.Space(10f);if (GUILayout.Button("获取帮助", new GUILayoutOption[0])){Process.Start("https://blog.csdn.net/qq_33789001");}GUILayout.EndVertical();}
如上的代码能绘制出下面的窗口:
其主要的作用就是在打开配置窗口后绘制出窗体,在窗体中提供Key、Code、默认加密/解密文件的后缀等输入框,点击保存配置按钮后会将这些输入信息进行保存,通过File.WriteAllBytes()函数写入到Resources下的配置文件中去,示例代码如下:
File.WriteAllBytes(path+ "/Key.txt", keybytes);
加密实现
加密的实现是通过选择Assets窗口中的文件来进行加密,所有菜单的选项都采用了[MenuItem(“Assets/***”)]的形式进行。为了满足大部分的应用场景提供了多种操作方式,单一自定义加密、批量直接加密和批量的加密到StreamAssets和Resources的方式等,所以写了一个枚举进行操作:
public enum EncodeType
{ direct = 1,custom = 2,steamingassets = 3,resources = 4,custompath = 5
}
在Assets窗口中新建了如下的菜单选项,并通过加密EncodeType 的枚举值不同的方式进行区分:
[MenuItem("Assets/加密文件/直接加密(批量)")]private static void DoEncodeFileDir(){DoEncodeFiles(EncodeType.direct);}[MenuItem("Assets/加密文件/选路径加密(批量)")]private static void DoEncodeFileSelPath(){DoEncodeFiles(EncodeType.custompath);}[MenuItem("Assets/加密文件/放入StreamAssets(批量)")]private static void DoEncodeFileSa(){DoEncodeFiles(EncodeType.steamingassets);}[MenuItem("Assets/加密文件/放入Resources(批量)")]private static void DoEncodeFileRes(){DoEncodeFiles(EncodeType.resources);}[MenuItem("Assets/加密文件/自定义加密(单一)")]private static void DoEncodeFileCustom(){DoEncodeFiles(EncodeType.custom);}
点击加密选项后,根据选项和选择的文件进行加密处理,样例代码如下:
string[] strs = Selection.assetGUIDs;string path = AssetDatabase.GUIDToAssetPath(strs[0]);string suffix = (Resources.Load("EncodeFile/DeSuffix") as TextAsset).text;string buildPath = EditorUtility.SaveFilePanel("请选择解析保存的路径", GetPrePath(path), GetFileName(path), suffix);string spath = buildPath;if (!string.IsNullOrEmpty(path)){string text = File.ReadAllText(path);string decode = Decrypt(text);//Debug.Log(spath);File.WriteAllText(spath, decode);AssetDatabase.Refresh();//刷新}elseDebug.LogError("请选择正确的文件进行解析!");
处理的流程是提取选中的文件路径,并读取加密的配置选项,再根据用户的自定义选择保存的目录、文件名称和文件后缀等加密后存储信息,将需要加密的文件进行读取内容,进行加密后,保存到对应的加密后存储位置中去。
解密实现
解密顾名思义就是加密的逆操作,其适用场景是对加密过的文件进行解密后,对文件进行浏览查看或者修改更新操作。对解密文件的操作类似于加密的操作窗口,都是在Assets窗口进行,以[MenuItem(“Assets/***”)]的形式进行,不过细分了入口的菜单:
[MenuItem("Assets/解密文件/直接解析(批量)")]
[MenuItem("Assets/解密文件/自定解析(单一)")]
这里就两种方式自定义解析(仅支持单一文件)和批量直接解析的方式。解析的样例代码如下:
string[] strs = Selection.assetGUIDs;string path = AssetDatabase.GUIDToAssetPath(strs[0]);string suffix = (Resources.Load("EncodeFile/DeSuffix") as TextAsset).text;string buildPath = EditorUtility.SaveFilePanel("请选择解析保存的路径", GetPrePath(path), GetFileName(path), suffix);string spath = buildPath;if (!string.IsNullOrEmpty(path)){string text = File.ReadAllText(path);string decode = Decrypt(text);//Debug.Log(spath);File.WriteAllText(spath, decode);AssetDatabase.Refresh();//刷新}elseDebug.LogError("请选择正确的文件进行解析!");
处理的流程和加密的流程类似,提取选中的文件路径,并读取加密的配置选项,再根据用户的自定义选择保存的目录、文件名称和文件后缀等解密后存储信息,将需要解密的文件进行读取内容,进行解密后,保存到对应的解密后存储位置中去。
加载解密测试
这个才是采用了两种方式进行,是读取Resources的方式和读取StreamingAssetsPath的方式。分别读取CSV、TXT和JSON、XML文件。测试过程尽量简单化,就是将文件读取、解密后,将解密的内容显示到Text上即可,其中需要注意的是如果文件存储到Resources下的话,文件最好是.txt、.json,否则可能读取不到内容。UI和测试脚本的配置如下:

读取Resources目录下的文件代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class LoadResourcesFileTest : MonoBehaviour
{[Header("文件名")]public string FileName = "";[Header("显示内容的Text")]public Text showText;private void Awake(){Debug.LogWarning("Resources文件夹下的文件最好是.txt、.json,否则可能读取不到");if (!showText)showText = transform.GetComponent<Text>();RequestFile();}void RequestFile(){TextAsset ta = Resources.Load(FileName) as TextAsset;string EnCodeStr ="";if (ta)EnCodeStr = ta.text;Debug.Log("解析前:" + EnCodeStr);string orgString = Decoder.GetDecodeString(EnCodeStr);if (showText)showText.text = orgString;Debug.Log("解析后:" + orgString);}
}
读取StreamingAssetsPath的代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;public class LoadSAFileTest : MonoBehaviour
{[Header("文件名")]public string FileName = "";[Header("显示内容的Text")]public Text showText;private void Awake(){if (!showText)showText = transform.GetComponent<Text>();string filePath = Application.streamingAssetsPath +"/"+ FileName;StartCoroutine(RequestFile(filePath));}IEnumerator RequestFile(string uri){using (UnityWebRequest webRequest = UnityWebRequest.Get(uri)){// Request and wait for the desired page.yield return webRequest.SendWebRequest();if (webRequest.result == UnityWebRequest.Result.Success){Debug.Log("解析前:"+webRequest.downloadHandler.text);string orgString = Decoder.GetDecodeString(webRequest.downloadHandler.text);if (showText)showText.text = orgString;Debug.Log("解析后:" + orgString);}else{Debug.LogError("加载解密文件异常:" + webRequest.error);}}}
}
这里的xml读取效果如下:

源码工程
https://download.csdn.net/download/qq_33789001/88915590
无法下载需要稍等,可能审核未通过。
工程说明
工程包含了上述所有的功能和演示场景,包含了所有的编辑器扩展代码和测试功能源码,可以自由修改自定义功能,也可以通过 “Tools” > “加密配置窗口”进行简单的加密配置后快速使用加密功能。
\Assets\TestFiles为加密测试的原文件;
\Assets\Editor为编辑器拓展的源代码;
\Assets\Resources 为测试加载加密文件并解析的文件和配置存储文件;\Assets\Scenes包含测试加载加密后的CSV、TXT、JSON、XML文件的demo场景;
\Assets\Scripts 测试和解密代码;
\Assets\StreamingAssets加密后的测试文件。
相关文章:
Unity3d C#实现文件(json、txt、xml等)加密、解密和加载(信息脱敏)功能实现(含源码工程)
前言 在Unity3d工程中经常有需要将一些文件放到本地项目中,诸如json、txt、csv和xml等文件需要放到StreamingAssets和Resources文件夹目录下,在程序发布后这些文件基本是对用户可见的状态,造成信息泄露,甚至有不法分子会利用这些…...
解释一下分库分表的概念和优缺点。如何设计一个高性能的数据库架构?
解释一下分库分表的概念和优缺点。 分库分表是数据库架构优化的常见手段,主要用于解决单一数据库或表在数据量增大、访问频率提高时面临的性能瓶颈和扩展性问题。 概念: 分库(Sharding-Database): 将原本存储在一个…...
功能强大使用简单的截图/贴图工具,PixPin
一、下载链接 PixPin 截图/贴图/长截图/文字识别/标注 | PixPin 截图/贴图/长截图/文字识别/标注 (pixpinapp.com) 二、功能 截图/贴图/长截图/文字识别/标注 三、安装教程 根据提示安装即可: 四、快捷键 1.软件自带快捷键(右击PixPin查看 )…...
机器学习周报第32周
目录 摘要Abstract一、文献阅读1.论文标题2.论文摘要3.论文背景4.论文方案4.1 多视角自注意力网络4.2 距离感知4.3 方向信息4.4 短语模式 二、self-attention 摘要 本周学习了多视角自注意力网络,在统一的框架下联合学习输入句子的不同语言学方面。具体来说&#x…...
人工智能|机器学习——DBSCAN聚类算法(密度聚类)
1.算法简介 DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种基于密度的聚类算法,簇集的划定完全由样本的聚集程度决定。聚集程度不足以构成簇落的那些样本视为噪声点,因此DBSCAN聚类的方式也可以用于异常点的检测。 2.算法原…...
Excel F4键的作用
目录 一. 单元格相对/绝对引用转换二. 重复上一步操作 一. 单元格相对/绝对引用转换 ⏹ 使用F4键 如下图所示,B1单元格引用了A1单元格的内容。此时是使用相对引用,可以按下键盘上的F4键进行相对引用和绝对引用的转换。 二. 重复上一步操作 ⏹添加或删除…...
前端实现跨域的六种解决方法
本专栏是汇集了一些HTML常常被遗忘的知识,这里算是温故而知新,往往这些零碎的知识点,在你开发中能起到炸惊效果。我们每个人都没有过目不忘,过久不忘的本事,就让这一点点知识慢慢渗透你的脑海。 本专栏的风格是力求简洁…...
macOS上实现「灵动岛」效果
自从Apple iPhone推出了「灵动岛」功能后,用户们就被其优雅的设计和强大的功能所吸引。然而,作为macOS用户,我们一直在等待这一功能能够在我们的设备上实现。现在,随着新的应用程序的推出,我们终于可以在我们的Mac上体…...
幕译--本地字幕生成与翻译--Whisper客户端
幕译–本地字幕生成与翻译 本地离线的字幕生成与翻译,支持GPU加速。可免费试用,无次数限制 基于Whisper,希望做最好的Whisper客户端 功能介绍 本地离线,不用担心隐私问题支持GPU加速支持多种模型支持(中文、英语、日…...
链表基础知识详解
链表基础知识详解 一、链表是什么?1.链表的定义2.链表的组成3.链表的优缺点4.链表的特点 二、链表的基本操作1.链表的建立2.链表的删除3.链表的查找4.链表函数 一、链表是什么? 1.链表的定义 链表是一种物理存储单元上非连续、非顺序的存储结构…...
GPT-prompt大全
ChatGPT目前最强大的的工具是ChatGPT Plus,不仅训练数据更新到了2023年,而且还可以优先访问新功能。对于程序员来说,升级到ChatGPT Plus,将会带来更多的便利和效率提升。 根据 升级ChatGPT Plus保姆级教程,1分钟就可以…...
的发射点2
☞ 通用计算机启动过程 1️⃣一个基础固件:BIOS 一个基础固件:BIOS→基本IO系统,它提供以下功能: 上电后自检功能 Power-On Self-Test,即POST:上电后,识别硬件配置并对其进行自检,…...
深入揭秘Lucene:全面解析其原理与应用场景(一)
本系列文章简介: 本系列文章将深入揭秘Lucene,全面解析其原理与应用场景。我们将从Lucene的基本概念和核心组件开始,逐步介绍Lucene的索引原理、搜索算法以及性能优化策略。通过阅读本文,读者将会对Lucene的工作原理有更深入的了解…...
拿捏算法的复杂度
目录 前言 一:算法的时间复杂度 1.定义 2.简单的算法可以数循环的次数,其余需要经过计算得出表达式 3.记法:大O的渐近表示法 表示规则:对得出的时间复杂度的函数表达式,只关注最高阶,其余项和最高阶…...
C语言实战—猜数字游戏(涉及循环和少部分函数内容)
对于前面一些内容的总结 不妨跟着一起试试吧 折半查找算法(二分查找) 比如我买了一双鞋,你好奇问我多少钱,我说不超过300元。你还是好奇,你想知道到底多少,我就让 你猜,你会怎么猜?…...
#define MODIFY_REG(REG, CLEARMASK, SETMASK)
#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK))) 这个宏 MODIFY_REG 是在嵌入式编程中,它用于修改一个寄存器的特定位,而不影响其他位。这个宏接受三个参数ÿ…...
使用 Docker 部署 Stirling-PDF 多功能 PDF 工具
1)Stirling-PDF 介绍 大家应该都有过这样的经历,面对一堆 PDF 文档,或者需要合并几个 PDF,或者需要将一份 PDF 文件拆分,又或者需要调整 PDF 中的页面顺序,找到的线上工具 要么广告满天飞,要么 …...
springcloud第3季 项目工程搭建与需求说明1
一 需求说明 1.1 实现结构图 订单接口调用支付接口 二 工程搭建 2.1 搭建工程步骤...
外包干了3个月,技术退步明显。。。。
先说一下自己的情况,本科生,2019年我通过校招踏入了南京一家软件公司,开始了我的职业生涯。那时的我,满怀热血和憧憬,期待着在这个行业中闯出一片天地。然而,随着时间的推移,我发现自己逐渐陷入…...
Redis特性与应用场景
Redis是一个在内存中存储数据的中间件,用于作为数据库,用于作为数据缓存,在分布式系统中能够发挥重要作用。 Redis的特性 1.In-memory data structures: MySQL使用表的方式存储数据,这意味着数据通常存储在硬盘上,并且…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
认识CMake并使用CMake构建自己的第一个项目
1.CMake的作用和优势 跨平台支持:CMake支持多种操作系统和编译器,使用同一份构建配置可以在不同的环境中使用 简化配置:通过CMakeLists.txt文件,用户可以定义项目结构、依赖项、编译选项等,无需手动编写复杂的构建脚本…...
