25.Winfrom —— 二进制,json,xml数据存储

目录

一、基础工具:文件对话框(操作本地文件必备)

[1. 两种常用对话框](#1. 两种常用对话框)

完整代码

知识点说明

[二、方案 1:手动 IO 读写存储对象(简单少量数据)](#二、方案 1:手动 IO 读写存储对象(简单少量数据))

原理

实体类

窗体读写代码

优缺点

[三、方案 2:二进制序列化(原生高性能,存集合首选)](#三、方案 2:二进制序列化(原生高性能,存集合首选))

核心概念

必备条件

实体类

完整窗体代码

优缺点

[四、方案 3:原生 JSON 序列化(System.Runtime.Serialization)](#四、方案 3:原生 JSON 序列化(System.Runtime.Serialization))

说明

实体类

读写代码

优缺点

[五、方案 4:第三方 Newtonsoft.Json(Json.NET,工业首选)](#五、方案 4:第三方 Newtonsoft.Json(Json.NET,工业首选))

使用步骤

优势

简单集合示例

[复杂嵌套 JSON 解析(接口数据场景)](#复杂嵌套 JSON 解析(接口数据场景))

优缺点

[六、方案 5:XML 序列化 / XML 文档解析](#六、方案 5:XML 序列化 / XML 文档解析)

[方式 1:XmlDocument 手动解析现有 XML](#方式 1:XmlDocument 手动解析现有 XML)

[方式 2:XmlSerializer 对象序列化](#方式 2:XmlSerializer 对象序列化)

优缺点

六、六种持久化方案选型总结


一、基础工具:文件对话框(操作本地文件必备)

1. 两种常用对话框

  1. FolderBrowserDialog:选择本地文件夹,获取文件夹路径
  2. OpenFileDialog:选择文件,获取文件完整路径

完整代码

cs 复制代码
using System;
using System.Windows.Forms;

namespace FileDialogDemo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // 选择文件夹按钮
        private void btnSelectFolder_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            fbd.Description = "请选择数据保存文件夹";
            // 设置对话框默认根目录:公共文档
            fbd.RootFolder = Environment.SpecialFolder.CommonDocuments;

            if (fbd.ShowDialog() == DialogResult.OK)
            {
                // 获取选中文件夹完整路径
                string path = fbd.SelectedPath;
                this.Text = path;
            }
        }

        // 打开文件对话框示例
        private void btnOpenFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "读取本地文本文件";
            ofd.InitialDirectory = @"D:\";
            // 文件过滤:仅显示txt、jpg
            ofd.Filter = "文本文件|*.txt|图片|*.jpg";

            if (ofd.ShowDialog() == DialogResult.OK)
            {
                // 读取文件全部文本
                string content = System.IO.File.ReadAllText(ofd.FileName, System.Text.Encoding.Default);
            }
        }
    }
}

知识点说明

  1. ShowDialog() 弹出模态窗口,返回 DialogResult.OK 代表用户确认选择
  2. SelectedPath:文件夹对话框专用,拿到文件夹路径
  3. FileName:打开文件对话框专用,拿到选中文件完整路径
  4. Filter 格式:说明|后缀|说明|后缀,用来筛选文件类型

二、方案 1:手动 IO 读写存储对象(简单少量数据)

原理

不使用序列化工具,手动拆分对象每个属性,分行 / 分隔符写入 txt;读取时逐行取出,手动赋值给对象。适合单个简单对象,集合存储维护麻烦。

实体类

cs 复制代码
public class People
{
    public string Name { get; set; }
    public string Age { get; set; }
    public string Sex { get; set; }
    public string Phone { get; set; }
}

窗体读写代码

cs 复制代码
using System;
using System.IO;
using System.Windows.Forms;

namespace IOObjectSave
{
    public partial class Form1 : Form
    {
        // 写入对象到文件
        private void btnSave_Click(object sender, EventArgs e)
        {
            People p = new People()
            {
                Name = txtName.Text,
                Age = txtAge.Text,
                Sex = txtSex.Text,
                Phone = txtPhone.Text
            };

            // 创建文件流 + 文本写入器
            using (FileStream fs = new FileStream(@"data.txt", FileMode.Create))
            using (StreamWriter sw = new StreamWriter(fs))
            {
                sw.WriteLine(p.Name);
                sw.WriteLine(p.Age);
                sw.WriteLine(p.Sex);
                sw.WriteLine(p.Phone);
            }
        }

        // 读取文件还原对象
        private void btnRead_Click(object sender, EventArgs e)
        {
            People p = new People();
            using (FileStream fs = new FileStream(@"data.txt", FileMode.Open))
            using (StreamReader sr = new StreamReader(fs))
            {
                p.Name = sr.ReadLine();
                p.Age = sr.ReadLine();
                p.Sex = sr.ReadLine();
                p.Phone = sr.ReadLine();
            }
            // 赋值回输入框
            txtName.Text = p.Name;
        }
    }
}

优缺点

  • 优点:无需任何引用、上手简单、文件可读
  • 缺点:集合操作繁琐、字段增减要同步改读写代码、扩展性差

三、方案 2:二进制序列化(原生高性能,存集合首选)

核心概念

序列化:对象 / 集合 → 二进制字节写入文件 反序列化:二进制文件 → 内存对象 / 集合

必备条件

实体类必须标记 [Serializable] 特性,引入命名空间 System.Runtime.Serialization.Formatters.Binary

实体类

cs 复制代码
using System;

[Serializable] // 标记允许二进制序列化
public class Student
{
    public string Name { get; set; }
    public string Phone { get; set; }
}

完整窗体代码

cs 复制代码
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;

namespace BinarySerializeDemo
{
    public partial class Form1 : Form
    {
        List<Student> studentList = new List<Student>();
        string filePath = @"student.dat";

        public Form1()
        {
            InitializeComponent();
            // 窗体加载:读取本地已有集合
            if (File.Exists(filePath))
            {
                using (FileStream fs = new FileStream(filePath, FileMode.Open))
                {
                    BinaryFormatter bf = new BinaryFormatter();
                    List<Student> temp = bf.Deserialize(fs) as List<Student>;
                    studentList.AddRange(temp);
                }
            }
        }

        // 新增对象并序列化保存集合
        private void btnSaveList_Click(object sender, EventArgs e)
        {
            Student stu = new Student() { Name = "张三1", Phone = "1232" };
            studentList.Add(stu);

            using (FileStream fs = new FileStream(filePath, FileMode.Create))
            {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(fs, studentList); // 序列化写入文件
            }
        }

        // 反序列化读取全部集合
        private void btnReadList_Click(object sender, EventArgs e)
        {
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                BinaryFormatter bf = new BinaryFormatter();
                List<Student> list = bf.Deserialize(fs) as List<Student>;
                string msg = "";
                foreach (var item in list)
                {
                    msg += $"{item.Name}:{item.Phone} ";
                }
                this.Text = msg;
            }
        }
    }
}

优缺点

  • 优点:速度快、文件体积小、原生无第三方依赖、完美支持 List 集合
  • 缺点:二进制文件无法直接打开阅读、跨语言不兼容、.NET 高版本逐渐不推荐

四、方案 3:原生 JSON 序列化(System.Runtime.Serialization)

说明

微软自带 JSON 工具 DataContractJsonSerializer,无需 NuGet,适合简单对象;需要手动添加程序集引用 System.Runtime.Serialization

实体类

cs 复制代码
public class People
{
    public string Name { get; set; }
    public string Age { get; set; }
    public string Sex { get; set; }
}

读写代码

cs 复制代码
using System;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Windows.Forms;

namespace NativeJsonDemo
{
    public partial class Form1 : Form
    {
        string path = @"user.txt";

        // 对象序列化为JSON写入文件
        private void btnSave_Click(object sender, EventArgs e)
        {
            People p = new People()
            {
                Name = txtName.Text,
                Age = txtAge.Text,
                Sex = txtSex.Text
            };
            using (FileStream fs = new FileStream(path, FileMode.Create))
            {
                DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(People));
                json.WriteObject(fs, p);
            }
        }

        // JSON文件反序列化为对象
        private void btnRead_Click(object sender, EventArgs e)
        {
            using (FileStream fs = new FileStream(path, FileMode.Open))
            {
                DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(People));
                People p = (People)json.ReadObject(fs);
                this.Text = p.Name;
            }
        }
    }
}

优缺点

  • 优点:框架原生自带、JSON 文本可读
  • 缺点:API 繁琐、复杂集合 / 嵌套对象兼容性差、开发效率低

五、方案 4:第三方 Newtonsoft.Json(Json.NET,工业首选)

使用步骤

  1. NuGet 搜索安装 Newtonsoft.Json
  2. 引入命名空间 using Newtonsoft.Json;

优势

一行代码完成序列化 / 反序列化,完美支持对象、List、多层嵌套复杂实体,开发最常用

简单集合示例

cs 复制代码
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using System.Windows.Forms;

namespace NewtonsoftJsonDemo
{
    public partial class Form1 : Form
    {
        List<Student> studentList = new List<Student>();
        string path = @"student.json";

        public Form1()
        {
            InitializeComponent();
            // 模拟测试数据
            for (int i = 0; i < 10; i++)
            {
                studentList.Add(new Student()
                {
                    Name = "哈兰德" + i,
                    Age = i * 10,
                    Info = "前锋"
                });
            }
        }

        // 保存集合到JSON文件
        private void btnSave_Click(object sender, EventArgs e)
        {
            string jsonStr = JsonConvert.SerializeObject(studentList);
            File.WriteAllText(path, jsonStr);
        }

        // 读取JSON还原集合
        private void btnRead_Click(object sender, EventArgs e)
        {
            string json = File.ReadAllText(path);
            List<Student> list = JsonConvert.DeserializeObject<List<Student>>(json);
            string text = "";
            foreach (var item in list) text += item.Name;
            this.Text = text;
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string Info { get; set; }
    }
}

复杂嵌套 JSON 解析(接口数据场景)

多层 JSON 对应多层实体,大括号对应类、数组对应 List:

cs 复制代码
// 分层实体
public class TopicMessageList
{
    public string cover_image_url { get; set; }
    public string author_name { get; set; }
}
public class Hits
{
    public List<TopicMessageList> topicMessageList { get; set; }
}
public class XiaoShuoRoot
{
    public int code { get; set; }
    public string message { get; set; }
    public int total { get; set; }
    public Hits hits { get; set; }
}

// 读取本地复杂JSON文件
private void btnLoadData_Click(object sender, EventArgs e)
{
    string json = File.ReadAllText(@"漫画.txt", System.Text.Encoding.Default);
    XiaoShuoRoot root = JsonConvert.DeserializeObject<XiaoShuoRoot>(json);
    foreach (var item in root.hits.topicMessageList)
    {
        richTextBox1.Text += item.author_name + "\n";
    }
}

优缺点

  • 优点:API 极简、支持所有数据结构、JSON 可读性强、跨平台通用、调试方便
  • 缺点:需要额外安装 NuGet 包

六、方案 5:XML 序列化 / XML 文档解析

两种操作方式:

  1. XmlSerializer:序列化对象直接生成 XML 文件
  2. XmlDocument:手动读取 XML 节点,灵活解析自定义 XML 结构

方式 1:XmlDocument 手动解析现有 XML

cs 复制代码
<?xml version="1.0" encoding="utf-8" ?>
<StudentList>
    <Student>
        <Name>张三1</Name>
        <Age>10</Age>
        <Sex>男</Sex>
        <Phone>121323232</Phone>
    </Student>
</StudentList>

解析代码

cs 复制代码
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Xml;

namespace XmlDemo
{
    public partial class Form1 : Form
    {
        private void btnReadXml_Click(object sender, EventArgs e)
        {
            List<Student> list = new List<Student>();
            XmlDocument doc = new XmlDocument();
            doc.Load(@"../../XMLFile1.xml");
            XmlNode root = doc.DocumentElement;

            foreach (XmlNode node in root.ChildNodes)
            {
                if (node.Name == "Student")
                {
                    Student stu = new Student();
                    foreach (XmlNode child in node.ChildNodes)
                    {
                        switch (child.Name)
                        {
                            case "Name": stu.Name = child.InnerText; break;
                            case "Age": stu.Age = int.Parse(child.InnerText); break;
                            case "Sex": stu.Sex = child.InnerText; break;
                            case "Phone": stu.Phone = child.InnerText; break;
                        }
                    }
                    list.Add(stu);
                }
            }
            foreach (var s in list) MessageBox.Show(s.Name);
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string Sex { get; set; }
        public string Phone { get; set; }
    }
}

方式 2:XmlSerializer 对象序列化

cs 复制代码
// 写入XML
People p = new People() { Age = 10, Name = "zs" };
using (FileStream fs = new FileStream(@"data.xml", FileMode.Create))
{
    XmlSerializer xmlSer = new XmlSerializer(typeof(People));
    xmlSer.Serialize(fs, p);
}

// 读取XML还原对象
using (FileStream fs = new FileStream(@"data.xml", FileMode.Open))
{
    XmlSerializer xmlSer = new XmlSerializer(typeof(People));
    People p = (People)xmlSer.Deserialize(fs);
    this.Text = p.Name;
}

public class People
{
    public string Name { get; set; }
    public int Age { get; set; }
}

优缺点

  • 优点:标准标记语言、老式系统通用、配置文件常用
  • 缺点:标签冗余文件大、代码冗长、现在新项目基本优先 JSON

六、六种持久化方案选型总结

  1. 少量简单对象、不想引用第三方:手动 IO 读写
  2. 追求速度、不要求可读、纯.NET 程序:二进制序列化
  3. 不想装 NuGet、简单对象存储:原生 DataContractJsonSerializer
  4. 绝大多数业务、集合 / 嵌套对象、前后端交互:Newtonsoft.Json(推荐)
  5. 老项目、配置文件、传统系统对接:XML
  6. 文件路径选择统一搭配:FolderBrowserDialog / OpenFileDialog