我们在上一个文章中提到了,在C#中使用代码操作文件,我们接下来再看看在C#中如何使用代码操作文件夹。C#提供了一个文件夹操作公共类Directory,其中给我们提供了一些操作文件夹的方法。
Directory中的方法
1.判断文件夹是否存在
2.创建文件夹
代码如下,如果存在文件夹则打印"存在文件夹",否则就打印“不存在文件夹”并创建文件夹
if (Directory.Exists(Application.dataPath + "/DataPersistance"))
{
print("存在文件夹");
}
else
{
print("文件夹不存在");
//2.创建文件夹
DirectoryInfo info = Directory.CreateDirectory(Application.dataPath + "/DataPersistance");
}
3.删除文件夹
//3.删除文件夹
//参数一:路径
//参数二:是否删除非空目录,如果为true,将删除整个目录,如果是false,仅当改目录为空时才可以删除
/Directory.Delete(Application.dataPath + "/DataPersistance");
4.查找指定文件夹和指定文件
//得到指定路径下的所有文件夹名
string[] strs = Directory.GetDirectories(Application.dataPath);
for (int i = 0; i < strs.Length; i++)
{
print(strs[i]);
}
//得到指定路径下的所有文件名
strs = Directory.GetFiles(Application.dataPath);
for (int i = 0; i < strs.Length; i++)
{
print(strs[i]);
}
5.移动文件夹(第一个参数为原文件路径,第二个参数为目标文件路径)
//5.移动文件夹
//如果第二个参数所在的路径已经存在了一个文件夹 就会报错
//移动会把文件夹中的所有内容 一起移动到新的路径
Directory.Move(Application.dataPath + "/DataPersistance", Application.dataPath+"/moveFile");
上述就是Directory中提供的常用的方法,在此基础上我们还可以通过DirectoryInfo获取到文件夹的更多信息
DirectoryInfo目录信息类和FileInfo文件信息类
//DirectoryInfo目录信息类
//我们可以通过它获取文件夹的更多信息
//它主要出现在两个地方
//1.创建文件夹方法的返回值
DirectoryInfo dInfo = Directory.CreateDirectory(Application.dataPath + "/DataPersistance2");
print("**********************");
//全路径
print(dInfo.FullName);
//文件名
print(dInfo.Name);
//2.查找上级文件夹信息
dInfo = Directory.GetParent(Application.dataPath + "/DataPersistance2");
print("**********************");
//全路径
print(dInfo.FullName);
//文件名
print(dInfo.Name);
//重要方法
//得到所有文件夹的目录信息
FileInfo[] fInfos = dInfo.GetFiles();
for (int i = 0; i <fInfos.Length; i++)
{
print(fInfos[i].Name);//文件名
print(fInfos[i].FullName);//路径
print(fInfos[i].Length);//字节长度
print(fInfos[i].Extension);//后缀名
//返回一个文件流
//fInfos[i].Open()
}
了解完了上述字节码转换,文件文件夹操作、数据的流的相关使用后,我们可以尝试去序列化对象。 我们先声明一些需要序列化的数据类型例子。
类对象的序列化
两个类类型(一个Person一个ClassTesr)一个结构体类型(StructTest)
[System.Serializable]
public class Person
{
public int age = 1;
public string name = "mqx";
public int[] ints = new int[] { 1, 2, 3, 4, 5 };
public List<int> list = new List<int>() { 1, 2, 3, 4, 5 };
public Dictionary<int, string> dic = new Dictionary<int, string>() { { 1, "NO.1" }, { 2, "NO.2" }, { 3, "NO.3" } };
public StructTest st = new StructTest(2, "123");
public ClassTest ct = new ClassTest();
}
[System.Serializable]
public struct StructTest {
public int i;
public string s;
public StructTest(int i,string s)
{
this.i = i;
this.s = s;
}
}
[System.Serializable]
public class ClassTest {
public int i = 1;
}
有两种方法可以去序列化Person类实例的方法,文件流存储和内存流存储:
方法一:使用内存流得到二进制字节数组
using (MemoryStream ms = new MemoryStream())
{
//二进制格式化程序
BinaryFormatter bf = new BinaryFormatter();
//生产二进制字节数组 写入到内存流中
bf.Serialize(ms, person);
//得到对象的二进制字节数组
byte[] bytes = ms.GetBuffer();
//存储字节
File.WriteAllBytes(Application.dataPath + "/Lesson5.mqx", bytes);
ms.Close();
//关闭内存流下
}
其本质就是通过BinaryFormatter去将对象转为二进制格式,写入内存流中,然后又从内存流中获取到这个二进制字数组,最后通过File写入文件。关闭内存流。
方法二:使用文件流进行存储
using (FileStream fs = new FileStream(Application.dataPath+"/Lesson5_2",FileMode.OpenOrCreate,FileAccess.Write)) {
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, person);
fs.Flush();
fs.Close();
}
这个方法的本质同样需要使用到BinaryFormatter将二进制进行转换,然后直接通过FileStream文件流写入文件,最后关闭文件流。
然后再是反序列化,反序列化其本质核心与序列化相同,都基本使用BinaryFormatter类和FileStream类(由于Unity网络开发还没有接触)所以还是使用MemoryStream内存流读取数据。
类对象的反序列化:
#region 反序列化之 反序列化文件中的数据
//主要类
//FileStream文件流
//BinaryFormatter
//主要方法
//Deserizlize
using (FileStream fs = File.Open(Application.dataPath + "/Lesson5_2", FileMode.Open, FileAccess.ReadWrite)) {
BinaryFormatter bf = new BinaryFormatter();
Lesson5.Person p= bf.Deserialize(fs) as Lesson5.Person;
}
#endregion
#region 反序列之反序列化网络传输过来二进制数据
//主要类
//MemoryStream内存流类
//BinaryFormatter 二进制格式化类
//主要方法
//Deserizlize
//目前没有网络传输就直接从文件获取
byte[] bytes = File.ReadAllBytes(Application.dataPath + "/Lesson5_2.mqx");
//声明内存流对象 一开始就把字节流数组传输进去
using (MemoryStream ms=new MemoryStream (bytes)) {
BinaryFormatter bf = new BinaryFormatter();
Lesson5.Person p= bf.Deserialize(ms) as Lesson5.Person;
ms.Close();
}
#endregion
}
其本质是声明一个对象流或者文件流,将需要序反序列化的文件传入BinaryForamatter对象中,然后将返回值as成相同类型。
学习了对象序列化和反序列化的基础操作后,可以尝试写一个用于此操作的单例类,代码如下
序列化单列类
public class BinaryDataMgr
{
private static BinaryDataMgr instance = new BinaryDataMgr();
public static BinaryDataMgr Instance => instance;
private BinaryDataMgr() { }
private static string SAVE_PATH = Application.persistentDataPath + "/Data/";
/// <summary>
/// 存储类对象数据
/// </summary>
/// <param name="data">需要存储的对象</param>
/// <param name="fileName">文件名</param>
public void Save(object data,string fileName) {
//判断路径文件夹是否存在
if (Directory.Exists(SAVE_PATH))
{
Directory.CreateDirectory(SAVE_PATH);
}
using (FileStream fs = new FileStream(SAVE_PATH+fileName+".mqx",FileMode.OpenOrCreate,FileAccess.Write)) {
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, data);
fs.Close();
}
}
/// <summary>
/// 读取二进制数据转换为类对象
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="fileName">文件名</param>
/// <returns></returns>
public T Load<T>(string fileName) where T:class {
if (!File.Exists(SAVE_PATH+fileName+".mqx"))
{
return default(T);
}
T obj;
using (FileStream fs=File.Open(SAVE_PATH+fileName +".mqx",FileMode.Open,FileAccess.Read)) {
BinaryFormatter bf = new BinaryFormatter();
obj = bf.Deserialize(fs) as T;
fs.Close();
}
return obj;
}
}