Java学习第十三天 字节流

字节流的概念

在计算机中,无论文本、图片、音频还是视频,所有文件都是以二进制(字节)形式存在的。IO流中针对字节的输入输出提供了一系列的流,统称为字节流。字节流是程序中最常用的流,根据数据的传输方向可将其分为字节输入流和字节输出流。在JDK中,提供了两个抽象类InputStream和OutputStream,它们是字节流的顶级父类,所有的字节输入流都继承自InputStream,所有的字节输出流都继承自OutputStream。

InputStream被看成一个输入管道,OutputStream被看成一个输出管道,数据通过InputStream从源设备输入到程序,通过OutputStream从程序输出到目标设备,从而实现数据的传输。IO流中的输入输出都是相对于程序而言的

InputStream的常用方法

public static read()
	从此字节流中读取一个数据字节

public static read(byte[] b)
	从此输入流中将最多b.length个字节的数据读入一个byte数组中

public static read(byte[] b,int off,int len)
	指定byte数组中从偏移量off开始的len个字节读出此文件流	

os.close()
	关闭此文件输出流并释放与此流有关的所有系统资源

OutputStream的常用方法

public void write(int b)
	将指定字节写入此文件输出流

public void write(byte[] b)
	将b.length个字节从指定byte数组写入到文件输出流中去

public void write(byte[] b,int off,int len)
	指定byte数组中从偏移量off开始的len个字节写入此文件输出流		

flush() 
	刷新缓存区并强制写出所有缓冲的输出字节	

os.close()
	关闭此文件输入流并释放与此流有关的所有系统资源

InputStream和OutputStream这两个类虽然提供了一系列的读写数据有关的方法,但是这两个类是抽象类,不能被实例化,因此,针对不同的功能,InputStream和OutputStream提供了两个不同的子类,这些子类形成了一个体系结构

字节流读写文件

由于计算机中的数据基本都保存在硬盘的文件中,因此操作文件中的数据时一种很常见的操作。在操作文件时,最常见的就是从文件中读取数据并将数据写入文件,即文件的读写。针对文件的读写,JDK专门提供了两个类,分别是FileInputStream和FileOutputStream。

FileInputStream是InputStream的子类,它是操作文件的字节输入流,专门用于读取文件中的数据。由于从文件中读取数据时重复性的操作,因此需要通过循环语句来实现数据的持续读取。

接下来通过一个安妮来实现字节流对文件数据的读取

public class Example01 {
	public static void main(String[] args) throws Exception {
		//创镌一个文件字节输入流对象
		FileInputStream in = new FileInputStream("test.txt");
		int b=0;			//定义一个int类型的变量b,记住每次读取的一个字节
		while(true) {
			b=in.read();	//变量b记住读取的一个字节
			if(b==-1) {		//如果读取的字节为-1,跳出while循环
				break;
			}
			System.out.println(b);	//否则将b输出
		}
	}
}

与FileInputStream对应的是FileOutputStream。FileOutputStream是OutputStream的子类,他是操作文件的字节输出流,专门把输入写入文件。

接下来通过一个案例来演示如何将数据写入文件

public class Example02 {
	public static void main(String[] args) throws IOException {
		FileOutputStream out = new FileOutputStream("example.txt");
		String str="波音飞机";
		byte[] b = str.getBytes();
		for (int i = 0; i < b.length; i++) {
			out.write(b[i]);
		}
		out.close();
	}
}

需要注意的是,如果是通过FileOutputStream向一个已经存在的文件中写入数据,那么该文件中的数据首先会被情况,再写入数据。若希望在已存在的文件内容之后追加新内容,则可使用FileOutputStrem的构造函数FileOutputStream(String file, boolean append)来创建文件输出流对象,并把append参数的值设置为true。

接下来通过一个案例来演示如何将数据追加到文件末尾

public class Example01 {
	public static void main(String[] args) throws Exception {
		//创镌一个文件字节输入流对象
		FileInputStream in = new FileInputStream("test.txt");
		int b=0;			//定义一个int类型的变量b,记住每次读取的一个字节
		while(true) {
			b=in.read();	//变量b记住读取的一个字节
			if(b==-1) {		//如果读取的字节为-1,跳出while循环
				break;
			}
			System.out.println(b);	//否则将b输出
		}
	}
}

由于IO流在进行数据读写操作时会出现异常,为了代码的简洁,在上面的程序中使用了throws关键字将异常抛出。然而一遇到IO异常,IO流的close()方法将无法得到执行,流对象所占用的系统资源将得不到释放,因此,为了保证IO流的close()方法必须执行,通常将关闭流的操作写在finally代码块中

finally{
	try{
		if(in!=null){
			in.close;
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}
文件的拷贝

在应用程序中,IO流通常都是成对出现的,即输入流和输出流一起使用。例如文件的拷贝就需要通过输入流来读取文件中的数据,通过文件输出流写入文件。

接下来通过一个案例来演示如何进行文件内容的拷贝

public class Example01 {
	public static void main(String[] args) throws Exception {
		//创建一个字节输入流,用于读取当前目录下sourse文件夹中的map3文件
		FileInputStream in = new FileInputStream("sourse\\周深 - 大鱼.mp3");
		
		//创建一个字节输出流,用于把读取的字节写入到target目录下的文件中
		FileOutputStream out = new FileOutputStream("target\\周深 - 大鱼.mp3");

		int len;	//定义一个整型类型的变量len,记住每次读取的一个字节
		long starttime = System.currentTimeMillis(); 		//获取拷贝文件前的系统时间
		while((len=in.read())!=-1) {
			out.write(len);  	//将读到的字节写入文件
		}
		long endtime = System.currentTimeMillis();
		System.out.println("拷贝时间: "+(endtime-starttime)+"毫秒");
		in.close();
		out.close();
	}
}
字节流的缓冲区

在拷贝文件时,可以一次性读取多个字节的数据,并保存在字节数组中,然后将字节而数组中的数据一次性写入文件。

接下来通过修改文件来学习如何使用缓冲区拷贝文件

public class Example02 {
	public static void main(String[] args) throws Exception {
		//创建一个文件输入流,用于读取当前目录下sourse目录下的mp3文件
		FileInputStream in = new FileInputStream("sourse\\周深 - 大鱼.mp3");
		
		//创建一个文件输出流,用于将读取的数据写入当前目录下的target文件中
		FileOutputStream out = new FileOutputStream("target\\周深 - 大鱼.mp3");
		
		//以下是用缓冲区读写文件
		byte[] buff = new byte[1024];	//定义一个字节数组,作为缓冲区
		
		int len;
		long startTime = System.currentTimeMillis();
		while((len=in.read(buff))!=-1) {	//判断是否读到文件末尾
			out.write(buff, 0, len);	//从第一个字节开始,想文件写入len个字符
		}
		long endTime = System.currentTimeMillis();
		System.out.println("拷贝文件所用的时间:"+(endTime-startTime));
		in.close();
		out.close();
	}
}

在拷贝过程中,使用while循环逐渐实现字节文件的拷贝,每循环一次,就从文件读取若干字节填充字节数组,并通过变量len记住读入数组的字节数,然后从数组的第一个字节开始,将len个字节一次写入文件。循环往复,当len值为-1时,说明已经读到了文件的末尾,循环会结束,整个拷贝过程也就结束了。
程序中的缓冲区就是一块内存,该内存主要用于存放暂时输入输出的数据,由于使用缓冲区减少了对文件的操作次数,所有可以提高读写数据的效率。

字节缓冲流

在IO包中提供两个带缓冲的字节流,分别是BufferedInputStream和BufferedOutputStream,它们的构造方法中分别接收InputStream和OutputStream类型的参数作为对象,在读写数据时提供缓冲功能。

接下来通过一个案例来学习BufferedInputStream和BufferedOutputStream这两个流的用法

public class Example03 {
	public static void main(String[] args) throws Exception {
		//创建一个带缓冲区的输入流
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream("src.txt"));
	
		//创建一个带缓冲区的输出流
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("des.txt"));
		int len;
		while((len=bis.read())!=-1){
			bos.write(len);
		}
		bis.close();
		bos.close();
	}
}

当调用了read()或者write()方法读写数据时,首先将读写的数据存入定义好了的字节数组,然后将字节数组一次性写入到文件中。从而提高了数据的读写效率

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值