·字节操作(InputStream、OutputStream)
·字符操作(Writer、Reader)
`磁盘操作
·控制台操作
·网络操作 socket (此类不在java.io包下面)
影响IO操作的要么是传输的数据格式(字符、字节),要么就是传输介质(磁盘、控制台、网络),java.io有很多jar包来解决这个问题。
1、输入流
java io类库可以分为输入流和输出流,输入流来读数据,输出流来写数据;输入流中分字节流的InputStream和字符流的Reader;输出流分字节流的OutputStream和字符流的Writer;InputStream是字节输入流的超类,她的衍生子类都有read()方法,可读一个字节或者字节数组, 但是read()方法只负责读数据
OutputStream的衍生子类都有write()方法,用来写一个字节或者字节数组;
但是我们一般不来调用这个方法,因为一般我们需要流的时候,并不是简单的用一个类创建一个对象,而是组合多个对象形成一个流,这就是为什么java.io中流比较复杂的原因。
那么输入流读数据一般从哪里读呢?数据来源是什么,一般是如下几个方面:
直接已知子类: AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, InputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream
1、字节数组(我们用一个InputStream做例子,一般都需要将要读入的数据转换成字节数组)
2、字符串
3、文件系统
4、管道系统
5、filter 他可以通过组装其他流来给流提供额外的特性,比如让流必须使用缓存等
5、其他(如网络等)
下面分别介绍下几个输入流:
流名称 | 作用 | 构造器参数作用 |
ByteArrayInputStream | 1、她在内存中开辟一个空间作为她的一个缓冲区,读了字节数据放在这个缓冲区里面; 2、你关闭不了她,即使关闭她后,仍然能够使用她的read()方法,而不报错 |
ByteArrayInputStream(byte[] buf) 创建一个 ByteArrayInputStream,使用 buf 作为其缓冲区数组 |
StringBufferInputStream | 1、可以读字符串 2、但是读字符有问题,建议使用StringReader |
StringBufferInputStream(String s) 创建一个字符串输入流,以从指定字符串读取数据。 |
FileInputStream | 1、读文件 字节文件(img等)、字符文件 2、但是读字符有问题,建议FileReader |
FileInputStream(File file) 要读取的文件 |
PipedInputStream | 1、读数据到输入管道流,并提供给输出管道流 2、不建议两者放在同一个线程,会堵塞 |
PipedInputStream(PipedOutputStream src) 创建 PipedInputStream, 以使其连接到传送输出流 src。 |
SequenceInputStream | 1、她将多个流按顺序串联起来,一个流一个流的读 | SequenceInputStream(InputStream s1, InputStream s2) 通过记住这两个参数初始化新创建的 SequenceInputStream (将按顺序读取这两个参数,先读取 s1 然后读取 s2),以提供从此 SequenceInputStream 读取的字节 |
FilterInputStream | 1、其他流继承他,然后给这些流提供额外的功能,见下表 |
继承自filterInputStream的类,他们扩展了如下的功能。
java.io.FilterInputStream
java.io.BufferedInputStream
java.io.DataInputStream (implements java.io.DataInput)
java.io.LineNumberInputStream
java.io.PushbackInputStream
FilterInputStream及其派生类有两项重要任务:
DataInputStream可以读取各种primitive及String。(所有的方法都以"read"打头,比如readByte( ), readFloat( ))。它,以及它的搭档DataOutputStream,能让你通过流将primitive数据从一个地方导到另一个地方。
其它的类都是用来修改InputStream的内部行为的:是不是做缓冲,是不是知道它所读取的行信息(允许你读取行号或设定行号),是不是会弹出单个字符。后两个看上去更像是给编译器用的(也就是说,它们大概是为Java编译器设计的),所以通常情况下,你是不大会用到它们的。
不论你用哪种I/O设备,输入的时候,最好都做缓冲。所以对I/O类库来说,比较明智的做法还是把不缓冲当特例(或者去直接调用方法),而不是像现在这样把缓冲当作特例
流名称 |
作用 |
构造器参数作用 |
DataInputStream | 1、可以从基本流中*的读取java的基本类型和string,通过readXXX方法 2、因为前面基本的流都只是读字节数组或者字符串的,读不了int等,必须转换 |
DataInputStream(InputStream in) 使用指定的基础 InputStream 创建一个 DataInputStream。 |
BufferedInputStream | 1、强制使用缓冲区 | BufferedInputStream(InputStream in) 创建 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用 |
LineNumberInputStream | 1、读当前流数据行号 2、给编译器用的 |
|
PushbackInputStream | 1、她可以讲读出来的数据再放回去 2、编译器用的 |
2、输出流
输出流于输入流对应,输出流主要输出到下面几个部分:
直接已知子类: ByteArrayOutputStream(字节数组), FileOutputStream(文件), FilterOutputStream(扩展破坏器), ObjectOutputStream, OutputStream, PipedOutputStream(管道)、控制器
流名称 |
作用 |
构造器参数作用 |
ByteArrayOutputStream | 1、她在内存中开辟一个空间作为她的一个缓冲区,要写的字节数据放在这个缓冲区里面; 2、你关闭不了她,即使关闭她后,仍然能够使用她的read()方法,而不报错 |
ByteArrayOutputStream(byte[] buf) 创建一个 ByteArrayOutputStream,使用 buf 作为其缓冲区数组 |
StringBufferOutputStream | 这个没有,写字符串不用缓存 | |
FileOutputStream | 1、写文件 字节文件(img等)、字符文件 2、但是写字符有问题,建议FileWriter |
FileOutputStream(File file) FileOutputStream(File file,boolean append) |
PipedInputStream | 1、读数据到输入管道流,并提供给输出管道流 2、不建议两者放在同一个线程,会堵塞 |
|
SequenceInputStream |
这个没有,排序交给input了 | |
FilterOutputStream | 1、其他流继承他,然后给这些流提供额外的功能,见下表 |
java.io.FilterOutputStream
java.io.BufferedOutputStream
java.io.DataOutputStream (implements java.io.DataOutput)
java.io.PrintStream (implements java.lang.Appendable, java.io.Closeable)
流名称 |
作用 |
构造器参数作用 |
DataOutputStream | 1、可以向基本流中写入java基本类型和字符串 2、因为前面基本的流都只是写字节数组或者字符串的,写不了int、boolean等,必须转换 |
创建一个新的数据输出流,将数据写入指定基础输出流。 |
BufferedOutputStream |
1、以前写数据每次都要调用文件系统,使用缓冲可以先缓冲一部分数据再交给基本流一次性写入。 | |
LineNumberInputStream | 1、读当前流数据行号 2、给编译器用的 |
|
PushbackInputStream | 1、她可以讲读出来的数据再放回去 2、编译器用的 |
下面是一个关于DataInputStream的例子
package test.io.filter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
/**
* @2012年12月19日10:59:58
* @author sunyz
* DataOutputStream 和DataInputStream 存在的意义:
* 比如你想存储一个float值到文件当中,需要将float值转换成String对象,然后再分解成字节数组才能够存放,使用FileWriter;
* 然而使用DataOutputStream 不用考虑这么多的数据类型,它支持java各种基本类型和String,只需要使用它的writeXXX()方法
* 就可以了,所以很是方便
*
* 同样DataInputStream 只需要使用readXXX()读出来相应的方法,DataInputStream需要的构造参数就是DataOutputStream
*/
public class FilterInputStreamTest {
public static void main(String[] args) {
testOutput();
}
/**
* 现在使用DataOutputStream 测试如何存储float到number.txt文件当中
*/
public static void testOutput(){
String source = "请将我读出来";
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
//dataOutputStream.writeChars(source);
dataOutputStream.writeFloat(12.30f);
dataOutputStream.writeBoolean(false);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
DataInputStream dataInputStream = new DataInputStream(byteArrayInputStream);
System.out.println(dataInputStream.available());
System.out.println(dataInputStream.readFloat());
System.out.println(dataInputStream.readBoolean());
byteArrayOutputStream.close();
dataOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
3、本身的缺陷:RandomAccessFile
从类名上看他不是输入io类的,但是他实现了InputStream 和 OutputStream当中的接口,他跟其他IO类相比,有一个很大的功能就是:能够在使用seek()方法在一个文件的任何位置移动,(前提是这个文件长度是已知的),能在任意位置读取和修改这个文件,看起来好像是InputStream和OutputStream两者的结合,他的构造函数中RandomAccessFile(File file,String mode) mode参数还能设定文件的访问类型,是只读?读写?还是什么的
文件的读写权限,可以参考SecurityManager.checkRead();权限。认识SecurityManager请参考http://blog.csdn.net/zhoche2008/article/details/7101830
跟RandomAccessFile类一比较就看出来IO的缺陷出来,比方说我们想象RandomAccessFile一样,随便的访问流中的任意一个位置,这是做不到的,RandomAccessFile虽然可以访问任意位置,但是只限于找文件。
备注:
1、涉及到字节到字符的转换,一般用InputStreamReader(读字节)
2、涉及到字符到字节的转换,一般用OutputStreamWriter(写字节)