1.字符串和其他类型转字节类型 BitConverter和Encoding
2.文件流的操作
//文件流操作
//打开或创建指定文件
FileStream fs = File.Open(Application.dataPath + "/Unity3.cl", FileMode.OpenOrCreate, FileAccess.ReadWrite);
//重要属性和方法
print(fs.Length);
if(fs.CanRead)
{
}
else if(fs.CanWrite)
{
}
//将文件写入
fs.Flush();
//关闭流
fs.Close();
//缓存资源的回收
fs.Dispose();
//写入字节
FileStream fs2 = new FileStream(Application.dataPath + "/Untitycl.ccc", FileMode.OpenOrCreate, FileAccess.ReadWrite);
//写入整形 转字节
byte[] bytes = BitConverter.GetBytes(999);
fs2.Write(bytes, 0, 4);
//写入字符串 转字节
byte[] bytes1 = Encoding.UTF8.GetBytes("唐老师哈哈哈哈");
//先写入字符串的长度 整形转字节
fs2.Write(BitConverter.GetBytes(bytes1.Length), 0, 4);
//再写入字符串
fs2.Write(bytes1,0,bytes1.Length);
//!!!!
//文件写入
fs2.Flush();
//缓存资源的回收
fs2.Dispose();
//读取字节
FileStream fs3 = new FileStream(Application.dataPath + "/Untitycl.ccc", FileMode.OpenOrCreate, FileAccess.ReadWrite);
//声明一个四字节的字节数组
byte[] bytes2 = new byte[4];
//记录流的下标状态
int index = fs3.Read(bytes2, 0, 4);
//读整形 字节转整形
int res3 = BitConverter.ToInt32(bytes2, 0);
print("流前进了" + index + "个位置");
print("读取的整数为:" + res3);
//读字符串长度(整形)
index= fs3.Read(bytes2, 0, 4);
print("流在4,前进了" + index + "个位置");
int length=BitConverter.ToInt32(bytes2, 0);
//声明一个字符串大小的字节数组
byte[] bytes3 = new byte[length];
index=fs3.Read(bytes3,0,length);
print("流在8,前进了" + index + "个位置");
//读字符串
string s =Encoding.UTF8.GetString(bytes3);
流的索引 index
3.文件夹操作
if(Directory.Exists(Application.dataPath+"/二进制操作"))
{
print("文件夹存在");
}
else
{
print("文件夹不存在");
}
Directory.CreateDirectory(Application.dataPath + "/二进制操作");
//删除文件夹
//Directory.Delete(Application.dataPath + "/二进制操作",true);
//得到指定路径的文件 夹 名
string []str= Directory.GetDirectories(Application.dataPath);
for (int i = 0; i < str.Length; i++)
{
print(str[i]);
}
print("************************");
//得到指定路径的文件 名
string[] str2= Directory.GetFiles(Application.dataPath);
for (int i = 0; i < str2.Length; i++)
{
//print(str2[i]);
}
//移动文件夹
//确保第二个文件没有被创建 不然会报错
//内容也会跟着走
// Directory.Move(Application.dataPath + "/二进制操作" , Application.dataPath + "/123123");
print("************************");
//文件夹目录信息
DirectoryInfo directoryInfo= Directory.CreateDirectory(Application.dataPath + "/ccc");
//文件所在路径
print(directoryInfo.FullName);
print(directoryInfo.Name);
directoryInfo= Directory.GetParent(Application.dataPath + "/ccc");
print(directoryInfo.FullName);
print(directoryInfo.Name);
print("************************");
//子文件夹信息
DirectoryInfo[] directoryInfo1= directoryInfo.GetDirectories();
print("************************");
FileInfo[] fileInfo = directoryInfo.GetFiles();
for (int i = 0; i < fileInfo.Length; i++)
{
print(fileInfo[i].FullName);
print(fileInfo[i].Name);
print(fileInfo[i].Length);
print(fileInfo[i].Extension);//后缀名
}
3.对一个类的序列化和反序列化
public class person{
public int age;
public string name;
public bool isactive;
public person()
{
this.age = 18;
this.name = "ccc";
this.isactive = true;
}
public byte[] GetBytes()
{
//声明字符数组的长度
int cavatity = sizeof(int) + Encoding.UTF8.GetBytes(name).Length + sizeof(bool)+100;
//声明一个字符数组容器
byte[] byteres = new byte[cavatity];
//
int index = 0;
//int
byte[] byte1 = BitConverter.GetBytes(age);
byte1.CopyTo(byteres, index);
index += sizeof(int);
//存长度
byte[] strByte = Encoding.UTF8.GetBytes(name);
int sInt = strByte.Length;
BitConverter.GetBytes(sInt).CopyTo(byteres, index);
index += sizeof(int);
//存字符串
strByte.CopyTo(byteres, index);
index += sInt;
//bool
byte[] byte2 = BitConverter.GetBytes(isactive);
byte2.CopyTo(byteres, index);
index += sizeof(bool);
return byteres;
}
}
3.序列化为二进制 和反序列化二进制
序列化:
//二进制操作
Person p=new Person();
//方法一 写入到内存流当中 一般用于网络传输
using(MemoryStream ms=new MemoryStream())
{
BinaryFormatter bf=new BinaryFormatter();
//序列化对象 生成p的字节数组 写入到内存流里面
bf.Serialize(ms, p);
//得到字节数组
byte[]bytes=ms.GetBuffer();
//存储字节
File.WriteAllBytes(Application.dataPath + "/序列化为二进制",bytes);
//关闭文件流
ms.Close();
}
//方法二 直接写入到文件流
using (FileStream fileStream = new FileStream(Application.dataPath + "/序列化为二进制2", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
BinaryFormatter bf2= new BinaryFormatter();
//这句代码会把p直接转换成字节形式写入到fileStream中
bf2.Serialize(fileStream, p);
fileStream.Flush();
fileStream.Close();
}
}
反序列化:
//反序列化
//直接从文件读
//Deserialize
using (FileStream fs = new FileStream(Application.dataPath + "/序列化为二进制", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
BinaryFormatter bf3= new BinaryFormatter();
Person p1= bf3.Deserialize(fs) as Person;
fs.Close();
}
//文件流
//需要先得到字节数组 用来初始化内存流对象
byte[] bytes1 = File.ReadAllBytes((Application.dataPath + "/序列化为二进制2"));
using(MemoryStream ms=new MemoryStream(bytes1))
{
BinaryFormatter bf4= new BinaryFormatter();
Person p2= bf4.Deserialize(ms) as Person;
ms.Close();
}
}
实践:
1.Unity添加菜单按钮
MenuItem特性
//代码文件要放到Enditor文件夹下面 因为打包之后不需要访问编辑器代码文件了
//加MenuItem特性 必须至少有两个目录
[MenuItem("GameTool/Test")]
//方法必须是静态的
public static void Test()
{
print("测试");
//代码直接写 刷新Progrect界面
AssetDatabase.Refresh();
}
2. 补充 打开并读取Excel表的具体信息
//根据文件流读取Excel表
IExcelDataReader excelReader= ExcelReaderFactory.CreateOpenXmlReader(fs);
//几个类
DataSet、DataTable 、DataRow
[MenuItem("GameTool/打开Excel集")]
public static void OpenExcel()
{
using (FileStream fs = File.Open(Application.dataPath + "/ArtRes/Excel/playerInfo.xlsx",FileMode.Open,FileAccess.Read))
{
//通过fs读取Excel数据
IExcelDataReader excelReader= ExcelReaderFactory.CreateOpenXmlReader(fs);
//转换成DataSet方便读取
DataSet result=excelReader.AsDataSet();
for (int i = 0; i < result.Tables.Count; i++)
{
Debug.Log(result.Tables[i].TableName);
Debug.Log(result.Tables[i].Rows.Count);
Debug.Log(result.Tables[i].Columns.Count);
}
fs.Close();
}
}
[MenuItem("GameTool/读取Excel表的具体信息")]
public static void ReadExcel()
{
using (FileStream fs = File.Open(Application.dataPath + "/ArtRes/Excel/playerInfo.xlsx", FileMode.Open, FileAccess.Read))
{
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(fs);
DataSet result = excelReader.AsDataSet();
for (int i = 0; i < result.Tables.Count; i++)
{
//某一张表的数据 DataTable
DataTable table = result.Tables[i];
//某一张表的数据 DataRow
DataRow row;
for (int j = 0; j < table.Rows.Count; j++)
{
row = table.Rows[j];
Debug.Log("新的一行********");
//每一列的信息
for (int k = 0; k < table.Columns.Count; k++)
{
Debug.Log(row[k].ToString());
//生成数据结构文件
GeneratorClass(table);
//生成容器类
GeneratorConstainer( table);
GenerateExcelBinary(table);
}
}
}
}
}
3.生成数据结构类
public static void GeneratorClass(DataTable table)
{
//生成数据结构文件
//得到表中变量名字的那一行
DataRow rowname = GetVaribleNameRow(table);
//得到表中变量类型的那一行
DataRow typename = GetVaribleTypeRow(table);
//存储数据文件类的路径
if (!Directory.Exists(ClASS_PATH))
{
Directory.CreateDirectory(ClASS_PATH);
}
//一系列拼接
string str = "public class " + table.TableName+"{\n";
for (int i = 0; i < table.Columns.Count; i++)
{
str += " public " + typename[i].ToString() + " " + rowname[i].ToString() + ";\n";
}
str += "}";
//最后通过File写入
File.WriteAllText(ClASS_PATH+table.TableName + ".cs", str);
//刷新
AssetDatabase.Refresh();
}
调用后
5.创建容器类
public static void GeneratorConstainer(DataTable table)
{
//设置通过Excel配置的主键为字典的主键
int key = GetKey(table);
//自定义规则 Excel表名和类名相同
//得到这个表的类型 就是创建的数据结构类
DataRow rowtype = GetVaribleTypeRow(table);
if(!Directory.Exists(CONSTAINER_PATH))
{
Directory.CreateDirectory (CONSTAINER_PATH);
}
string str = "using System.Collections.Generic;\n";
str += "public class " + table.TableName + "Constainer"+"\n{\n";
str += " ";
str += "public Dictionary< "+rowtype[key].ToString()+","+table.TableName+">";
str += "dataDic = new "+"Dictionary<"+rowtype[key].ToString()+","+table.TableName+">();\n";
str += "}";
File.WriteAllText(CONSTAINER_PATH + table.TableName + "Constainer.cs" , str);
AssetDatabase .Refresh();
}
调用后
6.生成二进制数据
public static void GenerateExcelBinary(DataTable table)
{
if(!Directory.Exists (BINARY_PATH))
{
Directory.CreateDirectory (BINARY_PATH);
}
using (FileStream fs = new FileStream(BINARY_PATH + table.TableName + ".ccc", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
//存储 一共有多少行
fs.Write(BitConverter.GetBytes(table.Rows.Count-4),0, 4);
//存储主键的变量名
//后面是通过字典来 . 点出数据
string keyname=GetVaribleNameRow(table)[GetKey(table)].ToString();
byte[]bytes=Encoding.UTF8.GetBytes(keyname);
//存储的字符串字节长度
fs.Write(BitConverter.GetBytes(bytes.Length), 0, 4);
//存储字符串字节数组
fs.Write(bytes, 0, bytes.Length);
DataRow row;
DataRow rowtype = GetVaribleTypeRow(table);
for (int i = index; i < table.Rows.Count; i++)
{
row = table.Rows[i];
for (int j = 0; j < table.Columns.Count; j++)
{
switch (rowtype[j].ToString())
{
case "int":
fs.Write(BitConverter.GetBytes(int.Parse(row[j].ToString())), 0, 4);
break;
case "float":
fs.Write(BitConverter.GetBytes(float.Parse(row[j].ToString())), 0, 4);
break;
case "bool":
fs.Write(BitConverter.GetBytes(bool.Parse(row[j].ToString())), 0, 1);
break;
case "string":
bytes = Encoding.UTF8.GetBytes(row[j].ToString());
fs.Write(BitConverter.GetBytes(bytes.Length), 0, 4);
fs.Write(bytes,0, bytes.Length);
break;
default:
break;
}
}
}
fs.Close();
AssetDatabase.Refresh();
}
}
乱码了...