Java流,
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接口。
相关文章
- 暂无相关文章
用户点评