C# IO操作(四)大文件拷贝(文件流的使用)、文件编码

     大文件拷贝(文件流的使用)、文件编码

首先说一下大文件拷贝和文件流,因为计算机的内存资源是有限的,面对几个G甚至更大的文件,需要通过程序来完成拷贝,就需要用到文件流(因为我们无法做到把文件一次性加载到内存中;事实上,内存也不允许这么干),所以在C#中出现了内存流这个东西。先看下面的内容,File类中的常用读取文件方法会将文件内容一次性全部加载到内存中

1             string sPath = @"C:\Users\Chens-PC\Desktop\Nginx.txt";
2             //File类的ReadAllBytes()方法会将文本内容一次性读取到内存中,然后以byte数组返回(同时关闭文件)。
3             byte[] bteData = File.ReadAllBytes(sPath);
4             //File类的ReadAllLines()方法会将文本内容一次性逐行读取到内存中,然后以string数组返回(同时关闭文件),它的重载能指定读取时使用的编码。
5             string[] strData = File.ReadAllLines(sPath);
6             //File类的ReadAllText()方法会将文本内容一次性读取到内存中,然后以string字符串返回(同时关闭文件),它的重载能指定读取时使用的编码。
7             string sData = File.ReadAllText(sPath);

注:上面的代码,在传参时为Encoding.Default(表示与当前操作系统编码一致,一般是简体中文ANSI),而DotNet新建文本文件编码为UTF-8.

在进行大文件拷贝之前,先说一下,如果使用文件流(FileStream):

 1            #region 通过文件流写文件
 2             string sMsg = "风儿吹来了童年的一幅画 你陪着我在那过家家 竹林是我们的家 竹叶是你送我的花 抬头见你笑得那么的无暇";
 3             using (FileStream fsWrite = new FileStream("msg.txt", FileMode.Create, FileAccess.Write))
 4             {
 5                 byte[] bteData = System.Text.Encoding.UTF8.GetBytes(sMsg);
 6                 fsWrite.Write(bteData, 0, bteData.Length);
 7                 fsWrite.Flush();
 8             }
 9             Console.WriteLine("文件写入完毕!");
10             #endregion
 1             #region 通过文件流读文件
 2             using (FileStream fsRead = new FileStream("msg.txt", FileMode.Open, FileAccess.Read))
 3             {
 4                 byte[] bteData = new byte[fsRead.Length];
 5                 fsRead.Read(bteData, 0, bteData.Length);
 6                 //将byte[]数组转换成字符串时才需要指定编码。
 7                 string s = System.Text.Encoding.UTF8.GetString(bteData);
 8                 Console.WriteLine(s);
 9             }
10             #endregion

1.大文件拷贝:

思路:考虑到大文件的拷贝要边读边写,故要创建2个文件流(一个读,一个写),案例的代码如下(winform照样适用):

1              #region 大文件拷贝
2             string sSource = @"F:\系统\cn_windows_7_ultimate_with_sp1_x86_dvd_618763.iso";
3             string sTarget = @"E:\C#练习第一天\windows_7.iso";
4
5             CopyBigFile(sSource, sTarget);
6             Console.ReadKey();
7             #endregion

 1 private static void CopyBigFile(string sSource, string sTarget)
 2         {
 3             using (FileStream fsRead=new FileStream(sSource,FileMode.Open,FileAccess.Read))
 4             {
 5                 using (FileStream fsWrite=new FileStream(sTarget,FileMode.Create,FileAccess.Write))
 6                 {
 7                     //定义缓冲区
 8                     byte[] bteData = new byte[12 * 1024 * 1024];
 9                     int r = fsRead.Read(bteData, 0, bteData.Length);
10                     while (r>0)
11                     {
12                         fsWrite.Write(bteData, 0, r);
13                         double d = 100 * (fsWrite.Position / (double)fsRead.Length);
14                         Console.WriteLine("{0}%", d);
15                         r = fsRead.Read(bteData, 0, bteData.Length);
16                     }
17                     Console.WriteLine("复制大文件成功");
18                 }
19             }
20         }

说明:

快速创建文件流的方式:(不要在循环中创建文件流,放在循环外,效率问题)
     FileStream fsRead=File.OpenRead(sPath);    //快速创建读取流
     FileStream fsWrite=File.OpenWrite(sPath);         //快速创建写入流
     FileStream fs=File.Open(sPath,FileMode.OpenOrCreate);    //创建文件流

上面的3个方法只是微软对(大文件拷贝中创建文件流方法的封装,简化代码编写的方式)。

最后再来讨论文件读写乱码的问题(文件编码):

下面是常用的文本文件编码:

1.GB2312编码:兼容ASCII码表,英文字符用1个字节表示(字节用正数来表示),中文用2个字节表示(字节用负数来表示)。
     2.GBK编码:兼容GB2312编码。中文用2个字节表示(第1个字节用负数,第2个字节用紧跟其后的正数)。
     3.Unicode:国际码表,中英文都占2个字节。
     4.UTF-8:国际码表,英文占1个字节,中文占3个字节。
因为各种编码存储数据格式不一致,如果读写编码不同就会乱码,解决乱码的途径就是让读写操作时保证编码一致即可

文件编码的BOM头:

时常在读取文件时用文件的编码,有时前面会多一个问号,这是因为BOM头造成的File.ReadAllBytes().(不准确,有的编码带BOM头,有的则不带)

2.StreamReader与StreamWriter
 应用场景:在使用FileStream进行大文件拷贝的时候,因为中文占2个字节,那么有可能产生读汉字读一半的情况,进而产生乱码。
 StreamReader,逐行读取文本文件。ReadLine()、EndOfStream. 注意:指定编码!

ReadToEnd用于从当前位置一直读到最后,内容大的话会占内存;每次调用都往下走,不能无意中调用了两次.

ReadLine读取一行,如果到了末尾,则返回null.

StreamWriter,逐行写入文本文件。

WriteLine,将字符串写入文件中的当前行。

3.压缩流GZipStream:

1>压缩:

1.创建读取流File.OpenRead()

2.创建写入流File.OpenWrite();

3.创建压缩流new GZipStream();将写入流作为参数与。

4.每次通过读取流读取一部分数据,通过压缩流写入。

 1             //GZipStream就是对FileStream的又一个包装
 2             //将文本文件1.txt压缩
 3             //1.创建读取文本文件的流
 4             using (FileStream fsRead = File.OpenRead("1.txt"))
 5             {
 6                 //2.创建写入文本文件的流
 7                 using (FileStream fsWrite = File.OpenWrite("yasuo.txt"))
 8                 {
 9                     //3.创建压缩流
10                     using (GZipStream zipStream = new GZipStream(fsWrite, CompressionMode.Compress))
11                     {
12                         //4.每次读取1024byte
13                         byte[] byts = new byte[1024];
14                         int len = 0;
15                         while ((len = fsRead.Read(byts, 0, byts.Length)) > 0)
16                         {
17                             //通过压缩流写入文件
18                             zipStream.Write(byts, 0, len);
19                         }
20                     }
21                 }
22             }
23             Console.WriteLine("ok");
24             Console.ReadKey();

2>解压:

1.创建读取流:File.OpenRead()

2.创建压缩流:new GZipStream();将读取流作为参数

3.创建写入流File.OpenWrite();

4.每次通过压缩流读取数据,通过写入流写入数据。

 1  using (FileStream fsRead = File.OpenRead("yasuo.txt"))
 2             {
 3
 4                 using (GZipStream gzipStream = new GZipStream(fsRead, CompressionMode.Decompress))
 5                 {
 6                     using (FileStream fsWrite = File.OpenWrite("jieya.txt"))
 7                     {
 8
 9                         byte[] byts = new byte[1024];
10                         int len = 0;
11                         while ((len = gzipStream.Read(byts, 0, byts.Length)) > 0)
12                         {
13                             fsWrite.Write(byts, 0, len);
14                         }
15
16                     }
17                 }
18             }
19             Console.WriteLine("ok");
20             Console.ReadKey();

C# IO操作(四)大文件拷贝(文件流的使用)、文件编码,布布扣,bubuko.com

时间: 2024-10-22 16:31:21

C# IO操作(四)大文件拷贝(文件流的使用)、文件编码的相关文章

【Java】利用文件输入输出流完成把一个文件夹内的所有文件拷贝的另一的文件夹的操作

一.基本目标 使用Java完成如下的操作: 把一个文件夹内的所有文件拷贝的另一的文件夹,例如,在F盘中有a与b两个文件夹: f:/a里面有一堆文件,运行Java程序之后就会全部复制到f:/b,并且完成重命名,在所有文件之前加rename_的前缀,如果里面有文件夹,则文件夹不重命名,里面的文件进行重命名,同样在所有文件之前加rename_的前缀: 二.制作过程 1.首先主函数非常简单,就是调用了上面FileTest类中的copyFolder函数 public class FileCopy { pu

IO流,字节流复制文件,字符流+缓冲复制文件

JAVAIO如果按流向分:输入流和输出流两种 输入流的基类:InputStream   Reader 输出流的基类:OutputStream   Writer 如果按数据单元划分:字节流和字符流 字节流输入输出的基类:InputStream  OutputStream 字符流输入输出的基类:Reader   Writer 字节流复制文件内容 public static void main(String[] args) { //字节流复制文件内容 InputStream io=null; Outp

Linux学习记录--文件IO操作相关系统编程

文件IO操作相关系统编程 这里主要说两套IO操作接口,分别是: POSIX标准 read|write接口,函数定义在#include<unistd.h> ISO C标准 fread|fwrite接口,函数定义在#include<stdio.h> 有书上说POSIX标准与ISO C标准的区别在于文件读写是否带缓冲区,我则不是很认同,因此POSIX标准下的IO操作也是带缓冲区的,至于这两个标准下的IO性能谁更加好则不一定,因为这和缓冲区的大小,以及用户逻辑有很大关系. POSIX标准

大文件拷贝,试试NIO的内存映射

最近项目里有个需求需要实现文件拷贝,在java中文件拷贝流的读写,很容易就想到IO中的InputStream和OutputStream之类的,但是上网查了一下文件拷贝也是有很多种方法的,除了IO,还有NIO.Apache提供的工具类.JDK自带的文件拷贝方法 IO拷贝 public class IOFileCopy { private static final int BUFFER_SIZE = 1024; public static void copyFile(String source, S

Java IO和Java NIO在文件拷贝上的性能差异分析 (转)

1.       在JAVA传统的IO系统中,读取磁盘文件数据的过程如下: 以FileInputStream类为例,该类有一个read(byte b[])方法,byte b[]是我们要存储读取 到用户空间的缓冲区.参看read(byte b[])方法的源码,可知,它会在内部再调用readBytes(b, 0, b.length)方法,而且readBytes(b, 0, b.length)方法是一个native方法(即本地方法),最终通过这个本地方法来发起一次系统调用,即调用系统内核的read()

Java IO和Java NIO在文件拷贝上的性能差异分析

1.  在JAVA传统的IO系统中,读取磁盘文件数据的过程如下: 以FileInputStream类为例,该类有一个read(byte b[])方法,byte b[]是我们要存储读取到用户空间的缓冲区.参看read(byte b[])方法的源码,可知,它会在内部再调用readBytes(b, 0, b.length)方法,而且readBytes(b, 0, b.length)方法是一个native方法(即本地方法),最终通过这个本地方法来发起一次系统调用,即调用系统内核的read()方法,内核从

文件拷贝, 使用 BIO,NIO的对比,四种写法性能分析。

测试环境: jdk 1.7 +  2G内存 测试代码基本上复制了: http://blog.csdn.net/tabactivity/article/details/9317143 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

使用IO流实现对特殊文件及文件夹中文件拷贝到指定文件中

本程序可以实现将自己指定的文件类型的文件拷贝到自己想放的文件中,比如一个文件夹中有很多文件,那么我们想把所有的TXT文件拷贝到自己指定的文件中.(靠背笔记) package com.blueZhang; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundExcept

php--------文件夹文件拷贝和复制

php开发中常常对文件进行操作,文件夹和文件的拷贝,复制等. /** * 文件夹文件拷贝 * * @param string $src 来源文件夹 * @param string $dst 目的地文件夹 * @return bool */ function dir_copy($src = '', $dst = '') { if (empty($src) || empty($dst)) { return false; } $dir = opendir($src); dir_mkdir($dst);

利用pom配置实现静态文件拷贝

java项目有时候需要将一些静态文件拷贝到生成的test-class文件夹或者其他地方,虽然手动拷贝可以做到,但是很麻烦.今天主要讲解如何利用pom.xml进行动态的拷贝. 具体的配置信息如下,在dependencies节点后面追加build节点,用于进行资源拷贝操作: <build> <plugins> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>