Java IO学习笔记

Java流的分类,一般可按以下方式分:

  1. 按方向分,分为输入流,输出流。
  2. 按类型分,分为字节流和字符流。
    2.1字节流是通过字节来读取数据
    2.2字符流是通过字符来读取数据
  3. 按操作方式分,分为节点流和过滤流。
    3.1 可以直接创建的流称为节点流,比如输入流,输出流
    3.2 过滤流可以装饰节点流,让流的功能变得更加强大,过滤流采用装饰者模式,对输入流进行包装。比如说BufferedInputStream,BufferedOutputStream,DataInputStream,DataOutputStream都是过滤流。
  4. 转换流。

废话不多说,看代码:
使用字节流读取文件内容:

    public void test1(){
        File file = new File("F:\hello.txt");
        FileInputStream fis = null;
        try {
            //创建一个文件输入流
            fis = new FileInputStream(file);
            //创建一个字节数组用来存储读取的信息
            byte[] buf = new byte[1024];
            //len表示读取的长度
            int len = 0;
            //只要len大于-1说明读取到元素,可对元素直接进行操作
            while((len=fis.read(buf))>-1){
                //通过控制台输出程序,需要指明输出的长度
                System.out.write(buf,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if (fis!=null) {
                    //操作完成之后关闭流
                    fis.close();
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

如何通过操作字节流来实现简单的文件拷贝呢?使用未经包装的输入输出流来拷贝文件,看代码:

    public void test2(){
        long startTime = new Date().getTime();
        File file = new File("F:\mysql-installer-community-5.6.22.0.msi");
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream(file);
            fos = new FileOutputStream("F:\1.msi");
            byte[] buf = new byte[1024];
            int len = 0;
            while((len=fis.read(buf))!=-1){
                fos.write(buf, 0, len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(fis!=null) fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(fos!=null) fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        long endTime = new Date().getTime();
        //查看效率
        System.out.println((endTime-startTime)/1000);
    }

最后的输出结果为2,也就是说拷贝一个接近300M的文件需要两秒钟。

再看看经过BufferedInputStream和BufferedOutputStream包装后的相同文件的拷贝,代码如下:

    public void test3(){
        long startTime = new Date().getTime();
        File file = new File("F:\mysql-installer-community-5.6.22.0.msi");
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            fis = new FileInputStream(file);
            //将fis包装起来
            bis = new BufferedInputStream(fis);
            //将输出流包装
            bos = new BufferedOutputStream(new FileOutputStream("F:\2.msi"));
            byte[] buf = new byte[1024];
            int len = 0;
            while((len=bis.read(buf))!=-1){
                bos.write(buf, 0, len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            //关闭流之后会自动flush
            try {
                if(bis!=null) bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(bos!=null) bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        long endTime = new Date().getTime();
        System.out.println((endTime-startTime)/1000);
    }

这里的输出为0,也就是说相同的文件拷贝,包装后的流效率会大大提高,原先需要两秒才能完成的拷贝,现在1秒都不到。

再看DataInputStream和DataOutputStream,这两个依然是将InputStream流包装,包装完成之后可以用它写基本类型数据以及字符型数据。

    public void test4(){
        FileOutputStream fos = null;
        DataOutputStream dos = null;
        DataInputStream dis = null;
        try {
            fos = new FileOutputStream("F:\2.txt");
            dos = new DataOutputStream(fos);
            /**
             * 每写一个Int类型数据,相当于写入四个字节数据,占四个字节,long是八个字节
             * 依次类推
             */
            dos.writeInt(1111);
            dos.writeInt(2222);
            dos.writeInt(3333);
            dis = new DataInputStream(new FileInputStream("F:\2.txt"));
            /**
             * 每执行一次readInt(),相当于读取四个字节数据,读取其他数据依次类推
             */
            System.out.println(dis.readInt());
            System.out.println(dis.readInt());
            System.out.println(dis.readInt());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(dos!=null) dos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(dis!=null) dis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

再看看包装后的字符流输入与输出:

    public void test5(){
        BufferedReader br = null;
        PrintWriter out = null;
        try {
            br = new BufferedReader(new FileReader("F:\hello.txt"));
            out = new PrintWriter(new BufferedWriter(new FileWriter("F:\11.txt")));
            String str = null;
            while((str=br.readLine())!= null){
                System.out.println(str);
                out.println(str);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(br!=null) br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if(out!=null) out.close();
        }
    }

字节流和字符流之间的转换,可以使用
字符流 =InputStreamReader(字节流)

把从控制台输入的文本内容转存到文本当中:

    public void test6() {
        BufferedReader br = null;
        PrintWriter out = null;
        try {
            br = new BufferedReader(new InputStreamReader(System.in));
            out = new PrintWriter(new BufferedWriter(new FileWriter(
                    "F:\222.txt")));
            String str = null;
            while ((str = br.readLine()) != null) {
                if (str.trim().equals("exit")) {
                    break;
                }
                System.out.println(str);
                out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null)
                    br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (out != null)
                out.close();
        }
    }

把一个对象写入到文件中:

    public void writeObject(){
        User user = new User("zhangsan","123");
        user.setMoney(200);
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("F:\object.dat"));
            oos.writeObject(user);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(oos!=null) oos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

User.java

import java.io.Serializable;

public class User implements Serializable{

    private String username;
    private String password;

    //添加了transient属性的字段不会被存储
    private transient int money;



    public int getMoney() {
        return money;
    }
    public void setMoney(int money) {
        this.money = money;
    }
    public User() {
    }
    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

从文件中读取一个对象:

    public void readObject(){
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream("F:\object.dat"));
            User u = (User) ois.readObject();
            System.out.println(u.getUsername()+","+u.getPassword()+","+u.getMoney());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

输出结果是:
这里写图片描述

由于给money字段添加了transient属性,所以money字段并不会被存储,当然也就读取不到。如果在User.java中删除transient,那么输出结果就是:

这里写图片描述

这个时候money就可被顺利的读取出来。

原文地址:https://www.cnblogs.com/lenve/p/4518014.html