`
java--hhf
  • 浏览: 305404 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

文件读出和写入两种基本方法

阅读更多

             文件读出和写入两种基本方法

  首先,我们的目的是:通过java源代码的运行将文件从一个地方复制到另外一个地方。只需要两步就可以了——将文件读出来,将读出来的内容保存到新建的一个文件夹内。

  现在介绍两种最基本的方法——字节流InputStream和缓冲流BufferedInputStream。第一种是将磁盘中文件的内容一个一个字节的读出写入;后一种则是将文件一段一段的读出写入。在创建 BufferedInputStream 时,会相应的创建一个内部缓冲区数组在java虚拟机内存中,因此每次处理的就是这一整块内存。

  我们先用InputStream来实现这一功能,然后再用BufferedInputStream 实现,最后比较这两者的优劣。

 

/**
	 * 读取指定文件内容
	 * 
	 * @param fileName被复制文件名
	 * @return 将读取到的内容作为String类型返回
	 * @throws IOException
	 *             文件操作异常
	 */
	private String readFileString(String fileName)
			throws IOException {
		// java.io.InputStream抽象类是表示字节输入流的所有类的超类,java.io.FileInputStream是它的一个实现类
		// 定义这样的输入流对象,来进行文件操作
		java.io.InputStream ins = new java.io.FileInputStream(fileName);
		// 也可以这样(多个构造方法)
		// java.io.InputStream ins1 = new java.io.FileInputStream(new
		// File(fileName));
		// 根据ins中的字节长度 创建一个byte数组保存读出的数据
		byte[] contentByte = new byte[ins.available()];
		// 对contentByte数组赋值
		// 读入就是把文件中的东西读出后读入到另一个东西里去
		ins.read(contentByte);
		//方法二
//		while (true) {
//			int i = ins.read();
//			if(i == -1)
//				break;
//	
//		}
		// 把contentByte转变为String类型
		String s = new String(contentByte);
		//关闭文件流
		ins.close();
		System.out.println("InputStream使用结束,文件已被读出");
		return s;
	}

  下一步就是创建一个新的文件,然后将刚刚获得的返回值写入进去便可了。

/**
	 * contentString 文件的内容
	 * @param path新路径名 
	 * @throws IOException
	 *             文件操作异常
	 */
	private void whiteFile_OutputStream(String contentString, String path)
			throws IOException {
		// 定义输出流对象,来进行文件操作
		java.io.OutputStream os = new java.io.FileOutputStream(path);
		// 对contentByte数组赋值
		byte[] contentByte = contentString.getBytes();
		//写入path中
		os.write(contentByte);
		os.close();
		System.out.println("OutputStream结束,文件已被复制");
	}

 这样的话filename里面的文件就被复制到了path里面。

     下面我们再看一下如果是BufferedInputStream 会怎么样。

/**
	 * 复制指定文件内容
	 * @param path新文件的路径
	 * @param fileName
	 * 
	 * @throws IOException
	 *             文件操作异常
	 */
	private void copyBuffered(String fileName, String path)
			throws IOException {//还是需要先 定义InputStream输入流对象	
		java.io.InputStream ins = new java.io.FileInputStream(fileName);
		// 创建一个BufferedInputStream对象时 需要用InputStream作为输入
		java.io.BufferedInputStream bis = new java.io.BufferedInputStream(ins);
		// 文件复制中的输出流
		java.io.OutputStream os = new java.io.FileOutputStream(path);
		java.io.BufferedOutputStream bos = new java.io.BufferedOutputStream(os);
		// 根据ins中的字节长度 创建一个byte数组保存读出的数据
		byte[] contentByte = new byte[bis.available()];
		// 对contentByte数组赋值
		// 读入就是把文件中的东西读出后读入到另一个东西里去
	           bis.read(contentByte);
		bos.write(contentByte);
//方法二		while (true) {
//			int i = bis.read();
//			if (i == -1) {
//				break;
//			}
//			bos.write(i);
//		}
		System.out.println("BufferedInputStream拷贝结束");
		bos.flush();// 将缓冲区中的内容强制全部写入到文件中(不管是否已经全部写入)有点类似于下面的语句
		// bos.close();
		// bis.close();
		// os.close();
		// ins.close();
		
	}

 

   读者将会发现其实并没有多少区别。

   只能说,形式的确是如此。但程序运行时内部的处理是不同的,这体现为后者的读取复制速度远远快于前者。

 

2
2
分享到:
评论
8 楼 canghailan 2012-12-17  
yonge812 写道
canghailan 写道
FileChannel.transferTo
,其实这个更方便,性能可能更好。

http://yonge812.iteye.com/blog/1747393这是我做的测试,并没有体现他的高性能。

性能可能更好更多地体现在CPU与内存使用上。
传统拷贝方式:源文件块=>操作系统文件缓存=>JVM缓冲区=>操作系统文件缓存=>目标文件块。
而NIO省掉了 操作系统文件缓存=>JVM缓冲区=>操作系统文件缓存 这个过程。
对于常规的磁盘IO来说,内存中内容拷贝所消耗的时间可以忽略。
操作系统可能会使用DMA等来节省系统资源,所以transferTo可能性能(CPU,内存)更好,但也要看具体实现。
测试第一次比其他几次耗时长应该是操作系统文件缓存的原因。
7 楼 sc_zcx 2012-12-15  
学习了。。。。
6 楼 java--hhf 2012-12-14  
byte[] contentByte = new byte[1024];
OutputStream os = new FileOutputStream("fileName");
while(true){
   int ret = bis.read(contentByte);
   if (ret > 0) {
	os.write(buf, 0, ret);
   } else if (-1 == ret) {
	break;
   }
}
os.close();  


这个代码写的不错^_^ 谢谢啦
5 楼 java--hhf 2012-12-14  
FileChannel.transferTo  这个 具体咋用呢?? API貌似不好懂
4 楼 yonge812 2012-12-14  
canghailan 写道
FileChannel.transferTo
,其实这个更方便,性能可能更好。

http://yonge812.iteye.com/blog/1747393这是我做的测试,并没有体现他的高性能。
3 楼 xiaoZ5919 2012-12-14  
crazywen2011 写道
byte[] contentByte = new byte[bis.available()];  
        // 对contentByte数组赋值  
        // 读入就是把文件中的东西读出后读入到另一个东西里去  
               bis.read(contentByte);  
        bos.write(contentByte);  
//方法二       while (true) {  
//          int i = bis.read();  
//          if (i == -1) {  
//              break;  
//          }  
//          bos.write(i);  
//      }  

对于这种做法并不赞成,小文件还可以用用,文件很大的话,会造成内存溢出的哦。
byte[] contentByte = new byte[1024];
OutputStream os = new FileOutputStream("fileName");
while(true){
   int ret = bis.read(contentByte);
   if (ret > 0) {
	os.write(buf, 0, ret);
   } else if (-1 == ret) {
	break;
   }
}
os.close();  

个人更赞成这样的写法

还是1楼说的fileChannel.transferTo吧其实两个文件的读写,没有必要字节数组copy到jvm的内存中。利用fileChannel在内核态搞定避免了四次copy
2 楼 crazywen2011 2012-12-14  
byte[] contentByte = new byte[bis.available()];  
        // 对contentByte数组赋值  
        // 读入就是把文件中的东西读出后读入到另一个东西里去  
               bis.read(contentByte);  
        bos.write(contentByte);  
//方法二       while (true) {  
//          int i = bis.read();  
//          if (i == -1) {  
//              break;  
//          }  
//          bos.write(i);  
//      }  

对于这种做法并不赞成,小文件还可以用用,文件很大的话,会造成内存溢出的哦。
byte[] contentByte = new byte[1024];
OutputStream os = new FileOutputStream("fileName");
while(true){
   int ret = bis.read(contentByte);
   if (ret > 0) {
	os.write(buf, 0, ret);
   } else if (-1 == ret) {
	break;
   }
}
os.close();  

个人更赞成这样的写法
1 楼 canghailan 2012-12-14  
FileChannel.transferTo
,其实这个更方便,性能可能更好。

相关推荐

    文件系统的用户界面

    (一)实验目的 <br> 进一步理解、使用和掌握文件的系统调用、文件的标准子例程,能利用和选择这些基本的文件操作完成复杂的文件处理工作。 (二)实验题目 1.编写一个文件复制的C语言程序: 分别...

    操作系统的第二次实验相关ppt

    管道是Linux支持的最初进程间通信形式之一,具有以下特点: 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个... 数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。

    C语言程序设计标准教程

    从用户的角度看,文件可分为普通文件和设备文件两种。  普通文件是指驻留在磁盘或其它外部介质上的一个有序数据集,可以是源文件、目标文件、可执行程序; 也可以是一组待输入处理的原始数据,或者是一组输出的...

    文件快速复制工具FastCopy.rar

    由于Windows默认的缓存太小,导致读取和转移这两过程基本都是同时进行,很容易出现瓶颈,致使“Windows复制文件快不起来”。而第三方文件复制软件会开辟一块更大的缓存空间,并把设置权重新交给用户。

    13.第十三章 文件.txt

    (2)用r方式打开文件时文件必须存在,只能从该文件读出。 (3)用w方式打开只能向文件写入。若打开的文件不存在,则以指定的文件名建立新文件。若存在,则将存在的文件删除,重建新文件。 (4)向一个已存在的...

    FastCopy 数据高速完整拷贝(复制)自动效验比对工具

    硬盘模式的设置是为了在读写时对缓存的操作方式,默认下为自动硬盘模式,另外两种分别是相同硬盘模式、不同硬盘模式,可以根自己机器的配置来选择。相同硬盘模式是指用大的缓存进行读入,直到缓存满额,再转入大缓存...

    河南科技大学C语言综合作业答案

    1.程序可使用模块化和非模块化两种形式 2.编写提示: a. 定义最高成绩变量,使用r方式打开stuin.dat,使用fscanf读出成绩并求出最高成绩,以只写方式打开stuout.dat文件,循环判断,若成绩等于最高成绩,则打印该生...

    API之网络函数---整理网络函数及功能

    ReadFile 从文件中读出数据 ReadFileEx 与ReadFile相似,只是它只能用于异步读操作,并包含了一个完整的回调 RegCloseKey 关闭系统注册表中的一个项(或键) RegConnectRegistry 访问远程系统的部分注册表 ...

    会计理论考试题

    23.如果要把C盘某个文件夹中的一些文件复制到C盘的另外一个文件央中,在选定文件后,若采用拖放操作,可以用___B___目标的方法。 A、直接拖至 B、Ctrl十拖至 C、Alt十拖至 D、单击 24.Windows98中的磁盘的根文件夹是...

    VB程序设计综合复习题

    (2)打开一个老的顺序文件SEQOLD.DAT,用户将从该文件读出数据,指定文件号为2。 (3)打开一个老的顺序文件SEQAPPEND.DAT,用户将在该文件后面添加数据,文件号通过调用FreeFile函数获得。 15、请写出程序代码片段...

    基于FPGA的CNN图像分类系统【100011968】

    神经网络的权重预先在电脑上训练好,转为二进制文件后通过 Quartus 写入片内。 图像输入通过 SD 卡实现。我们预先使用读卡器在 SD 卡写入图像,然后在将 SD 卡插入板上进行图像读写。图像的展示使用 VGA 实现。由于...

    计算机应用基础知识点总结.doc

    第二代:晶体管计算机 采用晶体管为基本元件,程序设计采用高级语言,出现了操作系统,应用到数据和事物处理 及工业控制等领域 第三代:中小规模集成电路计算机 采用集成电路为基本元件,应用到文字处理、企业管理和自动...

    极品快速复制工具FastCopy2.01中文绿色版(170K)

    硬盘模式的设置是为了在读写时对缓存的操作方式,默认下为自动硬盘模式,另外两种分别是相同硬盘模式、不同硬盘模式,可以根自己机器的配置来选择。相同硬盘模式是指用大的缓存进行读入,直到缓存满额,再转入大...

    Java高级程序设计实战教程第五章-Java序列化机制.pptx

    比较常见的做法有两种: 一是把对象包装成JSON字符串传输, 二是采用Java对象的序列化和反序列化。 随着Google工具protoBuf的开源,protobuf也是个不错的选择。 *提示:对JSON,Object Serialize,ProtoBuf 做个对比。...

    php下把数组保存为文件格式的实例应用

    我使用过两种办法: 第一种是数组序列化,简单,但是调用时比较麻烦一些;第二种是保存为标准的数组格式,保存时麻烦但是调用时简单。 第一种方法: PHP代码 复制代码 代码如下: $file=”./cache/file.cache”; $...

    最新软件狗时间复制工具

    目前市场上的加密锁大致分为两种类型:带CPU加密锁,不带CPU的加密锁。前者拥有计算能力,对加密数据、过程数据、通讯接口等可以实施动态密文处理,因此带CPU的加密锁也被演化出了多种多样的加密形式:密文校验、...

    linux编程之pipe()函数详解

    管道是一种把两个进程之间的标准输入和标准输出连接起来的机制,从而提供一种让多个进程间通信的方法,当进程创建管道时,每次都需要提供两个文件描述符来操作管道。其中一个对管道进行写操作,另一个对管道进行读...

    计算机基础总结.docx

    1B=8b.............(3)存储容量的换算:B、KB、MB、GB、TB,各单位之间为1024倍 (4)美国标准信息交换码(ASCII码)有7位码和8位码两种形式;国际通用的是......7. 位码,可表示128个不同...

Global site tag (gtag.js) - Google Analytics