变量的本质都是二进制,在内存中都以字节的形式存储着,通过sizeof方法可以看到常用变量类型占用的字节空间长度(1byte = 8bit,1bit(位)不是0就是1)
二进制文件读写的本质:将各类型变量转换为字节数组,将字节数组直接存储到文件中,不仅可以节约存储空间,提升效率;还可以提升安全性;而且在网络通信中我们直接传输的数据也是字节数据(2进制数据)
BitConverter类
类名:BitConverter
命名空间:using System
将各类型转字节
byte[] bytes = BitConverter.GetBytes(666);
字节数组转各类型,第二个参数是索引,从哪一位开始
int i = BitConverter.ToInt32(bytes, 0);
标准编码格式
编码是用预先规定的方法将文字、数字或其它对象编成数码,或将信息、数据转换成规定的电脉冲信号。为保证编码的正确性,编码要规范化、标准化,即需有标准的编码格式。常见的编码格式有ASCII、ANSI、GBK、GB2312、UTF - 8、GB18030和UNICODE等。
Encoding类
命名空间:using System.Text;
将字符串以指定编码格式转字节
byte[] bytes2 = Encoding.UTF8.GetBytes("HFUTER");
字节数组以指定编码格式转字符串
string s = Encoding.UTF8.GetString(bytes2);
对文件进行操作
File类
C#提供了一个名为File(文件)的公共类,可以快捷的通过代码操作文件相关
命名空间: System.IO
判断文件是否存在
if(File.Exists(Application.dataPath + "/Unity.wang")){print("文件存在");}else{print("文件不存在");}
创建文件
返回值是一个文件流类
FileStream fs = File.Create(Application.dataPath + "/Unity.shao");
(需要刷新才会在unity中显示)
写入文件
将指定字节数组 写入到指定路径的文件中
byte[] bytes = BitConverter.GetBytes(999);File.WriteAllBytes(Application.dataPath + "/Unity.kun", bytes);
将指定的string数组内容 一行行写入到指定路径中
string[] strs = new string[] { "lu", "ji", "peng", "kwy"};File.WriteAllLines(Application.dataPath + "/Unity.ikun", strs);
将指定字符串写入指定路径
File.WriteAllText(Application.dataPath + "/Unity.kunkun", "cxk");
读取文件
读取字节数据
//返回的也是字节数据
bytes = File.ReadAllBytes(Application.dataPath + "/Unity.lu");print(BitConverter.ToInt32(bytes, 0));
读取所有行信息
strs = File.ReadAllLines(Application.dataPath + "/Unity.zhiyin");for (int i = 0; i < strs.Length; i++){print(strs[i]);}
读取所有文本信息
print(File.ReadAllText(Application.dataPath + "/Unity.yuan"));
删除文件(如果删除打开着的文件 会报错)
File.Delete(Application.dataPath + "/Unity.edg");
复制文件
//参数一:现有文件 需要是流关闭状态//参数二:目标文件File.Copy(Application.dataPath + "/Unity.yuan", Application.dataPath + "/yuan.tanglaoshi", true);
文件替换
//参数一:用来替换的路径//参数二:被替换的路径//参数三:备份路径File.Replace(Application.dataPath + "/Unity.yuan", Application.dataPath + "/yuan.ji", Application.dataPath + "/yuan.peng");
以流的形式 打开文件并写入或读取
FileStream fs = File.Open(Application.dataPath + "/Unity.yuan", FileMode.OpenOrCreate, FileAccess.ReadWrite);
参数一:路径
参数二:打开模式
参数三:访问模式
返回的是一个流对象
文件夹
可以在操作系统的文件管理系统中,通过一些操作增删查改文件夹,通过代码的形式,对文件夹进行增删查改
类名:Directory
命名空间:using System.IO
判断文件夹是否存在
Directory.Exists(Application.dataPath + "/json")
创建文件夹
DirectoryInfo info = Directory.CreateDirectory(Application.dataPath + "/json");
删除文件夹
参数一:路径
参数二:是否删除非空目录,如果为true,将删除整个目录,如果是false,仅当该目录为空时才可删除
Directory.Delete(Application.dataPath + "/json");
查找文件夹和文件(得到指定路径下所有文件夹名)
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]);}
移动文件夹
如果第二个参数所在的路径 已经存在了一个文件夹 那么会报错,移动会把文件夹中的所有内容一起移到新的路径
Directory.Move(Application.dataPath + "/json", Application.dataPath + "/999");
DirectoryInfo和FileInfo
DirectoryInfo目录信息类,可以通过它获取文件夹的更多信息
创建文件夹方法的返回值
DirectoryInfo dInfo = Directory.CreateDirectory(Application.dataPath + "/HFUT");//全路径print(dInfo.FullName);//文件名print(dInfo.Name);
查找上级文件夹信息
dInfo = Directory.GetParent(Application.dataPath + "/HFUT");//全路径print(dInfo.FullName);//文件名print(dInfo.Name);
得到所有子文件夹的目录信息
DirectoryInfo[] dInfos = dInfo.GetDirectories();
FileInfo文件信息类:可以通过DirectoryInfo得到该文件下的所有文件信息
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);//后缀名}
文件流
C#中提供了一个文件流类 FileStream类,主要作用是用于读写文件的细节,FileStream可以以读写字节的形式处理文件
类名:FileStream
命名空间:System.IO
方法一:new FileStream
//参数一:路径//参数二:打开模式// CreateNew:创建新文件 如果文件存在 则报错// Create:创建文件,如果文件存在 则覆盖// Open:打开文件,如果文件不存在 报错// OpenOrCreate:打开或者创建文件根据实际情况操作// Append:若存在文件,则打开并查找文件尾,或者创建一个新文件// Truncate:打开并清空文件内容//参数三:访问模式//参数四:共享权限// None 谢绝共享// Read 允许别的程序读取当前文件// Write 允许别的程序写入该文件// ReadWrite 允许别的程序读写该文件FileStream fs = new FileStream(Application.dataPath + "/Lesson.yuan", FileMode.Create, FileAccess.ReadWrite);
方法二:File.Create
//方法二:File.Create//参数一:路径//参数二:缓存大小//参数三:描述如何创建或覆盖该文件(不常用)// Asynchronous 可用于异步读写// DeleteOnClose 不在使用时,自动删除// Encrypted 加密// None 不应用其它选项// RandomAccess 随机访问文件// SequentialScan 从头到尾顺序访问文件// WriteThrough 通过中间缓存直接写入磁盘FileStream fs2 = File.Create(Application.dataPath + "/Lesson.yuan");
方法三:File.Open
//参数一:路径//参数二:打开模式FileStream fs3 = File.Open(Application.dataPath + "/Lesson.yuan", FileMode.Open);
重要属性和方法
FileStream fs = File.Open(Application.dataPath + "Lesson.yuan", FileMode.OpenOrCreate);
文本字节长度:fs.Length
是否可写:fs.CanRead
是否可读:fs.CanWrite
将字节写入文件 当写入后 一定执行一次:fs.Flush();
关闭流 当文件读写完毕后 一定执行:fs.Close();
缓存资源销毁回收:fs.Dispose();
写入字节
(可写可读的路径,Application.persistentDataPath)
using (FileStream fs = new FileStream(Application.persistentDataPath + "/Lesson3.tang", FileMode.OpenOrCreate, FileAccess.Write)){byte[] bytes = BitConverter.GetBytes(999);//方法:Write//参数一:写入的字节数组//参数二:数组中的开始索引//参数三:写入多少个字节fs.Write(bytes, 0, bytes.Length);//写入字符串时bytes = Encoding.UTF8.GetBytes("HFUTER");//先写入长度//int length = bytes.Length;fs.Write(BitConverter.GetBytes(bytes.Length), 0, 4);//再写入字符串具体内容fs.Write(bytes, 0, bytes.Length);//避免数据丢失 一定写入后要执行的方法fs.Flush();//销毁缓存 释放资源fs.Dispose();}
读取字节
byte[] bytes2 = new byte[4];//参数一:用于存储读取的字节数组的容器//参数二:容器中开始的位置//参数三:读取多少个字节装入容器//返回值:当前流索引前进了几个位置int index = fs2.Read(bytes2, 0, 4);int i = BitConverter.ToInt32(bytes2, 0);
index = fs2.Read(bytes2, 0, 4);int length = BitConverter.ToInt32(bytes2, 0);//要根据存储的字符串字节数组的长度 来声明一个新的字节数组 用来装载读取出来的数据bytes2 = new byte[length];index = fs2.Read(bytes2, 0, length);//因此要先存取长度,然后再读取出来print(Encoding.UTF8.GetString(bytes2));fs2.Dispose();
索引每次读取了多少位之后,便同时移动这些位
还可以一次性读取后,再挨个读取
一开始就申明一个 和文件字节数组长度一样的容器(如果文件较大,则不推荐使用这种方式去读取)
byte[] bytes3 = new byte[fs3.Length];fs3.Read(bytes3, 0, (int)fs3.Length);fs3.Dispose();//读取整数print(BitConverter.ToInt32(bytes3, 0));//得去字符串字节数组的长度int length2 = BitConverter.ToInt32(bytes3, 4);
更加安全的使用文件流对象
using关键字重要用法(无论发生什么情况 当using语句块结束后 ,会自动调用该对象的销毁方法 避免忘记销毁或关闭流)
using (申明一个引用对象)
{
使用对象
}
C#类对象的序列化与反序列化
序列化
申明类对象
注意:如果要使用C#自带的序列化2进制方法,申明类时需要添加[System.Serializable]特性
将对象进行2进制序列化
方法一:使用内存流得到2进制字节数组,主要用于得到字节数组,可以用于网络传输
内存流对象
类名:MemoryStream
命名空间:System.IO
2进制格式化对象
类名:BinaryFormatter
命名空间:System.Runtime.Serialization.Formatters.Binary、
主要方法:序列化方法 Serialize
Person p = new Person();using (MemoryStream ms = new MemoryStream()){//2进制格式化程序BinaryFormatter bf = new BinaryFormatter();//序列化对象 生成2进制字节数组 写入到内存流当中bf.Serialize(ms, p);//得到对象的2进制字节数组byte[] bytes = ms.GetBuffer();//存储字节File.WriteAllBytes(Application.dataPath + "/Lesson.t", bytes);//关闭内存流ms.Close();}
方法二:使用文件流进行存储(主要用于存储到文件中)
using (FileStream fs = new FileStream(Application.dataPath + "/Lesson.t", FileMode.OpenOrCreate, FileAccess.Write)){//2进制格式化程序BinaryFormatter bf = new BinaryFormatter();//序列化对象 生成2进制字节数组 写入到内存流当中bf.Serialize(fs, p);fs.Flush();fs.Close();}
反序列化
反序列化文件中数据
主要类:
FileStream文件流类
BinaryFormatter 2进制格式化类
主要方法:
Deserizlize
通过文件流打开指定的2进制数据文件
using (FileStream fs = File.Open(Application.dataPath + "/Lesson.t", FileMode.Open, FileAccess.Read)){//申明一个 2进制格式化类BinaryFormatter bf = new BinaryFormatter();//反序列化Person p = bf.Deserialize(fs) as Person;fs.Close();}
反序列化网络传输过来的2进制数据
主要类
MemoryStream内存流类
BinaryFormatter 2进制格式化类
主要方法
Deserizlize
byte[] bytes = File.ReadAllBytes(Application.dataPath + "/Lesson.t");//申明内存流对象 一开始就把字节数组传输进去using (MemoryStream ms = new MemoryStream(bytes)){//申明一个 2进制格式化类BinaryFormatter bf = new BinaryFormatter();//反序列化Person p = bf.Deserialize(ms) as Person;ms.Close();}
C#对象2进制数据加密
当将类对象转换为2进制数据时进行加密,当将2进制数据转换为类对象时进行解密
这样如果第三方获取到2进制数据,不知道加密规则和解密秘钥时就无法获取正确的数据,起到保证数据安全的作用
加密并不是百分百安全可靠,只能提升一定的安全性
常用加密算法
MD5算法、SHA1算法、HMAC算法、AES/DES/3DES算法等