JavaIO之字节流与字符流

在我的博客:JavaIO之File类 中介绍了关于File类,该类用于处理文件本身(如:创建文件、删除文件等),并不能对文件的内容进行处理。如果要处理文件的内容,必须要通过流的操作来完成,在java.io包中流含有字节流和字符流。而字节流或字符流中又分为输入流和输出流。下面详细介绍字节流和字符流。

1. 字节流

字节流是由字节组成的,主要处理二进制数据,它的操作是原生的。字节流的操作步骤主要分为4步(以处理文件为例):

(1)根据文件路径创建File类对象

(2)根据字节流的子类实例化父类对象

(3)进行数据的读取、写入等操作

(4)关闭流(close())

1.1 字节输出流:OutputStream

如果想要通过程序进行内容的输出操作,则可以使用java.io.OutputStream类。下面观察OutputStream类的部分源码:

public abstract class OutputStream implements Closeable, Flushable 

(1)由于OutputStream类是一个抽象方法,所以要想实例化其对象,必须要使用其子类。如果要对文件进行处理,可以使用FileOutputStream类。FileOutputStream类中的某两个构造方法:

①接收File类(覆盖文件内容):

public FileOutputStream(File file) throws FileNotFoundException

②接收File类(追加文件内容):

public FileOutputStream(File file, boolean append)

(2)OutputStream类实现了Closeable和Flushable接口,这两个接口中的只含有如下方法:

Closeable接口中的close()方法:

public void close() throws IOException;

Flushable接口中的flush()方法:

void flush() throws IOException;

(3)在OutputStream类中除了覆写了以上两个方法外,还有其他方法:

①将给定的字节数组内容全部输出:

    public void write(byte b[]) throws IOException

②将部分字节数组内容输出:

    public void write(byte b[], int off, int len) throws IOException 

③输出单个字节:

    public abstract void write(int b) throws IOException;

1.2 实现将字符串输出到文件中:

package www.bit.java.test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

public class Test1 {
	public static void main(String[] args) throws Exception {
		//实现将字符串输出到文件中
		//1.创建File类的实例化对象
		File file=new File("C:"+File.separator+"Users"+File.separator+
				"Administrator"+File.separator+"Desktop"+File.separator+"File.txt");
		if(!file.getParentFile().exists()) {
			file.getParentFile().mkdirs();
		}
		//2.由于OutputStream类是一个抽象类,需要通过其子类实例化对象
		OutputStream output=new FileOutputStream(file);
		//3.进行数据的输出操作,即将数据写入到文件中
		String string="将数据输出到文件中";
		//由于write()方法接收的是字节数组,故将字符串转为字节数组再写入
		output.write(string.getBytes());
		//4.关闭流
		output.close();
	}
}
需要注意的是:文件输出流FileOutputStream类默认为覆盖文件原有内容的操作,若不想覆盖原有内容,只是将内容进行追加的话,实例化OutputStream类对象不再使用FileOutputStream(File file)而是使用FileOutputStream(File file,boolean append),并且将append值置为false表示覆盖内容,将append值置为true表示追加内容。

1.3 自动关闭流与手动关闭流

在之前的操作中,我们使用Closeable接口中的close()方法手动关闭流,而在JDK1.7以后追加了AutoCloseable接口,这个接口的主要目的是自动进行流的关闭处理,但是存在一个麻烦的步骤就是它必须结合try...catch。

修改之前的将字符串输出到文件中的操作,使用AutoCloaseable接口实现自动关闭流操作。下面观察AutoCloseable接口的使用:

package www.bit.java.test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

public class Test1 {
	public static void main(String[] args) throws Exception {
		File file=new File("C:"+File.separator+"Users"+File.separator+
				"Administrator"+File.separator+"Desktop"+File.separator+"File.txt");
		if(!file.getParentFile().exists()) {
			file.getParentFile().mkdirs();
		}
		//使用AutoCloseable接口实现自动关闭流,但流的实例化对象必须定义在try块中
		try(OutputStream output=new FileOutputStream(file,true)){
			String string="将数据输出到文件中";
			output.write(string.getBytes());
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
}

1.4 字节输入流:InputStream

利用OutputStream类实现了程序内容输出到文件的操作,下面使用InputStream类实现在程序中读取文件内容的操作。下面关于InputStream类的部分源码如下:

public abstract class InputStream implements Closeable 

观察发现InputStream类实现了Closeable接口,在InputStream类中含有如下方法:

(1)读取数据到字节数组中,返回数据的读取个数。

    public int read(byte b[]) throws IOException

需要注意的是其返回值的大小:

①如果开辟的字节数组的大小大于读取的数据的大小,则返回读取的数据的大小

②如果开辟的字节数组的大小小于读取的数据的大小,则返回字节数组的大小

③如果流中没有数据但还在读取时,返回-1

(2)读取部分数据到字节数组中,每次只读取数组的部分内容,返回数据的读取个数。

    public int read(byte b[], int off, int len) throws IOException 
该方法与read(byte b[])类似,返回的个数为:

①如果读取到数组指定长度的内容,则返回数组指定长度len

②如果没有读取到数组指定长度的内容,则返回读取的个数

③如果流中没有数据但还在读取时,返回-1

(3)读取单个字节,每次读取一个字节的内容,直到没有数据了返回-1

    public abstract int read() throws IOException;

1.5 实现文件内容到程序中的读取操作

同OutputStream类的使用一样,由于InputStream类是一个抽象类,如果要对其实例化对象,需要使用其子类。若处理的是文件,则使用FileInputStream类进行实例化对象。

package www.bit.java.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

public class Test1 {
	public static void main(String[] args) throws Exception {
		//1.实例化File类对象
		File file=new File("C:"+File.separator+"Users"+File.separator+
				"Administrator"+File.separator+"Desktop"+File.separator+"File.txt");	
		//对文件进行读取操作,必须保证该文件存在
		if(file.exists()) {
			//2.由于InputStream类是抽象类,故用其子类FileInputStream类对其实例化对象
			InputStream input =new FileInputStream(file);
			//3.对文件进行读取操作
			byte[] data=new byte[1024];
			int len=input.read(data);
			String string=new String(data,0,len);
			System.out.println("从文件中读取的内容为:"+string);
			//4.关闭流
			input.close();
		}
	}
}

运行结果为:

从文件中读取的内容为:将数据输出到文件中

2. 字符流

字符流是由字符组成的,主要处理中文数据,它的操作是是经过处理的。字符流的操作步骤与字节流的操作步骤相同,也分为4步(以处理文件为例):

(1)根据文件路径创建File类对象

(2)根据字符流的子类实例化父类对象

(3)进行数据的读取、写入等操作

(4)关闭流(close())

2.1 字符输出流:Writer

关于Writer类的部分源代码如下:

public abstract class Writer implements Appendable, Closeable, Flushable 

(1)与OutputStream类相比,它多实现了一个Appendable接口。在Writer类中也提供了write()方法,但需要注意的是Writer类中提供了一个直接接收字符串的方法:

    public void write(String str) throws IOException

(2)观察Writer类的定义可以看出,该类是抽象类,要想实例化Writer类对象,就需要其子类去实例化对象。如果要操作文件的话,需要FileWriter子类去实例化对象。

2.2 通过Writer类实现程序到文件的输出操作

package www.bit.java.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.Writer;

public class Test1 {
	public static void main(String[] args) throws Exception {
		//1.实例化File类对象
		File file=new File("C:"+File.separator+"Users"+File.separator+
				"Administrator"+File.separator+"Desktop"+File.separator+"File.txt");	
		//必须保证文件的父目录都存在
		if(!file.getParentFile().exists()) {
			file.getParentFile().mkdirs();
		}
		//2.由于Writer类是抽象类,故用其子类FileWriter类对其实例化对象
		Writer writer =new FileWriter(file);
		//3.对文件进行操作
		String string="将程序内容输出到文件中";
		writer.write(string);
		//4.关闭流
		writer.close();
	}
}

需要注意Writer类与OutputStream类的一点区别:

(1)Writer类会把数据先放在缓冲区,如果操作结束没有关闭流,则不会将数据写入到目标终端。此时,要想把数据写入到目标终端,可以有两个方法:①调用close()从而关闭流;②调用flush()从而强制清空缓冲区。

(2)OutputStream类即使没有关闭流也会将内容写入到目标终端。

2.3 字符输入流:Reader

先来观察Reader类的部分源代码:

public abstract class Reader implements Readable, Closeable 

(1)Reader类依然是一个抽象类,要想实例化其对象就需要其子类实例化对象。如果要操作的是文件,则使用FileReader子类实例化对象。

(2)Writer类中提供了一个可以直接向目标终端写入字符串的方法,但Reader类没有该类型方法,故也只能通过字符数组进行操作。

2.4 通过Reader类实现文件到程序的读取操作

package www.bit.java.test;

import java.io.File;
import java.io.FileReader;
import java.io.Reader;

public class Test1 {
	public static void main(String[] args) throws Exception {
		//1.实例化File类对象
		File file=new File("C:"+File.separator+"Users"+File.separator+
				"Administrator"+File.separator+"Desktop"+File.separator+"File.txt");	
		//必须保证文件存在才可以进行读取操作
		if(file.exists()) {
			//2.由于Reader类是抽象类,故用其子类FileReader类对其实例化对象
			Reader reader =new FileReader(file);
			//3.对文件进行读取操作
			char[] data=new char[1024];
			int len=reader.read(data);
			String string=new String(data,0,len);
			System.out.println("从文件中读取的内容为:"+string);
			//4.关闭流
			reader.close();
		}
	}
}

运行结果为:

从文件中读取的内容为:将程序内容输出到文件中

总结字节流和字符流的使用范围:

进行IO处理时,如果处理的是图片、音乐、文字都可以使用字节流;只有在处理中文的时候才使用字符流。






猜你喜欢

转载自blog.csdn.net/tongxuexie/article/details/80461852
今日推荐