目录
I/O基础知识
流
字节流和字符流
关闭流的两种方式
手动关闭
自动关闭
字节流
顶级抽象类
InputStream
OutputStream
文件流
FileInputStream类
FileOutputStream类
字节数组流
ByteArrayInputStream类
ByteArrayOutputStream类
字节缓冲流
BufferedInputStream类
BufferedOutputStream类
PushbackInputStream类
打印流
PrintStream类
字符流
顶级抽象类
Reader
Writer
文件流
FileReader类
FileWriter类
字符数组流
CharArrayReader类
CharArrayWriter类
缓冲流
BufferedReader类
BufferedWriter类
PushbackReader类
打印流
PrintWriter类
 随机访问文件
RandomAccessFile类
控制台I/O
Console类
序列化
序列化的应用
Serializable
保存和加载序列化对象
ObjectOutputStream类
ObjectInputStream类
序列化的控制
Externalizable接口
瞬态和静态
File类
文件操作
文件筛选
文件列表对象
写在最后
 
  java的I/O系统是一个大块头,包含的东西太多了(就贴接口表格就能贴的让人头晕目眩),而且内容顺序不好安排,横切有字节流字符流,竖切有输入输出,再加新旧几轮迭代,三个维度纵横交错,真的不好写,以至于写这篇博客之前心里纠结了很久才下定的决心。
  因为不系统的梳理出来仔仔细细的过一遍,就不算是理解了。
  本篇博客只是自己整理,记录的是自己觉得有必要记录的东西,所以有一些偏冷门的类和用法是没有收录的,因为类实在太多了,记那么多根本没有必要,反倒让人学起来找不着东南西北。
  总之一句话:走大路,看辅路,不用管岔路。岔路留着让百度去查。
回到顶部
I/O基础知识
流
  java程序通过流执行I/O(I/O的意思就是 输入/输出)。
  流,是一种抽象,要么产生信息,要么使用信息,流通过java的IO系统链接到物理设备。
  尽管所有的流链接的物理设备是不同的,但是他们的行为方式都是相同的,因此,可以为任何类型的设备应用相同的IO类和方法。这意味着可以将许多不同类型的输入:磁盘文件、键盘或网络socket,抽象为输入流。与之对应,输出流可以引用控制台、磁盘文件或网络连接。
  流是处理输入/输出的一种清晰方式,例如代码中所有的部分都不需要去理解键盘和网络之间的区别,只需要操作流就行了,也就是说,‘流’屏蔽了实际IO设备中处理数据的细节。
字节流和字符流
  java定义了两种类型的流:字节流和字符流,两种流都有输入、输出两个内容。
  InputStream和OutStream针对字节流和而设计,为处理字节的输入和输出提供了方法。
  Reader和Writer针对字符流而设计,为处理字符的输入和输出提供了方便的方法。
  最初版本的java 1.0并没有提供字符流,因此,所有IO都是面向字节的。字符流是java 1.1添加的,并且某些面向字节的类和方法不再推荐使用。
  另外一点:在最底层,所有IO仍然是面向字节的,基于字符的流只是为处理字符提供了一种方便和高效的方法。
回到顶部
关闭流的两种方式
手动关闭
  通常,当不需要时,流必须关闭,如果没有关闭,就可能会导致内存泄漏以及资源紧张。
  从java最初发布以来就一直有关闭流的close()方法,对于这种方式,通常是在finally代码块中调用close()方法。
自动关闭
  到JDK7的时候,官方增加了一个新特性,该特性提供了另外一种管理资源的方式,这种方式能自动关闭文件。
  该特性以try语句的扩展版为基础:try(在这里生成流){}.
  当try代码块结束时,资源会被自动关闭,它的优点是当不再需要文件或者其他资源时,可以防止无意中忘记释放他们。
下面是带资源的try语句的3个关键点:
  1.由带资源的try语句管理的资源必须是实现了AutoCloseable接口的类的对象。
  2.在try代码中声明的资源被隐式声明为final。
  3.通过使用分号分割每个声明可以管理多个资源。
  带资源的try语句流线化了释放资源的过程,并消除了可能在无意中忘记释放资源的风险,所以如果可能的话,尽量在开发中使用这种方式。
回到顶部
字节流
顶级抽象类
回到顶部
InputStream
  字节流的顶层抽象类,定义了java的字节流输入模型。
方法列表:
方法	描述
int available()	返回当前可读取的输入字节数
void close	关闭输入流
boolean markSupported()	当前流是否支持打标记
void mark(int limit)	在输入流的当前位置放一个标记(并不是所有的流都支持这个特性),该标记在读入limit个字节之前一直都有效。
void reset()	将输入流的指针重置为前面设置的标记,如果当前没有任何标记,则指针重置到开头。
int read()	读入一个字节,并返回该字节。(这个read方法在碰到输入流的结尾时返回-1)
int read(byte b[])	读入一个字节数组,返回实际读入的字节数。(在碰到数据流的结尾时返回-1,这个方法最多读入b.length个字节)
int read(byte[] b,int off,int len)	读入一个字节数组,从byte[off]开始读,最多读取len个字节,返回实际读入的字节数,碰到输入流的结尾时返回-1.
long skip(long n)	在输入流中跳过n个字节,返回实际跳过的字节数。
 
 
 
 
 
 
 
 
 
 
回到顶部
OutputStream
  字节流的顶层抽象类,定义了java的字节流输出模型。
方法列表:
方法	描述
void write(int n)	写出一个字节的数据
void write(byte[] b)	写出一个字节数组
void write(byte[] b,int off,int len)	写出一个字节数组,从b[off]开始写,最多写len个字节。
void flush()	冲刷输出流,结束输出状态。
void close()	冲刷并关闭输出流。
 
 
 
 
 
 
 
文件流
回到顶部
FileInputStream类
  FileInputStream继承于InputStream,该对象可以用于从文件中读取字节。
构造函数:
  FileInputStream(String filePath);//文件的完整路径
  FileInputStream(File fileObj);//文件的File对象
  这两个构造器都会抛出FileNotFoundException异常。
从流中读取内容的两种方式:
复制代码
        try(FileInputStream f = new FileInputStream("./src/bytes/en.txt")){
            int size;
            System.out.println("总字节是:"+(size = f.available()));
            int num = 3;
            while(num>0){
                System.out.println("单个字节的读:"+(char) f.read());
                num--;
            }
            //注意:此时io流的指针已经到了第4个字节了,所以下面打印的内容不包含前3个字节。
            byte b[] = new byte[size];
            f.read(b);
            System.out.println("文件内容是:"+new String(b));
            //System.out.println("文件内容是:"+new String(b,0,size));//也可以这样
        }catch (IOException e){
            e.printStackTrace();
        }
复制代码
回到顶部
FileOutputStream类
  FileOutputStream继承于OutputStream,该对象可以将字节写入文件。
构造函数:
复制代码
  FileOutputStream(String filePath)
  FileOutputStream(String filePath,boolean append)
  FileOutputStream(File fileObj)
  FileOutputStream(File fileObj,boolean append)
复制代码
和FileInputStream一样,不同的是有一个append参数,这个参数如果为true,则以追加的方式打开文件,否则,这个方法会删除同名的已有文件创建一个新的输出流。
  另外,如果试图打开只读文件会抛出异常。
以下演示将数据写入文件:
复制代码
        try(FileOutputStream f1 = new FileOutputStream("./io/src/bytes/file1.txt");
            FileOutputStream f2 = new FileOutputStream("./io/src/bytes/file2.txt");
            FileOutputStream f3 = new FileOutputStream("./io/src/bytes/file3.txt")
        ){
            String source = "1234567890";
            byte[] buf = source.getBytes();
            //每跳一个字节写
            for(int i=0;i