Java流

概念

在Java程序中,对于数据的输入、输出操作都是以"流(Stream)"的方式进行的。
Java提供了各种"流"类,用以处理各种不同种类的数据。程序中通过标准的方法输入或输出数据。
java.io包中定义了多个流类型(类或抽象类)来实现输入、输出功能。
可从不同的角度对流进行分类,主要从三方面:
一方面,从流向分,可分为输入流和输出流。
输入流和输出流通常是对程序来说的,输入流指的是从硬盘等其他地方往程序中读数据,读到的数据放在为程序分配的内存中,可通过System.out.print打印到控制台。输出流指的是从程序中往其他地方输出数据,如对象的序列化,就是将程序中的对象保存到硬盘上。
另一方面,按照处理数据单位的不同可以分为字节流和字符流。Java当中一个字符等于两个字节,中文占两个字节,读取中文就必须使用字符流。
最后,按照功能的不同可以分为节点流和处理流。
节点流是可以从一个特定的数据源(节点)读写数据(如文件,内存),也就是普通的流。如FileInputStream表示文件字节输入流,从硬盘文件中逐个字节地往程序中读数据。
处理流是套接在已经存在的流(可以是节点流或其他处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。如new BufferedOutputStream(new FileOutputStream)就是在一个文件字节输出流上面套接一层缓冲流,待缓冲区中满了之后一并将数据写到文件中,减少硬盘的操作次数。

Java提供的所有位于包java.io内的流类型都分别继承自以下四种抽象流类型:
在这里插入图片描述

节点流类型

在这里插入图片描述
实例
以文件输入输出流为例,简单介绍一下从文件中往程序中读数据和从程序中往文件写数据。
文件字节输入流

//文件字节输入流
public class FileInputStreamTest {
	public static void main(String[] args) {
		int b = 0;
		FileInputStream fis = null;
		try {
			fis = new FileInputStream("D:\\Program\\IoTest.java");
		} catch (FileNotFoundException e) {
			System.out.println("找不到指定文件!");
			//系统退出
			System.exit(-1);
		}
		try {
			//记录读取的字节数
			long num = 0;
			while((b = fis.read()) != -1) {
				//将整形数据强制转换为char类型
				System.out.print((char)b);
				num++;
			}
			//关闭流
			fis.close();
			System.out.println();
			System.out.println("共读取了:" + num + "个字节");
		} catch (IOException e1) {
			System.out.println("文件读取错误!");
			System.exit(-1);
		}
	}
}

系统文件内容
在这里插入图片描述
输出结果
在这里插入图片描述
注:InputStream的read方法一次读取一个字节并以整数的形式返回(0~255),若返回-1表示已到输入流的末尾。

文件字符输入流
若文件中包含中文字符,如

在这里插入图片描述

重新运行该测试程序,则输出为
在这里插入图片描述

可以发现,中文的字符乱码了。这时,就需要用FileReader类来读取:

FileReader fr = null;
try {
	fr = new FileReader(D:\\Program\\IoTest.java);
} catch (FileNotFoundException e) {
	...
	//其他都与上个例子的代码一样
}

输出结果
在这里插入图片描述
注:使用FileReader可以读取文件中的中文字符,但文件的编码必须与Java程序中的编码一致,否则还是会乱码。通常,中文的Windows系统下创建的文件默认编码为GBK,而Java程序中一般会设置成UTF8.
若编码不一致,可以使用InputStreamReader转换流来将字节数据转换成字符数据,构造的时候指定其编码与文件编码一致就可以了。
InputStreamReader isr = new InputStreamReader(new FileInputStream(“xxx”),“GBK”);
文件字节输出流

//文件字节输出流
public class FileOutputStreamTest {
	public static void main(String[] args) {
		FileOutputStream fos = null;
		byte[] b = {'H','e','l','l','o'};
		try {
			fos = new FileOutputStream("D:\\Program\\IoTest.java");
			fos.write(b);
		} catch (FileNotFoundException e) {
			System.out.println("找不到指定文件!");
			System.exit(-1);
		} catch (IOException e) {
			System.out.println("文件写入失败!");
			System.exit(-1);
		}
		System.out.println("文件写入成功!");
	}
}

输出结果
在这里插入图片描述
文件
在这里插入图片描述

处理流类型

在这里插入图片描述
常见的处理流如缓冲流,缓冲流要套接在相应的节点流之上,对读写数据提供了缓冲的功能,提高了读写效率,减少了访问硬盘的次数,同时增加了一些新的方法。
实例

//缓冲文件输入流
public class BufferedReaderTest {
	public static void main(String[] args) {
		try {
			BufferedReader br = new BufferedReader(new FileReader("D:\\Program\\IoTest.java"));
			//读取一行数据,并以字符串形式返回
			String s = br.readLine();
			System.out.println(s);
		} catch (FileNotFoundException e) {
			System.out.println("找不到文件!");
			System.exit(-1);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

文件
在这里插入图片描述
输出结果
在这里插入图片描述
BufferedReader的readLine方法是读取一行数据,返回包含改行内容的字符串,不包含任何行终止符,若已到达流末尾,则返回null.
缓冲流是加了一块缓冲区,当从硬盘文件中读数据或往硬盘文件中写数据时,先将数据保存到缓冲区,当缓冲区满了后,再一并将数据取出或是写入。如此,在很大程度上减少了硬盘的读写次数。
在输出流外面套接缓冲流时,在关闭流之前一般应手动调用flush方法,先将缓冲区中的数据全部写入到硬盘,再关闭流。因为缓冲区中的数据一般是待缓冲区满了之后再往硬盘中写入。

转换流

InputStreamReader和OutputStreamWriter用于字节数据到字符数据之间的转换。
InputStreamReader需要和InputStream套接,OutputStreamWriter需要和OutputStream套接。
转换流在构造时可指定其编码集合,如
InputStreamReader isr = new InputStreamReader(System.in,“ISO8859-1”);
转换流声明方式
InputStreamReader isr = new InputStreamReader(new FileInputStream(“xxx”));
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“xxx”));
实例

public class InputStreamReaderTest {
	public static void main(String[] args) {
		int b = 0;
		FileInputStream fis = null;
		InputStreamReader isr = null;
		try {
			fis = new FileInputStream("D:\\Program\\InputStreamReaderTest.txt");
			isr = new InputStream(fis,"GBK");
			while((b = isr.read()) != -1) {
				System.out.print((char)b);
			}
		} catch (FileNotFoundException e) {
			System.out.println("未找到指定文件!");、
			System.exit(-1);
		} catch (IOException e1) {
			e.printStackTrace();
		}
	}
}

文件
在这里插入图片描述
输入内容
在这里插入图片描述
注:可以在构造InputStreamReader的时候在第二个参数位置指定与文件相同的编码。这往往非常有用,当文件编码与程序编码不一致的时候,中文往往会乱码,这用FileReader又解决不了。

其他流

数据流

DataInputStream和DataOutputStream分别继承自InputStream和OutputStream,它属于处理流,需分别套接在InputStream和OutputStream类型的节点流上。
数据流提供了可以存取与机器无关的Java原始类型数据(如int,Double等)的构造方法。
构造方法为
DataInputStream(InputStream is);
DataOutputStream(OutputStream os).

Print流

PrintStream和PrintWriter都属于输出流,分别针对于字节和字符串。
它们都提供了重载的print、println方法用于多种数据类型的输出。
PrintStream和PrintWriter的输出操作不会抛出异常,用户通过检测错误状态获取错误信息。
此两者有自动flush的功能。如System.out.println方法就不需要手动调用flush方法。
Object流
直接将Object写入或读出。
一般用于对象序列化。
其中,对象当中被transient关键字修饰的成员不会被序列化。
要被序列化的对象,其类需实现serializable接口或externalizable接口。
实现serializable接口,序列化过程由JVM自动实现;实现externalizable接口,序列化过程必须自定义。一般,对象序列化都是实现serializable接口。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值