抽象类InputStream是读取二进制数据的根类,抽象类OutputStream是写入二进制数据的根类。
Java IO类的设计是一个很好的应用继承的例子,它们的公共操作在父类中泛化定义,而子类提供特定的操作。
抽象的InputStream为输入字节流定义了方法
- public int read() throws IOException;
从输入流中读取下一个字节数据,字节值以0到255取值范围的int值返回。如果因为已经到流的最后而没有可的字节,则返回-1;
- public int read(byte b[]) throws IOException
从输入流中读取b.length个字节到数组b中,并且返回实际读取的字节数。到流的最后时返回-1;
- public int read(byte b[], int off, int len) throws IOException
从输入流中读取字节并且将它们保存在b[off],b[off+1],…,b[off+len-1]中。返回实际的字节数。到流的最后时返回-1.
- public void close() throws IOException ;
关闭输入流,释放其占用的任何系统资源。
- public native long skip(long n) throws IOException;
从输入流中跳过并且丢弃n字节的数据,返回实际跳过的字节数。
抽象的OutputStream为输出字节流定义了方法
- public abstract void write(int b) throws IOException;
将指定的字节写入该输出流中,参数b是一个int值。将(byte)b写入输出流中。
- public void write(byte b[]) throws IOException;
将数组b中的所有字节写入输出流中
- public void write(byte b[], int off, int len) throws IOException;
将b[off],b[off+1],…,b[off+len-1]写出到输出流中。
- public void close() throws IOException ;
关闭输出流,释放其占用的任何系统资源。
- public void flush() throws IOException;
清掉输出流,强制写出任何缓冲的输出流字节。
二进制IO类中的所有方法都声明为抛出java.io.IOException或java.io.IOException的子类
FileInputStream和FileOutputStream
FileInputStream从文件读取字节
FileOutputStream向文件写入字节
从上图可以看到继承关系。他们并没有什么特殊的方法,核心是看下源码对应的构造方法即可。
FileInputStream从文件系统中的文件获取输入字节。 什么文件可用取决于主机环境。
FileInputStream用于读取诸如图像数据的原始字节流。 要阅读字符串,请考虑使用FileReader 。
- FileInputStream(File file)
通过打开与实际文件的连接创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。
- FileInputStream(FileDescriptor fdObj)
创建 FileInputStream通过使用文件描述符 fdObj ,其表示在文件系统中的现有连接到一个实际的文件。
- FileInputStream(String name)
通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。
如果视图为一个不存在文件创建FileInputStream对象,将会发生java.io.FileNotFoundException异常。
FileOutputStream构造方法比较特别,文件不存在也不会异常,并且由追加和覆盖两类骚操作
文件输出流是用于将数据写入到输出流File或一个FileDescriptor 。 文件是否可用或可能被创建取决于底层平台。 特别是某些平台允许一次只能打开一个文件来写入一个FileOutputStream (或其他文件写入对象)。 在这种情况下,如果所涉及的文件已经打开,则此类中的构造函数将失败。
FileOutputStream用于写入诸如图像数据的原始字节流。 对于写入字符流,请考虑使用FileWriter 。
构造方法
- FileOutputStream(File file)
创建文件输出流以写入由指定的 File对象表示的文件。
- FileOutputStream(File file, boolean append)
创建文件输出流以写入由指定的 File对象表示的文件。
- FileOutputStream(FileDescriptor fdObj)
创建文件输出流以写入指定的文件描述符,表示与文件系统中实际文件的现有连接。
- FileOutputStream(String name)
创建文件输出流以指定的名称写入文件。
- FileOutputStream(String name, boolean append)
创建文件输出流以指定的名称写入文件。
读写1~100
语法糖真香
public static void main(String[] args) {
try (
OutputStream out = new FileOutputStream("d:\\temp.bat");
FileInputStream in = new FileInputStream("d:\\temp.bat");
) {
for (int i = 1; i <= 10; i++) {
out.write(i);
}
int value;
while ((value = in.read()) != -1) {
System.out.print(value + " ");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
JDK 1.7引入了语法糖try-with-resource,好处不言而喻,关闭资源更加优雅,也更加安全,避免忘记流等关闭。
只要实现了AutoCloseable接口的资源都可以通过这种方式实现自动关闭。
这个例子中temp.data是一个二进制文件,可通过java程序读取它,却不能用文本编辑器阅读它。
FilterInputStream和FilterOutputStream
过滤器数据流是了某种目的的过滤字节的数据流。
基本字节输入流提供的读取方法read只能用来读取字节。如果要读取整数值,双精度值或字符串,哪就需要一个过滤器类来包装字节输入流。使用过滤器类就可以读取整数值、双精度值和字符串,而不是字节或字符。
FilterInputStream和FilterOutputStream是用于过滤数据的基类,需要处理基本数值类型时,就使用DataInputStream和DataOutputStream.
封装的流是protected volatile InputStream in;
DataInputStream和DataOutputStream
先来个实例看下,什么时候用这是个问题。
public static void main(String[] args) throws IOException {
try (
DataOutputStream out = new DataOutputStream(new FileOutputStream("d:\\temp.bat", true));
) {
out.writeUTF("知人者智");
out.writeUTF("自知者明");
out.writeUTF("胜人者有力");
out.writeUTF("自胜者强");
}
try (
DataInputStream in = new DataInputStream(new FileInputStream("d:\\temp.bat"));
) {
System.out.println(in.readUTF());
System.out.println(in.readUTF());
System.out.println(in.readUTF());
System.out.println(in.readUTF());
}
}
DataInputStream对于多线程访问来说不一定是安全的。
数据输入流允许应用程序以独立于机器的方式从底层输入流读取原始Java数据类型。 应用程序使用数据输出流来写入稍后可以被数据输入流读取的数据。
public class DataOutputStream extends FilterOutputStream implements DataOutput
数据输出流使应用程序以便携式方式将原始Java数据类型写入输出流。 然后应用程序可以使用数据输入流来读取数据。
具体的API 可参考JDK帮助文档。
BufferedInputStream和BufferedOutputStream
这两个类干嘛用的?
主要功能是减少磁盘的读写次数来提高输入输出的速度。
就是一个内存缓冲功能,为了批量操作。
本质还是二进制读写工具,但是它是用内存缓冲来配合IO,减少磁盘交互,默认大小为512.
对于小文件,你可能注意不到性能的提升,但是对于超过100MB的大文件,你会看到使用缓冲IO带来的实质性的性能提升。