• Java基础—IO小结(一)概述与节点流


    一、File类的使用 

      由于file类是一个基础类,所以我们从file类开始了解。(SE有完善的中文文档,建议阅读)

      构造器:

      

       常用方法:——完整方法请参见API API API!!!

          File做的是面上的事——文件的新建、删除、重命名等。有关文件内容的操作,需要流来进行,所以,它经常作为形参。

      

       文件名:

      测试文件:

      

      测试代码:

       @Test
        public void test1() {
            // 通过绝对路径创建File对象——对应一个文件或者文件夹
            File file = new File("D:\test\hello.txt");
            // getName()——文件或目录名
            System.out.println("#getName:"+file.getName());
            //     getPath()——路径字符串,若是相对路径,返回相对路径字符串
            System.out.println("#getPath:"+file.getPath());
            // getAbsoluteFile()——绝对路径形式,返回File
            System.out.println("#getAbsoluteFile() "+file.getAbsoluteFile());
            // getAbsolutePath()——绝对路径字符串
            System.out.println("#getAbsolutePath() "+file.getAbsolutePath());
            // getParent() ——返回父目录
            System.out.println("#getParent() "+file.getParent());
    
        }
    View Code

       测试结果:

      

      文件检测:

      测试文件:

      

      测试代码:

     @Test
        public void test2() {
            File file1 = new File("D:\test\hello.txt"); // 文件
            File file2 = new File("D:\test\childDir"); // 文件夹
            //     exists()——文件或目录是否存在
            System.out.println("#exists()"+file1.exists());
            // canRead() canWrite() ——是否可读可写
            System.out.println("#canRead()"+file1.canRead());
            System.out.println("#canWrite()"+file1.canWrite());
            //     isFile() isDirectory() ——是否是文件/目录
            System.out.println("#isFile()"+file1.isFile());
            System.out.println("#isFile()"+file2.isFile());
            System.out.println("#isDirectory()"+file1.isDirectory());
            System.out.println("#isDirectory()"+file2.isDirectory());
        }
    View Code

       测试结果:

      

      获取常规文件信息:

      测试文件:上文hello.txt

        测试代码:

    @Test
        public void test3() {
            File file = new File("D:\test\hello.txt");
            // lastModified() ——文件最后修改时间
            System.out.println("lastModified() :"+ new Date(file.lastModified()));
            // length()——文件长度(字节)
            System.out.println("length:"+file.length());
        }
    View Code

      测试结果:

      

      文件操作相关:

      测试代码:

     @Test
        public void test4() throws IOException {
            File file = new File("D:\test\hello1.txt"); //文件不存在
            // createNewFile()  ——不存在时创建新文件
            if (!file.exists()) {
                boolean b = file.createNewFile();
                System.out.println("创建空文件结果:"+ b);
            }
            // delete() ——文件长度(字节)
            System.out.println("delete() :" + file.delete());
        }
    View Code

      测试结果:

      

      目录操作相关:

      测试文件:

      

      测试代码:

     @Test
        public void test5() throws IOException {
            File file1 = new File("D:\test\childDir"); // 文件夹
            if (!file1.exists()) {
                // mkdir()——创建一个文件目录 mkdirs()——递归创建
                boolean b = file1.mkdir();
                System.out.println("新建文件夹结果:"+ b);
            }
            File file = new File("D:\test");
            // 与Linux命令的ls类似,list返回字符串,listFiles返回文件
            String[] files = file.list();
            for (String s : files) {
                System.out.println(s);
            }
        }
    View Code

      测试结果:

      

    二、IO流的分类

        读取外部设备中到程序中,称之为 input,输入;从程序向外输出到外部,称之为 ouput,输出;

      也就是,站在程序的角度来理解输入输出!

       A.根据处理数据类型的不同分为:字符流和字节流

       B.根据数据流向不同分为:输入流和输出流

       C.按功能分:节点流(一线的,离源最近的)和处理流

      

      都是由四个最基本的 抽象类派生而成

      

    三、节点流的使用

      

      请注意:由于流不是JVM的资源,不会被回收,所以:必须手动显式关闭!

       1.fis与fos

      FileInputStream

      构造器:

      

      方法摘要:输入流对应读的方法

      

      read()方法:

      @Test
        public void testFis1() throws Exception{
            // 从硬盘读取一个文件(File类与文件建立联系),将其文件内容读取到程序中
            File file = new File("D:\test\hello.txt");
            // 通过file构建一个输入流
            FileInputStream fis = new FileInputStream(file);
            // 调用fis的方法进行文件的操作
            /*
            * read():读取文件的一个字节(java中int为4字节),到结尾时返回-1
            * */
    //        int b = fis.read();
    //        while (b != -1) {
    //            System.out.print((char)b);
    //            b = fis.read();
    //        }
            int b;
            while ((b = fis.read()) != -1) {
                System.out.print((char)b);
            }
            // 必须手动关闭流!
            fis.close();
        }
    View Code

      结果:

      

      //实际上,txt中文件为Hello World,仔细看 72便是H的ASCII值(char型转为Int型了)

      若要显示英文字符,可以进行强转:

     System.out.print((char)b);

      当然,这里直接thorws的做法是及其不靠谱的,至少,当前面出现异常时,后续的代码(如colse())不会继续执行,也就是说,资源无法关闭!

      我们稍加改进:—— IO的操作请注意写法!

     @Test
        public void testFis2(){
            FileInputStream fis = null;
            try {
                // 从硬盘读取一个文件(File类与文件建立联系),将其文件内容读取到程序中
                File file = new File("D:\test\hello.txt");
                // 通过file构建一个输入流
                fis = new FileInputStream(file);
                // 调用fis的方法进行文件的操作
    
                int b;
                while ((b = fis.read()) != -1) {
                    System.out.print((char)b);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                // 必须手动关闭流!
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
        }
    View Code

      当然,一个一个字节读,在实际中是不可能的,我们可以使用它的重载方法:

      

      @Test
        public void testFis3() {
            FileInputStream fis = null;
            try {
                File file = new File("D:\test\hello.txt");
                fis = new FileInputStream(file);
                // 定义每次读取的字节数组,这里定义长度为5
                byte[] bytes = new byte[5];
                int len; // 每次读取的字节长度
                while ((len = fis.read(bytes)) != -1) {
                    /* 这里必须注意bytes.length与len的区别,len是实际读到的长度,
                       bytes.length是数组长度,可能会有之前读到的老的字符,读到的字节是依次放入bytes中,
                       将原先数组的进行替换,若未替换完,则保留了老的字节,不能遍历!
                    */
                    for (int i = 0; i < len; i++) {
                        System.out.print((char)bytes[i]);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    // 手动关闭流
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    View Code

      //相关注意的问题请看注释!

      FileOutputStream

      构造器:

      

      方法摘要:对应写的方法

      

      测试代码:

     @Test
        public void testFos1() {
            // 文件可以不存在,将会自动创建
            File file = new File("D:\test\hello1.txt");
            FileOutputStream fos = null;
            try {
                // 同样,使用文件作为构造器,关联上一个文件
                fos = new FileOutputStream(file);
                // 使用字节数组写入数据到文件
                fos.write(new String("I love China").getBytes());
                System.out.println("fos done!");
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (fos != null) { //增加空判断,防止空指针异常
                    try {
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    View Code

     //稍微改进异常处理时流的关闭引发的NPE

       结果:若文件存在不是追加,而是直接覆盖文件

      

      fos与fis实现文件的复制:

      测试代码:

     @Test
        public void testFisAndFos1() {
            // 已经存在,用于输入流读取
            File file1 = new File("D:\test\0.jpg");
            // 不存在,用于输入流写出
            File file2 = new File("D:\test\1.jpg");
            FileInputStream fis = null;
            FileOutputStream fos = null;
            try {
                fis = new FileInputStream(file1);
                fos = new FileOutputStream(file2);
                int len;
                byte[] bytes = new byte[5];
                while ((len = fis.read(bytes)) != -1) {
                    // 将取到的字节写入新的文件,注意读的长度
                    // 考虑 fos.write(bytes);的写法的错误之处
                    fos.write(bytes, 0, len);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    View Code

      // 后续将会升级为缓冲流

      测试结果:

      

      // 无论字节或者字符,都可以使用字节流进行处理

      2.fr与fw

      FileReader与FileWriter处理的步骤与上述是基本一样的,不同的是字符流处理的单位稍有差异

      构造器:

      

      

      FileReader

      测试代码:

       @Test
        public void testFr1() {
            File file = new File("D:\test\hello.txt");
            FileReader fr = null;
            try {
                // 同样的,根据文件构建一个输入流
                fr = new FileReader(file);
                int len;
                // 实际操作请根据文件大小修改字符数组大小
                char[] cbuf = new char[5];
                while ((len = fr.read(cbuf)) != -1) {
                    String s = new String(cbuf, 0, len);
                    System.out.print(s);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (fr != null) {
                    try {
                        fr.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
    
        }
    View Code

      测试结果即为输出文本文件到控制台

      FileReader与FileWriter进行文本文件复制与之前类似,只是数组类型不同:

      @Test
        public void testFrAndFw1() {
            // 需要关联的文件
            File file1 = new File("D:\test\hello.txt");
            File file2 = new File("D:\test\hello3.txt");
            FileReader fr = null;
            FileWriter fw = null;
            try {
                // 通过文件创建流
                fr = new FileReader(file1);
                fw = new FileWriter(file2);
                int len;
                char[] cbuf = new char[5];
                while ((len = fr.read(cbuf)) != -1) {
                    fw.write(cbuf, 0, len);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (fr != null) {
                    try {
                        fr.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (fw != null) {
                    try {
                        fw.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    View Code
  • 相关阅读:
    Springboot整合dubbo搭建基本的消费、提供和负载均衡
    SpringBoot与Dubbo整合的三种方式
    Dubbo整合SpringBoot
    Java 如何有效地避免OOM:善于利用软引用和弱引用
    finalize的作用
    垃圾回收
    不同JDK版本之间的intern()方法的区别-JDK6 VS JDK6+
    Java8内存模型—永久代(PermGen)和元空间(Metaspace)
    to meet you
    Atomic long 和long的区别
  • 原文地址:https://www.cnblogs.com/jiangbei/p/6664943.html
Copyright © 2020-2023  润新知