拷贝文件的两种方式:将源文件内容全部读到内存中,再写到目标文件中;读取源文件的1KB内存,写到目标文件中,再读取源文件的1KB内存,再写到目标文件中........。第二种方式就是一种流的操作。
用File.ReadAllText、File.WriteAllText进行文件读写是一次性读、写,如果文件非常大会占内存、慢。需要读一行处理一行的机制,这就是流(Stream)。Stream会只读取要求的位置、长度的内容。
Stream不会将所有内容一次性读取到内存中,有一个指针,指针指到哪里才能读、写到哪里。
FileStream的Postion属性为当前文件指针位置,每写一次就要移动一下Position以备下次写到后面的位置。Write用于向当前位置写入若干字节,Read用户读取若干字节。
流操作的都是字节,不能直接操作字符串。
通过FileStream来写文件:
1 //1.创建文件流----除了下面这种方式,还有通过File.OpenWrite实现 2 using (FileStream fsWrite =new FileStream("first.txt", FileMode.Create, FileAccess.Write)) 3 { 4 //2.使用文件流,执行读写操作 5 string msg="今天是个好日子。lalala....."; 6 byte[] byts=System.Text.Encoding.UTF8.GetBytes(msg); 7 8 // 写 9 // 参数1:表示将指定的字节数组中的内容写入到文件 10 // 参数2:参数1的数组的偏移量,一般为0 11 // 参数3:本次文件写入操作要写入的实际字节数 12 fsWrite.Write(byts,0,byts.Length); 13 }
通过FileStream来读文件:
1 //1.创建文件流----除了下面这种方式,还有通过File.OpenRead实现 2 //使用FileStream文件流读取文本文件的时候,不想要指定编码,因为编码是在将byte数组转换为字符串的时候才需要使用编码,而这里是直接读取到byte[],所以无需使用编码 3 using (FileStream fsRead =new FileStream("first.txt", FileMode.Open, FileAccess.Read)) 4 { 5 //根据文件的总字节数,创建一个byte数组,这种方式会将文件内容一次性读取出来,读取到byte[]中 6 byte[] bytes = new byte[fsRead.Length]; 7 8 //2.读取文件 9 fsRead.Read(bytes, 0, bytes.Length); 10 }
大文件拷贝
// 通过文件流实现将source中的文件拷贝到target private static void BigFileCopy(string source, string target) { //1.创建一个读取源文件的文件流 using (FileStream fsRead = new FileStream(source, FileMode.Open, FileAccess.Read)) { //2.创建一个写入新文件的文件流 using (FileStream fsWrite = new FileStream(target, FileMode.Create, FileAccess.Write)) { //拷贝文件的时候,创建一个中间缓冲区 byte[] bytes=new byte[1024 * 1024 * 5]; //返回值表示本次实际读取到的字节个数 int r = fsRead.Read(bytes, 0, bytes.Length); while (r > 0) { //将读取到的内容写入到新文件中 //第三个参数应该是实际读取到的字节数,而不是数组的长度 fsWrite.Write(bytes, 0, r); double d = (fsWrite.Position / (double)fsRead.Length) * 100; Console.WriteLine("{0}%", d); r = fsRead.Read(bytes, 0, bytes.Length); } } } }