NET基础学习笔记8
文件流
拷贝文件的两种方式:
第一种将源文件内容全部读到内存中,再写到目标文件中;读取源文件的1KB内存,写到目标文件中,再读取源文件的1KB内存,再写到目标文件中。
第二种方式就是一种流的操作。
Stream不会将所有内容一次性读取到内存中,有一个指针,指针指到哪里才能读、写到哪里。
两种方式:
直接把一个缸中的水倒入另一个缸中。(用File直接操作)
用个桶来把一个缸中的水舀到另一个缸中。(用流的方式操作)
把字符串转化为byte字符数组 byte[] byts=System.Text.Encoding.UTF8.GetBytes(msg);
把byte数组转换为一个字符串:string msg=System.Text.Encoding.UTF8.GetString(byts);
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.IO; 6 7 namespace 文件流的操作 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 #region 通过文件流读取磁盘上的文件 14 ////1.创建文本流 15 //FileStream fsRead = new FileStream(@"1.txt", FileMode.Open); 16 ////2.创建缓存区 17 //byte[] byts = new byte[fsRead.Length]; 18 ////3.开始读取 19 //int r = fsRead.Read(byts, 0, byts.Length); 20 //fsRead.Close(); 21 //fsRead.Dispose(); 22 //string readfile=System.Text.Encoding.UTF8.GetString(byts); 23 //Console.WriteLine(readfile); 24 25 #endregion 26 27 #region 通过文件流写入文件 28 //1.创建文件流 29 FileStream fs = new FileStream(@"c:\1.txt", FileMode.OpenOrCreate); 30 string msg = "创建文件流然后把东西存入文件"; 31 //2.创建byte[]缓存区 32 byte[] byts=System.Text.Encoding.UTF8.GetBytes(msg); 33 //3.将byts中的内容写入文件中。 34 fs.Write(byts, 0, byts.Length); 35 //4.关闭文件流. 36 fs.Close();//不关闭,写不进去 37 fs.Dispose(); 38 Console.WriteLine("写入成功"); 39 #endregion 40 41 Console.WriteLine("OK"); 42 Console.ReadKey(); 43 } 44 } 45 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.IO; 6 7 namespace 文件读取到内存中 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //源路径 14 string source = @"E:\HTCDriver3.0.0.005.rar"; 15 //目标路径 16 string target = @"F:\HTCDriver3.0.0.005.rar"; 17 18 CopyFile(source, target); 19 } 20 21 private static void CopyFile(string source, string target) 22 { 23 //文件流的使用步骤: 24 //1.创建一个文本流: 25 using (FileStream fs = new FileStream(source, FileMode.Open)) 26 { 27 using (FileStream ws = new FileStream(target, FileMode.OpenOrCreate)) 28 { 29 //2.读或者写: 30 //创建缓存区。byte表示字节。8个bit表示8位。每次读取的内容都要放在缓冲区中。 31 byte[] byts = new byte[1024 * 1024 * 5]; 32 //第一个参数:byts,表示将文件中的字节读取到该数组中。 33 //第二个参数:表示从文件中读取出的字节数,要放到byts这个数组中,从第几个开始放。 34 //第三个参数:这次最多读取多少个字节。 35 //返回表示本次实际读取到了多少个字节。 36 long readlength = fs.Length; 37 double parportion=0.0; 38 while (parportion != 1.0) 39 { 40 int result = fs.Read(byts, 0, byts.Length); 41 string strfile = System.Text.Encoding.UTF8.GetString(byts); 42 ws.Write(byts, 0, result); 43 long writelength = ws.Length; 44 parportion = (double)writelength / readlength; 45 Console.WriteLine("复制到{0}%",parportion*100); 46 } 47 } 48 } 49 50 Console.WriteLine("复制完成"); 51 Console.ReadKey(); 52 53 } 54 } 55 }
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.IO; 10 11 namespace _1加密文件 12 { 13 public partial class Form1 : Form 14 { 15 public Form1() 16 { 17 InitializeComponent(); 18 } 19 20 private void button1_Click(object sender, EventArgs e) 21 { 22 Emcrypt(textBox1.Text, textBox2.Text); 23 } 24 25 private void button2_Click(object sender, EventArgs e) 26 { 27 Deciphering(textBox2.Text, textBox3.Text); 28 } 29 30 public void Emcrypt(string souce, string goal) 31 { 32 using(FileStream readstram=new FileStream(souce,FileMode.OpenOrCreate)) 33 { 34 using (FileStream writestream = new FileStream(goal, FileMode.Create)) 35 { 36 int readnumber; 37 byte[] bys = new byte[1024 * 1024 * 5 + 5]; 38 while (true) 39 { 40 readnumber = readstram.Read(bys, 4, bys.Length-5); 41 if (readnumber == 0) 42 { 43 break; 44 } 45 writestream.Write(bys, 0, readnumber); 46 } 47 } 48 } 49 } 50 51 public void Deciphering(string souce, string goal) 52 { 53 using (FileStream readstram = new FileStream(souce, FileMode.OpenOrCreate)) 54 { 55 using (FileStream writestream = new FileStream(goal, FileMode.Create)) 56 { 57 int readnumber; 58 byte[] bys = new byte[1024 * 1024 * 5 + 5]; 59 while (true) 60 { 61 readnumber = readstram.Read(bys, 0, bys.Length); 62 if (readnumber == 0) 63 { 64 break; 65 } 66 writestream.Write(bys, 4, readnumber-5); 67 } 68 } 69 } 70 } 71 72 73 } 74 }
StreamWriter(读取文本文件)
Stream把所有内容当成二进制来看待,如果是文本内容,则需要程序员来处理文本和二进制之间的转换。
用StreamWriter可以简化文本类型的Stream的处理
StreamWriter是辅助Stream进行处理的
StreamReader
和StreamWriter类似, StreamReader简化了文本类型的流的读取。
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.IO; 10 11 namespace _2.StreamWrite和StreamRead 12 { 13 public partial class Form1 : Form 14 { 15 public Form1() 16 { 17 InitializeComponent(); 18 } 19 20 private void button1_Click(object sender, EventArgs e) 21 { 22 using (StreamWriter streamwrite = new StreamWriter(@"c:\writ.txt", true, Encoding.Default)) 23 { 24 for (int i = 0; i < 50; i++) 25 { 26 streamwrite.WriteLine("加油!多努力一点,以后生活美好一点+" + i); 27 } 28 } 29 using (StreamReader streamreader = new StreamReader(@"c:\writ.txt",Encoding.Default)) 30 { 31 //第一种方式读入 32 //while (!streamreader.EndOfStream) 33 //{ 34 // textBox1.Text = textBox1.Text + streamreader.ReadLine(); 35 //} 36 //第二种方式读入 37 string result; 38 while ((result=streamreader.ReadLine())!=null) 39 { 40 textBox1.Text = textBox1.Text + result+"/t /n"; 41 } 42 43 } 44 } 45 } 46 }
对象序列化(二进制序列化)
对象序列化是将对象(比如Person对象)转换为二进制数据(字节流),反序列化是将二进制数据还原为对象。对象是稍纵即逝的,不仅程序重启、操作系统重启会造成对象的消失,就是退出函数范围等都可能造成对象的消失,序列化/反序列化就是为了保持对象的持久化。就像用DV录像(序列化)和用播放器播放(反序列化)一样。
对象序列化,只能针对对象的字段进行序列化。
BinaryFormatter类有两个方法:
void Serialize(Stream stream, object graph)对象graph序列化到stream中
object Deserialize(Stream stream)将对象从stream中反序列化,返回值为反序列化得到的对象
不是所有对象都能序列化,只有可序列化的对象才能序列化,在类声明上添加[Serializable],对象的属性、字段的类型也必须可序列化
关于二进制序列化需要注意的事项:
1.要序列化的类型必须标记为:[Serializable]
2.该类型的父类也必须标记为: [Serializable]
3.该类型中的所有成员的类型也必须标记为: [Serializable]
4.序列化只会对类中的字段序列化。(只能序列化一些状态信息。)
5.不建议使用自动属性。(每次生成的字段都可能不一样,影响反序列化)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Runtime.Serialization.Formatters.Binary; 6 using System.IO; 7 8 namespace _3系列化文本对象 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 Person zhj = new Person(); 15 zhj.Name = "速度改变"; 16 zhj.Age = 21; 17 zhj.Mycar = new Car(); 18 //对象序列化的步骤: 19 //1.创建二进制对象序列化器 20 BinaryFormatter bf = new BinaryFormatter(); 21 22 //2.创建文本流 23 using (FileStream fs = new FileStream("person.bin", FileMode.Create)) 24 { 25 bf.Serialize(fs, zhj); 26 } 27 28 } 29 } 30 //Person类型要想被序列化。 31 //1.必须Person类型本身是可序列化的。 32 //2.类中所有的字段属性的类型也必须标记为可序列化的。 33 [Serializable] 34 public class Person 35 { 36 //在使用序列化的时候尽量避免使用自动属性,因为自动属性,每次编译的时候自动生成的字段名可能不一样。 37 //所以在反序列化的时候可能会造成问题。 38 public string Name 39 { 40 set; 41 get; 42 } 43 44 public int Age 45 { 46 get; 47 set; 48 } 49 50 private Car mycar; 51 52 public Car Mycar 53 { 54 get { return mycar; } 55 set { mycar = value; } 56 } 57 } 58 59 [Serializable] 60 public class Car 61 { 62 private string carname; 63 64 public string Carname 65 { 66 get { return carname; } 67 set { carname = value; } 68 } 69 } 70 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Runtime.Serialization.Formatters.Binary; 6 using System.IO; 7 using _3系列化文本对象; 8 9 namespace _4反序列化 10 { 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 //1.创建二进制序列化器 16 BinaryFormatter bf = new BinaryFormatter(); 17 18 //2.创建流 19 using (FileStream fs=new FileStream("Person.bin",FileMode.Open)) 20 { 21 //开始执行反序列化 22 //在执行反序列化的时候,必须引用Person的程序集 23 //反序列化的时候。要返回一个对象。这个对象必须根 24 //据原来Person所在的程序集才能创建。也就是说Person.bin中包含的仅仅一些数据, 25 //根据这些数据是无法在内存中创建对象的。只能是根据原来的Person类型的程序集来创建 26 //object obj = bf.Deserialize(fs); 27 Person per = (Person)bf.Deserialize(fs); 28 Console.WriteLine(per.Name); 29 Console.ReadKey(); 30 } 31 } 32 } 33 }
为什么要序列化?
将一个复杂的对象转换流,方便我们的存储与信息交换
序列化的应用:
将对象持久化存储,磁盘、数据库
将对象复制到剪贴板
将对象通过网络传输
将对象备份(深拷贝。)
序列化的步骤:
1.创建一个二进制序列化器:
BinaryFormatter bf=…..;
1.5:创建一个文件流。
2.bf.Serialize(stream,对象);
反序列化的步骤
1.创建一个二进制序列化器:
BinaryFormatter bf;
2.创建文件流:
3.执行反序列化:
object obj=bf.Deserialize(stream);