IO知识点汇总1

1、File类

  一般使用我们可能是像这样

File inFile = new File("*****");
File outFile = new File("*****");

  new一个File然后用输入流读文件。

InputStream in = new FileInputStream(inFile);

  文件如果不存在,会报FileNotFound

  File提供isFile()方法验证目录正确文件存在,可以来做验证

InputStream in = null;
if (inFile.isFile()) {
  in = new FileInputStream(inFile);
}

  写文件的时候

OutputStream out = new FileOutputStream(outFile);

  这种情况文件如果不存在,会自动创建。

  但需要注意的是,如果路径不存在,会FileNotFound,而不会自动创建路径的

  File提供了mkdir()和mkdirs()方法来创建目录

File parrent = outFile.getParentFile();
if (!parrent.exists()) {
  parrent.mkdirs();
}
OutputStream out = new FileOutputStream(outFile);

  mkdirs和mkdir不同的是mkdirs可以创建多级目录而mkdir只能创建单层目录,其实mkdirs实现就是递归一层一层做mkdir。

  File还提供很多方法,比如创建文件createNewFile,获取据对路径getAbsolutePath,获取磁盘空间等等,都比较简单需要的时候直接使用即可。

2、InputStream

  InputStream提供了三种读的方法

       

  read()方法,读一个字节,返回这个字节的int值

        byte[] bytes = new byte[1024];
        int i = 0;
        while (true) {
            int j = in.read();
            if (j == -1) {
                break;
            }
            bytes[i++] = (byte) j;
        }
        System.out.println(new String(bytes, 0, i));

  大概可以这样使用把,不严谨因为我知道文件就几个字节。大文件需要外面再套一层循环,whiletrue换成有条件的循环,可以参考下面的read(byte[],int,int)

  read(byte[])方法其实是read(byte[],0,byte.leng),所以主要看read(byte[],int,int)源码

      

  可以看到,类似上面写的逻辑,也是使用read()来一个字节一个字节读,把读到的字节放到byte[]中。

  返回的并不是读到的数据,而是字节数,-1表示读完了。数据放在byte[]里。

  我们平常使用比较多的应该是read(byte[])方法

        byte[] bytes = new byte[1024];
        int i;
        StringBuilder builder = new StringBuilder();
        while ((i = in.read(bytes)) != -1) {
            builder.append(new String(bytes, 0, i));
        }
        System.out.println(builder.toString());

  使用完后记得close(),也可以使用apache的common包的一些方法来close。

  InputStream还提供skip(long)方法跳过字节,reset和mark可以重复利用流,不过inputstream默认不支持。

 3、OutputStream

  

  OutputStream提供的方法很简单,3个write方法,flush,close

  类似InputStream,不做详细介绍了。不同的是读的时候可能经常使用read(byte[]),而写的时候一般使用write(byte[],int,int),如下:

byte[] bytes = new byte[1024];
        int i;
        while ((i = in.read(bytes)) != -1) {
            out.write(bytes, 0, i);
        }

  这个write的时候还是要注意的,可能bytes里有效数据不满,如果直接使用write(byte[])会出问题的。

  flush方法有必要说下,输出流输出的时候一般是先写在缓冲区中,然后再写入文件中。当完成输出流的输出后,可能缓冲区还没满,可能就不写入文件,所以这会儿需要flush强制将缓冲区的内容写入文件中。所以一般输出流在close之前需要先flush。

4、FileInputStream和FileOutputStream

  前面举的例子基本使用FileInputStream和FileOutputStream。一些特有的方法后面使用过程中遇到再做总结。

5、FilterInputStream和FilterOutputStream

  FilterInputStream是InputStream特殊的子类,里面包含了一个InputStream

  

  通过构造方法传入这个InputStream

  

  FilterInputStream子类,对InputStream进行改装,在原有的InputStream基础上提供了新的功能。

    DataInputStream,可以直接从stream中读取基本类型、字符串等类型数据

        DataOutputStream out = new DataOutputStream(new FileOutputStream("***"));
        out.writeInt(112314);
        out.writeUTF("hello world");
        out.writeBoolean(true);
        out.flush();
        out.close();

        DataInputStream in = new DataInputStream(new FileInputStream("*"));
        int i = in.readInt();
        System.out.println(i);
        String s = in.readUTF();
        System.out.println(s);
        boolean b = in.readBoolean();
        System.out.println(b);
        in.close();

    DataInputStream暂时没有想到一些合适的使用场景,以后碰到了再研究了解下。

    

    BufferedInputStream和BufferedOutputStream。

    使用方法参考前面列的InputStream,区别是BufferedInputStream和BufferedOutputStream提供了一个字节数组当缓存。每次read的时候先看缓存有没有,没有再从InputStream中读。输出时也是先写到缓存数组中,满了活着flush,一次性写OutputStream中。

  FilterInputStream和FilterOutputStream是装饰者模式的一个比较典型的应用。

6、ObjectInputStream和ObjectOutputStream

  可以直接对类进行读写

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("/Users/lianzhehua/workSpace/testMain/src/main/resources/test.txt"));
        out.writeObject(new Person("a", 22));
        out.writeObject(new Person("b", 23));
        out.writeObject(new Person("c", 24));
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("/Users/lianzhehua/workSpace/testMain/src/main/resources/test.txt"));
        try {
            while (true) {
                Object obj = in.readObject();
                Person a = (Person) obj;
                System.out.println(a);
            }
        } catch (EOFException e) {

        }

  这里提一下transient关键字,修饰的变量不参与序列化,可能有些同学不太了解。

  ObjectInputStream还提供对基本数据类型和字符串的读写,类似DataInputStream

posted @ 2017-09-18 20:39  方头狼  阅读(214)  评论(0编辑  收藏  举报