Android开发经验谈Android开发Android技术知识

什么是 Java 输入输出流?流的用法大全

2019-08-16  本文已影响7人  Android架构师丨小熊

I/O 流

关于数据的存储,分为内部存储和外部存储。内部存储就像内存一样,是一种临时性的对数据进行储存的方式,这种方式存储的数据量不大,但是获取数据块。另一种就是持久性的存储,以文件的方式来保存数据,可以是数据库、文本文件、图片文件、视频文件等等,存储的数据量非常大。

Java提供了一种对文件进行操作的API,就是I/O流。I/O流是Java中的一个非常庞大的家族,同时这个家族也非常强大。关于流的概念,我们可以这样的理解。水流,流的是水;电流,流的是电;I/O流,流的就是与计算机相关的二进制字节码、字符码。

I/O(Input / Output)就是标准的输入和输出,加上流的话。那么就是InputStream / OutputStream。流这个家族成员有很多,下面我们来通过一个表格来看看常用的流。

(1)流的家族

整个流的家族差不多也就这些了。通过以上的表格,我们大致了解了流的家族成员,下面我们来看看关于流的分类。

(2)流的分类

  1. 输入流 、输出流的作用
    输入流,用于从 .txt文件中读取数据;输出流,向文件中写入数据

  2. 字节流 、字符流的区别
    字节流,byte来接收数据,作用于任何类型的文件。

    字符流,char来接收数据。只能作用于纯文本(.txt)文件。如果是纯文本文件,读取速度比字节流更快。

  3. 节点流 、 处理流
    节点流,直接作用于文件上,如:new FileInputStream(File file);

  4. 处理流 , 作用于流上,如:new BufferedInputStream(InputStream is),作用是加速流的读取/写入速度。

File 类

介绍了整个流家族,我们还缺一个与流息息相关的 File 类。顾名思义,这是对文件进行创建、删除操作的一个类。而流则就是对文件的读取/写入操作的类。对于文件的操作,我们直接看代码例子比较鲜明,这也没什么理论好说的。

    @Test
    public void file() throws IOException {
        // 绝对路径:d:/FileTest/test ,新建文件夹
        File dirFile = new File("d:/FileTest/test");
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }
        // 相对路径:C:\Users\x\eclipse-workspace\HelloJava\Test.txt ,新建文件
        File helloFile = new File("Test.txt");
        if (!helloFile.exists()) {
            helloFile.createNewFile();
        }
 
        // 列出 d:/FileTest/test 文件夹下的所有文件名
        File nameFile = new File("d:/FileTest/test");
        String[] fileName = nameFile.list();
        for (String name : fileName) {
            System.out.println(name);
        }
 
        //判断文件的存在性
        System.out.println(helloFile.exists());
        //获取绝对路径
        System.out.println(helloFile.getAbsolutePath());
        //获取父目录
        System.out.println(helloFile.getParent());
        // 获取最后修改文件的时间
        System.out.println(new Date(helloFile.lastModified()));
    }

注意点:例如,D:/FileTest/test ,使用 mkdir 与 mkdirs 的区别 mkdir 前提是 FileTest 存在的情况下才可以创建成功 mkdirs 不需要,若 FileTest 文件夹不存在,则一并创建。

I/O流的用法

    @Test
    public void fisTest() {
        File file = new File("Hello.txt");
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            byte[] b = new byte[10];
            int length;
            while ((length = fis.read(b)) != -1) {
                String str = new String(b, 0, length);
                System.out.print(str);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

比较难理解的就是while循环,它表达的是从 Hello.txt 文件中读取byte[10]这样长度的字节,然后打印到控制台。若已经读到结尾,则没有数据可以读了,就会返回 -1

    @Test
    public void fosTest() {
        // 指定文件路径,若不存在,则会自动创建
        File file = new File("Hello.txt");
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            byte[] b = new String("hello Java 2").getBytes();
            fos.write(b, 0, b.length);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

FileInputStream/FileOutputStream 实现文件拷贝

    @Test
    public void copyTest() {
        long start = System.currentTimeMillis();
 
        File srcFile = new File("mv.mp4");
        File destFile = new File("mv3.mp4");
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);
            byte[] b = new byte[4 * 1024];
            int len;
            while ((len = fis.read(b)) != -1) {
                fos.write(b, 0, len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("time:" + (end - start));
    }
@Test
    public void copy2Test() {
        long start = System.currentTimeMillis();
        //备注:mv.mp4  测试文件大小 500M
        File file = new File("mv.mp4");
        File file2 = new File("mv2.mp4");
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            FileInputStream fis = new FileInputStream(file);
            FileOutputStream fos = new FileOutputStream(file2);
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);
            byte[] b = new byte[4 * 1024];// 4k缓冲区
            int len;
            while ((len = bis.read(b)) != -1) {
                bos.write(b, 0, len);
                bos.flush();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //把 bis 和 bos 关闭,那么 fis 和 fos 也就自动被关闭
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("time:" + (end - start));
    }
/**
     * 使用 FileReader 来读取文件 注意:只能读取文本文件,如.txt
     */
    @Test
    public void frTest() {
        FileReader fr = null;
        try {
            File file = new File("Hello.txt");
            fr = new FileReader(file);
            char[] c = new char[10];
            int len;
            while ((len = fr.read(c)) != -1) {
                String str = new String(c, 0, len);
                System.out.println(str);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

FileReader/FileWriter实现纯文本文件的拷贝

@Test
    public void txtCopyTest() {
        FileReader fr = null;
        FileWriter fw = null;
        try {
            File file = new File("Hello.txt");
            File file2 = new File("Test.txt");
            fr = new FileReader(file);
            fw = new FileWriter(file2);
 
            char[] c = new char[10];
            int len = 0;
            while ((len = fr.read(c)) != -1) {
                fw.write(c, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fw != null) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

@Test
    public void txtCopy2Test() {
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            File file = new File("Hello.txt");
            File file2 = new File("Test.txt");
            FileReader fr = new FileReader(file);
            FileWriter fw = new FileWriter(file2);
            br = new BufferedReader(fr);
            bw = new BufferedWriter(fw);
            String str = null;
            while ((str = br.readLine()) != null) {
                bw.write(str);
                bw.newLine();
                bw.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bw != null) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
/**
     * 系统的输入和输出,利用InputStreamReader(转换流)来转二进制码
     */
    @Test
    public void systemOut() {
        InputStreamReader isr = null;
        try {
            System.out.println("请输入字符串:");
            InputStream is = System.in;
            // 用到转换流
            isr = new InputStreamReader(is);
            char[] c = new char[10];
            int len;
            while ((len = isr.read(c)) != -1) {
                String str = new String(c, 0, len);
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (isr != null) {
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * PrintStream 和 PrintWriter 用法一致,只不过流的单位不同
     */
    @Test
    public void printIOTest() {
        PrintStream ps = null;
        try {
            File file = new File("Hello2.txt");
            ps = new PrintStream(file);
            ps.append("Java");
            ps.append("Android");
            ps.append("Python");
            ps.append("kotlin");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (ps != null) {
                ps.close();
            }
        }
    }
/**
     * DataOutputStream 只能用于写入基本数据类型,反之也只能用DataInputStream来读取,否则读到的就是乱码
     */
    @Test
    public void dataIOTest() {
        DataInputStream dis = null;
        DataOutputStream dos = null;
        try {
            dis = new DataInputStream(new FileInputStream(new File("Hello2.txt")));
            dos = new DataOutputStream(new FileOutputStream(new File("Hello2.txt")));
            dos.writeUTF("Java");
            dos.writeChar('c');
            dos.writeLong(4564114564l);
            dos.writeBoolean(false);
            dos.write(22);
 
            System.out.println(dis.readUTF());
            System.out.println(dis.readChar());
            System.out.println(dis.readLong());
            System.out.println(dis.readBoolean());
            System.out.println(dis.read());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (dos != null) {
                try {
                    dos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (dis != null) {
                try {
                    dis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

使用 FileInputStream 来读取的话,只能读到乱码文件:


使用DataInputStream来都,则正常显示:


ObjectOutputStream 序列化对象

         /**
     * 序列号过程
     */
    @Test
    public void objIOTest() {
        Student stu1 = new Student("001", "张三");
        Student stu2 = new Student("002", "李四");
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream(new File("student.txt")));
            oos.writeObject(stu1);
            oos.flush();
            oos.writeObject(stu2);
            oos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

ObjectInputStream 反序列化

    /**
     * 反序列化
     */
    @Test
    public void objIOTest2() {
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream(new File("student.txt")));
            Student get_stu1 = (Student) ois.readObject();
            System.out.println(get_stu1);
            Student get_stu2 = (Student) ois.readObject();
            System.out.println(get_stu2);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * RandomAccessFile 实现在文本中插入数据
     */
    @Test
    public void randomAccessTest() {
        RandomAccessFile raf_rw = null;
        try {
            raf_rw = new RandomAccessFile(new File("Hello3.txt"), "rw");
            // 光标移动到要插入的位置
            raf_rw.seek(5);
            // 保存后面的所有字符串
            StringBuffer buf = new StringBuffer();
            String str;
            while ((str = raf_rw.readLine()) != null) {
                buf.append(str + "\n");
            }
            System.out.println(buf.toString());
            raf_rw.seek(5);
            raf_rw.writeUTF("Java" + buf.toString());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                raf_rw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

IO流的大致使用都过了一遍,这些仅仅是的基本用法。

最后

最后我准备了一些面试的知识汇总,数据结构,计算机网络等等都有。自己整理和分类的,还请尊重知识产出。
分享给大家的资料包括高级架构技术进阶脑图、Android开发面试专题资料,还有高级进阶架构资料包括但不限于【高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术】希望能帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也是可以分享给身边好友一起学习的!
资料免费领取方式:加群:797404811

image
上一篇 下一篇

猜你喜欢

热点阅读