数据持久化(二进制)

二进制数据持久化的好处:安全、效率高、利于网络通信

补充文件夹相关

Editor

打包是不会将Editor文件打包出去

Resources

  • 打包时会合并Assets目录下的所有Resources的文件,启动程序时对所有对象初始化,构建实例ID这个过程耗时非线性,可能导致启动程序过长,打包完后会进行压缩加密

  • Resources资源在App中,是存储在resources.assetsresources.assets.resSsharedassets0.assetssharedassets0.assets.resS文件中

  • .assets.assets.resS两个后缀文件。同名文件的.assets存储的是序列化文件,类似于Prefab,存储着资源的所有序列化信息,以及对二进制数据源的引用。而.assets.resS里面存储的是二进制数据源,如图片、音效等,是.assets里面所引用的实际的图片、音效等数据。

  • Resources目录下的资源是打包时,未被引用的资源是打包到resources*中,比如新放入的图片还没有使用。而被引用的资源是被打包到sharedassets*,比如被其他Prefab引用的图片。
    在这里插入图片描述

SteammingAsset

只能有一个且位于Assets下,一般放置二进制配置文件,打包时不会被加密压缩,一般用于存储二进制文件
在这里插入图片描述

序列化和反序列化

序列化类对象添加特性:[System.Serializable]字段中的类也需要添加特性

内存流对象:
类对象:MemoryStream
命名空间:System.IO
2进制格式化对象:
类对象:BinaryFormatter
命名空间:System.Runtime.Serialization.Formatters.Binary

序列化

// 方法一:使用内存流
using (MemoryStream ms = new MemoryStream())
{
    BinaryFormatter bf = new BinaryFormatter();
    bf.Serialize(ms, animal); // 二进制序列化程序
        
    byte[] aniBytes = ms.GetBuffer(); // 获得字节
    File.WriteAllBytes(path, aniBytes);
    
    ms.Close();
}

// 方法二:使用文件流
using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
{
    BinaryFormatter bf = new BinaryFormatter();
    bf.Serialize(fs, animal); // 直接写入文件流
    
    fs.Flush();
    fs.Close();
}

反序列化

// 方法一:文件流
using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read))
{
    BinaryFormatter bf = new BinaryFormatter();
    Animal an = bf.Deserialize(fs) as Animal; // 返回object
    
    fs.Close();
}
        
// 方法二:内存流(用于网络传输)
using (MemoryStream ms = new MemoryStream(bytes))
{
    BinaryFormatter bf = new BinaryFormatter();
    Animal an = bf.Deserialize(ms) as Animal;
    
    ms.Close();
}

使用Excel表

using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read))
{
    // 通过文件流获取数据
    IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(fs);
    // 将excel表中的数据转换为DataSet数据类型
    DataSet result = excelReader.AsDataSet();
    // 获取表中的信息
    // 空表不会获得
    for (int i = 0; i < result.Tables.Count; i++)
    {
        string tableName = result.Tables[i].TableName; // 表名
        int rowCount = result.Tables[i].Rows.Count; // 表行数
        int colCount = result.Tables[i].Columns.Count; // 表列数
    
        DataTable dataTable = result.Tables[i]; // 获得一张表
        DataRow dr = dataTable.Rows[0]; // 第0行数据
        object obj1 = dr[0]; // 第0行第0列
        object obj2 = dataTable.Rows[0][1];
    }
    
    fs.Close();
}

二进制数据持久化

转换为字节数据

int age = 10;
// 字节数组长度与数据类型的字节数相等
// 【数据转字节】 
byte[] ageByte = BitConverter.GetBytes(age);
// 【字节转数据】
age = BitConverter.ToInt32(ageByte, 0);

// 【字符串转字节】
// Encoding.编码格式
byte[] strByte = Encoding.UTF8.GetBytes("111111");
// 【字符串字节转数据】
string str = Encoding.UTF8.GetString(strByte);

文件操作

类名:File 命名空间:System.IO

// 【判断文件是否存在】
if (File.Exists(Application.dataPath + "/DataPersistence/Teach1.cs"))
{
    Debug.Log("存在");
}
//  【创建文件】
// 已经存在的文件不能创建会抛异常
FileStream gfs = File.Create(Application.dataPath + "/DataPersistence/Teach2.txt");

// 【写入文件】
// 按字节写入
File.WriteAllBytes(Application.dataPath + "/DataPersistence/Teach2.txt", BitConverter.GetBytes(1024));
// 按行写入字符串数组
string[] strArray = new string[] { "一", "二", "三" };
File.WriteAllLines(Application.dataPath + "/DataPersistence/Teach2.txt", strArray);
// 写入字符串
File.WriteAllText(Application.dataPath + "/DataPersistence/Teach2.txt", "面包");

// 【读取文件】
// 读取字节数据
Byte[] bytes = File.ReadAllBytes(Application.dataPath + "/DataPersistence/Teach2.txt");
// 读取所有行字符串
strArray = File.ReadAllLines(Application.dataPath + "/DataPersistence/Teach2.txt");
// 读取文本
string tStr = File.ReadAllText(Application.dataPath + "/DataPersistence/Teach2.txt");

// 【删除文件】
File.Delete(Application.dataPath + "/DataPersistence/Teach2.txt");

// 【文件流】
// 打开 (路径、文件模式 打开or创建、打开方式 可读可写)
File.Open( Application.dataPath + "/DataPersistence/Teach2.txt", FileMode.OpenOrCreate, FileAccess.Write);

类名:FileStream 命名空间:System.IO

基本操作:

// 【创建文件】
// FileMode:打开模式
// CreateNew (创建新文件,如果存在则报错)
// Create (创建新文件,存在则覆盖)
// Open (打开文件,不存在则报错)
// OpenOnCreate (打开文件,不存在则创建)
// Append (存在则打开并查找文件尾,或创建新文件)
// Truncate (打开并清空内容)

// FileAccess:访问模式
// None (谢绝共享)
// Read (允许别的程序读取)
// Write (允许别的程序写入)
// ReadWrite (允许别的程序读写)

// 方法一:
FileStream fs = new FileStream("teach1.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite);
//方法二:
FileStream gfs = File.Create(Application.dataPath + "/DataPersistence/Teach2.txt");
//方法三:
File.Open( Application.dataPath + "/DataPersistence/Teach2.txt", FileMode.OpenOrCreate,
FileAccess.Write);

// 【获得属性】
long fsLength = fs.Length; // 长度
bool canRead = fs.CanRead; // 是否可读
bool canWrite = fs.CanWrite; // 是否可写

// 【方法】
fs.Flush(); // 执行完文件后执行,保证文件操作成功进行缓存
fs.Close(); // 关闭流,
fs.Dispose(); // 释放缓存资源

写入字节:

FileStream fs1 = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
// 参数:(字节数组,数组开始位置,写入多少个字节)
Byte[] data1 = BitConverter.GetBytes(100);
Byte[] data2 = BitConverter.GetBytes(true);
fs1.Write(data1, 0, 4);
fs1.Write(data2, 0, data2.Length);
// 写入字符串
Byte[] data3 = Encoding.UTF8.GetBytes("Hello World");
int strLength = data3.Length; // 获得字节长度
// 写入字符串的长度
fs1.Write(BitConverter.GetBytes(strLength), 0, sizeof(int)); 
// 写入字符串的长度
fs1.Write(data3, 0, data3.Length); 
fs1.Flush(); // 防止数据丢失
fs1.Dispose(); // 释放资源

读取字节

FileStream fs2 = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Read);
// 方法一:分段读取
Byte[] byte1 = new byte[4];
int streamIndex = fs2.Read(byte1, 0, 4); // 返回流索引
int data1 = BitConverter.ToInt32(byte1);

// 读取字符串
Byte[] byte2 = new byte[4];
fs2.Read(byte2, 0, 4);
int strLength = BitConverter.ToInt32(byte2); // 获取字符串长度
Byte[] strBytes = new Byte[strLength];
fs2.Read(strBytes, 0, strLength);
string str = Encoding.UTF8.GetString(strBytes); // 读取字符串内容

// 方法二:全部读取
byte[] data = new byte[fs2.Length];
fs2.Read(data, 0, data.Length);

fs2.Dispose();

安全关闭

using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
{
	// 语句块执行完之后自动调用Dispose,更加安全
}

文件夹操作

操作文件夹

// 【判断文件夹是否存在】
if (Directory.Exists(path))
{
    Debug.Log("存在文件夹");
}

// 【创建文件夹】
DirectoryInfo df = Directory.CreateDirectory(path);

// 【删除文件夹】
// 参数二:是否删除非空目录,true可以删除非空目录,false非空目录不能删除进行报错
Directory.Delete(path, true);

// 【查找文件夹】
// 返回该路径下的所有文件夹名
string[] allDirec = Directory.GetDirectories(path); 
// 返回该路径下的所有文件名
string[] allFiles = Directory.GetFiles(path);

// 【移动文件夹】
// 参数二路径中的文件夹已存在会报错
// 将目录下的所有文件进行移动
Directory.Move(Application.dataPath + "/TestFile", path);

目录信息和文件信息

类名:DirectoryInfo

DirectoryInfo df = Directory.CreateDirectory(path);
string direcPath = df.FullName; // 文件夹路径
string direcName = df.Name; // 文件夹名
DirectoryInfo dfParent = Directory.GetParent(path); // 得到上级文件夹信息
DirectoryInfo[] sonDf = df.GetDirectories(); // 所有子文件夹目录信息

类名:FileInfo

DirectoryInfo df = Directory.CreateDirectory(path);
string direcPath = df.FullName; // 文件夹路径
string direcName = df.Name; // 文件夹名
DirectoryInfo dfParent = Directory.GetParent(path); // 得到上级文件夹信息
DirectoryInfo[] sonDf = df.GetDirectories(); // 所有子文件夹目录信息

FileInfo[] fi = df.GetFiles(); // 得到所有文件信息
foreach (FileInfo fileInfo in fi)
{
    string fileName = fileInfo.Name; // 文件名
    string filePath = fileInfo.FullName; // 路径
    long fileLength = fileInfo.Length; // 字节长度
    string fileExtension = fileInfo.Extension; // 后缀名
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值