WinUI3-读写.json文件

原文链接

WinUI3-读写.json文件 – WhiteNight's Site

2023年5月24日

However,我自己也是刚接触Javascript。这里也只是分享其中一种,经过我自己测试后可行的方法。

应用场景

什么时候用到.json

以我在写一个Redis的可视化工具时碰到的问题为例子。

用户打开应用,在设置界面设置了自己Redis服务器的IP和密码。但是应用不可能一直挂在后台,迟早会被用户关闭。

那么问题来了,用户再次打开应用的时候,上一次设置的IP和密码会自动保存吗?当然不会,程序加载的是你预设好的代码,如果你在程序里预设IP为”127.0.0.1″,那么用户无论重启多少次应用,默认的IP还是”127.0.0.1″。

当然,让用户每次启动应用后都自行设置也没问题。但为了用户的良好体验,我就在想“怎么才能把用户上次输入的数据保存到本地”呢?

写入txt?然后每次都读取?写入是很方便,但是读取就很麻烦。每次读取txt都要去匹配然后分割字符串,代码实现起来实在是比较麻烦。

刚好最近在研究怎么爬取”深圳技术大学教务系统“的课表,初次接触到了Javascript和.json格式。发现.json文件过于好用了,C#自带处理Json格式方法,原本要自己写分割字符串的代码,现在人直接给你封装好直接用就完事了。

一个.json文件

WinUI3暂不“支持”

为什么说不支持捏?你打开你的项目,右键选择添加-新建项。搜索.json,发现只有TypeScript和Javascript的配置json。

但并不意味着WinUI3的程序无法读取.json,只是vs里的winui3项目不给你添加,仅此而已。

直接去文件夹下自己新建一个.json文件;或者用vs打开需要添加.json文件的文件夹(不要选择.sln进入项目),再选择添加-新建项,在web那一栏找到.json,选择添加,完事。

那么.json文件的格式到底是啥样的,我以我的InitSetting.json为例

[
  {
    "databaseIP": "127.0.0.1",
    "databasePassword": null
  }
]

该json文件指定了数据库的地址和密码。

.json存放的路径

非打包程序不要存放到C盘的AppData文件夹下

既然要读取.json文件,那得有它的路径吧,得有它的文件名吧?我个人建议把用户配置的.json存放到你程序的同个路径下。比如新建一个文件夹AppData,然后往里面扔.json。

个人建议不要(表示友好的词语,已自动屏蔽)存到C盘的AppData文件夹里,特别是选择打包(Packaged)方式发布的程序。先不说因为一堆应用都往AppData里面扔东西,我每次清这文件夹都要清理半天。

另一个最主要的原因是:选择未打包(Unpackaged)运行的程序,是无法通过

private static string ApplicationData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);

等一系列方法获取到应用的环境文件夹(即C盘的AppData目录)的。这也是为什么你选择未打包运行程序的时候,你用这些方法会报错。因为应用在没打包的情况下压根不知道这个方法指向的是哪个文件夹。

读取.json

先读文件,再分字符串

以SimpleString为例,建议先参考该仓库的代码再来看接下来的内容。

在应用目录下有一个AppData文件夹,该文件夹中有一个InitSetting.json文件。该文件中存放着我想要在应用关闭后仍然保存的数据–数据库地址和数据库密码。

那么打开InitSetting.json的代码如下

  private async void InitDatabase()
        {
            string fileName = "AppData/InitSettings.json";
            string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,fileName);

            string databaseIP = null;
            string databasePassword = null;
            if (File.Exists(filePath))
            {
             string json = await File.ReadAllTextAsync(filePath);
            }

        }

这段代码不难理解,单纯就是打开该json文件,并将文件里的所有内容都写入一个字符串中的操作。

接下来是拆分字符串。先来看看json文件的内容

[
  {
    "databaseIP": "127.0.0.1",
    "databasePassword": null
  }
]

对于json来说,方括号 “[ ]”就相当于一个起始标记,大括号”{ }”相当于一个数组,大括号里面是它的对象–即可以简单把它理解为一个C++的对象数组。

那么接下来我们就要用到”JsonArray”。将字符串划分为Json类型的数组。然后遍历数组去判断对应的值即可。代码如下

tring json = await File.ReadAllTextAsync(filePath);
                JsonArray data = (JsonArray)JsonArray.Parse(json);
                foreach (var item in data)
                {
                    if(item["databaseIP"] != null)
                        databaseIP = item["databaseIP"].ToString();
                    if (item["databasePassword"] != null)
                        databasePassword = item["databasePassword"].ToString();
                }

                Settings.databaseInfo.databaseIP = databaseIP;
                Settings.databaseInfo.databasePassword = databasePassword;

上面这种方法适用于:“寻找特定键名”的情况。

还有一种方法,适用“不需要考虑键名”的情况。该方法是我在“将json文件中的键值对写入Redis”中试出来的。这种方法用起来也会更加直观。

当然,这代码有点长,而且我没写注释。建议复制到vs里面看。代码如下

    private async void JsonToRedis(object sender, RoutedEventArgs e)
        {
            string fileName = "AppData/RedisKey.json";
            string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
           try
           { 
                configurationOptions = new ConfigurationOptions
                {
                    EndPoints = { $"{Settings.databaseInfo.databaseIP}" },
                    Password = $"{Settings.databaseInfo.databasePassword}"
                };
                connectionMultiplexer = ConnectionMultiplexer.Connect(configurationOptions);
                database = connectionMultiplexer.GetDatabase();
            }
            catch
            {
                ErrorMessage_CantFindRedis();
            }

            try
            {
                string keyName = null;
                string keyValue = null;
                long TTL = (long)TTLSetter.Value;
                if (File.Exists(filePath))
                {
                    string json = await File.ReadAllTextAsync(filePath);
                    JsonArray data = (JsonArray)JsonArray.Parse(json);
                    TimeSpan timeSpan;
                    if (TTLType == "s")
                    {
                        timeSpan = TimeSpan.FromSeconds((long)TTLSetter.Value);
                    }
                    else if (TTLType == "ms")
                    {
                        timeSpan = TimeSpan.FromMilliseconds((long)TTLSetter.Value);
                    }
                    else
                    {
                        timeSpan = TimeSpan.Zero;
                    }
                    foreach (var item in data)
                    {
                        var props = item.AsObject();
                        foreach (var prop in props)
                        {
                            keyName = prop.Key;
                            keyValue = prop.Value.ToString();
                            if (TTL != 0)
                            {
                                database.StringSet(keyName, keyValue, timeSpan);
                            }
                            else
                            {
                                database.StringSet(keyName, keyValue);
                            }
                        }

                    }
                }
            }
            catch
            {
                ErrorMessage_UnsupportedMethod();
            }
        }

大致解释几点:

  • try-catch是用来捕获异常的。防止应用在碰到异常时直接闪退。可以在catch的部分加上触发弹窗的代码表示程序运行时异常。
  • Timespan类是用来处理时间的。主要是因为Redis中的键值对有设置TTL(Time to live)的操作。我想让用户能看到“选择设置61秒的TTL,在前端展示给用户的是设置了一分钟1秒的TTL”。所以用Timespan处理会方便许多。
  • 和第一种方法不一样的是,第二种方法不需要考虑键名和键值的具体含义。所以foreach里面再套一个循环。去获取JsonArray中的每一个对象的键名和键值。

写者注

这部分真的建议自己写一遍。不同的程序json文件的含义和内容也大概率不一样。如果不能理解,可以自己照着Github上的代码改一下试试,多设几个断点调试调试就懂了。

删去其他无关代码,核心代码直接放出来的话,如下

string keyName = null;
                string keyValue = null;
                if (File.Exists(filePath))
                {
                    string json = await File.ReadAllTextAsync(filePath);
                    JsonArray data = (JsonArray)JsonArray.Parse(json);
                  
                    foreach (var item in data)
                    {
                        var props = item.AsObject();
                        foreach (var prop in props)
                        {
                            keyName = prop.Key;
                            keyValue = prop.Value.ToString();
                            }
                        }

                    }
                }

写入json文件

读取的逆向操作

写入说白了就是读取的逆向操作。同样是“转换为Json对象,一次写入整个文档”。

先是序列化。首先要确认你的键名和键值是什么。还是以SimpleString为例子,我需要保存数据库地址和密码。那么键名就是数据库地址,键值就是数据库密码。那么现新建一个对象表示键值对。

   public class DatabaseInfo
        {
            public string databaseIP { get; set; }
            public string databasePassword { get; set; }
        }

接下来就是对象的序列化了。

   private void SaveIPAndPassword(object sender, RoutedEventArgs e)
        {
            string fileName = "AppData/InitSettings.json";
            string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
            
            try
            {
                List<DatabaseInfo>_data=new List<DatabaseInfo>();
                _data.Add(new DatabaseInfo()
                {
                    databaseIP = databaseInfo.databaseIP,
                    databasePassword = databaseInfo.databasePassword
                });
                string json = JsonSerializer.Serialize(_data);
                File.WriteAllText(filePath, json);
            }catch
            {
                ErrorMessage_CantSaveIPAndAddress();
            }
        }

其实最关键的就是这行代码。这行代码表示将_data对象序列化为字符串。

 string json = JsonSerializer.Serialize(_data);

当然这只是代码示例,具体细节如何更改得看你的程序需要保存什么数据至本地,需要读取什么类型的数据,不过大体的思路都是差不多的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ELK企业级日志分析系统

ELK概述 为什么要使用 ELK 日志主要包括系统日志、应用程序日志和安全日志。系统运维和开发人员可以通过日志了解服务器软硬件信息、检查配置过程中的错误及错误发生的原因。经常分析日志可以了解服务器的负荷&#xff0c;性能安全性&#xff0c;从而及时采取措施纠正错误。 往…

切比雪夫不等式,大数定律及极限定理。

一.切比雪夫不等式 1.定理 若随机变量X的期望EX和方差DX存在,则对任意ε > 0,有   P{ |X - EX| > ε } < DX/ε2 或 P{ |X - EX| < ε } > 1 - DX/ε2 2.解析定理 ①该定理对 X 服从什么分布不做要求&#xff0c;仅EX DX存在即可。 ②“| |” 由于X某次…

软件测试炸了,作为从业者,你做好准备了吗?

软件测试行业已经发生很大变化&#xff0c;你跟上变化了吗&#xff1f; 岗位少不可怕&#xff0c;要求越来越高也不可怕&#xff0c;可怕的是&#xff0c;软件测试行业已经发生巨变&#xff0c;而你却原地踏步&#xff01;目前一线大厂更多倾向于招收测试开发&#xff0c;或者…

自学网络安全(黑客),一般人我劝你还是算了吧

一、自学网络安全学习的误区和陷阱 1.不要试图先成为一名程序员&#xff08;以编程为基础的学习&#xff09;再开始学习 我在之前的回答中&#xff0c;我都一再强调不要以编程为基础再开始学习网络安全&#xff0c;一般来说&#xff0c;学习编程不但学习周期长&#xff0c;而且…

torch.distributed.launch多卡多机

torch.distributed.launch命令介绍 我们在训练分布式时候&#xff0c;会使用到 torch.distributed.launch 可以通过命令&#xff0c;来打印该模块提供的可选参数 python -m torch.distributed.launch --help usage: launch.py [-h] [--nnodes NNODES] [--node_rank NODE_RANK]…

诚迈科技携智达诚远出席高通汽车技术与合作峰会

5月25日至26日&#xff0c;诚迈科技及旗下的智能汽车操作系统及中间件产品提供商智达诚远作为高通生态伙伴&#xff0c;亮相首届“高通汽车技术与合作峰会”&#xff0c;通过产品展示和主题演讲呈现了基于高通骁龙数字底盘的最新智能座舱技术成果&#xff0c;共同展望智能网联汽…

GcExcel v6.1 支持新的 ‘.sjs‘ 模板文件 ‘.xltx‘ 格式 Crack

GrapeCity Documents for Excel (GcExcel) v6.1 版本现已上线&#xff01;该版本支持新的 SpreadJS .sjs 文件格式和 Excel 模板文件 .xltx 格式。此外&#xff0c;GcExcel 支持更多的SpreadJS兼容性功能和对 GcDataViewer 的多项增强。看看下面的主要亮点。 导入/导出 Spread…

Revit幕墙:用幕墙巧做屋面瓦及如何快速幕墙?

一、Revit中用幕墙巧做屋面瓦 屋面瓦重复性很高&#xff0c;我们如何快速的创建呢?下面我们来学会快速用幕墙来创建屋面瓦的技巧。 1.新建“公制轮廓-竖挺”族&#xff0c;以此来创建瓦的族(以便于载入项目中使用) 2.在轮廓族中绘制瓦的轮廓(轮廓需要闭合)&#xff0c;将族名称…

【JavaSE】Java基础语法(三十四):实现多线程

文章目录 1. 简单了解多线程2. 并发和并行3. 进程和线程4. 实现多线程方式一&#xff1a;继承Thread类【应用】5. 实现多线程方式二&#xff1a;实现Runnable接口【应用】6. 实现多线程方式三: 实现Callable接口【应用】7. 设置和获取线程名称【应用】8. 线程休眠【应用】9. 线…

Z-Library2023现状

网上基本上年年都会传出来Z-Library要被干掉的消息&#xff0c;我一直觉得&#xff0c;如果那真的发生了&#xff0c;会是人类的悲哀。 由于之前我存储的地址又挂了&#xff0c;所以紧急又寻找了一下。 1.朋友帮忙 朋友帮我搜了一下&#xff0c;发现有三个地址。 他说这第一个…

xlsx是什么格式

xlsx是什么格式? xlsx是Excel文档的扩展名&#xff0c;其基于Office Open XML标准的压缩文件格式&#xff0c;取代了其以前专有的默认文件格式&#xff0c;在传统的文件名扩展名后面添加了字母x&#xff0c;即.xlsx取代.xls。 xlsx文件是什么格式? xlsx是Excel表格的文件格…

【P34】JMeter ForEach控制器(ForEach Controller)

文章目录 一、ForEach控制器&#xff08;ForEach Controller&#xff09;参数说明二、准备工作三、测试计划设计 一、ForEach控制器&#xff08;ForEach Controller&#xff09;参数说明 可以对一个组变量进行循环迭代&#xff1b;该组件通常与后置处理器中的 JSON 提取器、正…

桥梁结构健康监测解决方案

城市桥梁担负着城市的交通和运输网络的重要角色&#xff0c;是城市生命线的重要组成部分。然而&#xff0c;随着时间的推移和日益增长的负荷&#xff0c;桥梁可能会受到各种因素的损害&#xff0c;如自然灾害、疲劳、腐蚀等。因此&#xff0c;桥梁结构健康监测变得至关重要&…

chatgpt赋能Python-python中怎么导入numpy

介绍 Python是一种广泛使用的编程语言&#xff0c;具有许多内建功能和模块&#xff0c;让开发者能够快速地编写代码。然而&#xff0c;虽然能够实现许多计算&#xff0c;但是原始Python本身并不足够处理各种科学和数字计算上需要的高效性&#xff0c;因此numpy这个开源的Pytho…

【机器学习】采样方法

文章目录 采样方法11.1 简介11.2 常见采样方法11.2.1 均匀分布采样11.2.2 逆变换采样11.2.3 拒绝采样11.2.4 重要采样11.2.5 Metropolis方法11.2.6 Metropolis-Hasting 算法11.2.7 吉布斯采样 采样方法 11.1 简介 什么是采样 从一个分布中生成一批服从该分布的样本&#xff0c…

JavaWeb ( 十 ) SpringMVC

4.Spring MVC Spring MVC是Spring提供的一个实现了Web MVC设计模式的轻量级Web框架。 三层架构分为表述层&#xff08;或表示层)、业务逻辑层、数据访问层&#xff0c;表述层表示前台页面和后台servlet 4.1.Spring MVC优点&#xff1a; ① 基于原生的Servlet&#xff0c;通过…

API测试| 了解API接口测试| API接口测试指南

什么是API&#xff1f; API是一个缩写&#xff0c;它代表了一个 pplication P AGC软件覆盖整个房间。API是用于构建软件应用程序的一组例程&#xff0c;协议和工具。API指定一个软件程序应如何与其他软件程序进行交互。 例行程序&#xff1a;执行特定任务的程序。例程也称为过…

MKS SERVO4257D 闭环步进电机_系列1 产品简介

第1部分 产品概述 1.1 产品介绍 MKS SERVO 28D/35D/42D/57D 系列闭环步进电机是创客基地为满足市场需求而自主研发的一款产品。具备脉冲接口&#xff0c;RS485接口和CAN接口&#xff0c;内置高效FOC矢量算法&#xff0c;采用高精度编码器&#xff0c;通过位置反馈&#xff0c;有…

【工具】vscode的常用插件之git插件

&#x1f41a;作者简介&#xff1a;花神庙码农&#xff08;专注于Linux、WLAN、TCP/IP、Python等技术方向&#xff09;&#x1f433;博客主页&#xff1a;花神庙码农 &#xff0c;地址&#xff1a;https://blog.csdn.net/qxhgd&#x1f310;系列专栏&#xff1a;善假于物&#…

进程间通信(命名管道)

目录&#xff1a; 1.命名管道 2.创建命名管道 --------------------------------------------------------------------------------------------------------------------------------- 1.命名管道 1.管道的一个应用限制就是只能在具有共同祖先&#xff08;具有亲缘关系&…
最新文章