java学习笔记13——IO流

File****类的使用

常用构造器

路径分隔符

常用方法

File类的获取功能和重命名功能


File 类的判断功能


File类的创建功能和删除功能

File 类的使用

总结:

复制代码
1.File类的理解
> File类位于java.io包下,本章中涉及到的相关流也都声明在java.io包下
> File类的一个对象,对应与操作系统下的一个文件或一个文件目录(或文件夹)
> File类中声明了新建、删除、获取名称、重命名等方法,并没有涉到文件内容的读写操作。要想实现文件内容的读写,
    我们就需要使用io流。
> File类的对象,通常是作为io流操作的文件的端点出现的。
        > 代码层面,将File类的对象作为参数传递到IO相关类的构造器中。

2.内部api使用说明
2.1 构造器
 public File(String pathname)
以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果
pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。
 绝对路径:是一个固定的路径,从盘符开始
 相对路径:是相对于某个位置开始
 public File(String parent,String child)
以parent为父路径,child为子路径创建File对象。
 public File(File parent,String child)
根据一个父File对象和子文件路径创建File对象
2.2 方法
获取文件和目录基本信息
    * public String getName():获取名称
    *public String getPath():获取路径
    *public String getAbsolutePath():获取绝对路径
    *public File getAbsoluteFile():获取绝对路径表示的文件
    *public String getParent():获取上层文件目录路径。若无,返回null
    *public long length():获取文件长度(即:字节数)。不能获取目录的长度。
    *public long lastModified():获取最后一次的修改时间,毫秒值
3.概念:
绝对路径:以windows操作系统为例,包括盘符在内的文件或文件目录的完整路径

相对路径:相对于某一个文件目录来讲的相对的位置
          在IDEA中,如果使用单元测试方法:相对于当前的module来讲
                    如果使用main()方法,相对于当前的project来讲

代码:

java 复制代码
public class FileTest {
    /**
     * public File(String pathname)
     * 以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果
     * pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。
     *  绝对路径:是一个固定的路径,从盘符开始
     *  相对路径:是相对于某个位置开始
     *  public File(String parent,String child)
     * 以parent为父路径,child为子路径创建File对象。
     *  public File(File parent,String child)
     * 根据一个父File对象和子文件路径创建File对象
     *
     * 文件的路径表示方式:
     * 方式1:绝对路径:以windows操作系统为例,包括盘符在内的文件或文件目录的完整路径
     * 方式2:相对路径:相对于某一个文件目录来讲的相对的位置
     *              在IDEA中,如果使用单元测试方法:相对于当前的module来讲
     *                   如果使用main()方法,相对于当前的project来讲
     */
    @Test
    public void test1(){
        //public File(String pathname)
        File file1 = new File("d:/io\\hello.txt");
        File file2 = new File("ab");
        System.out.println(file2.getAbsoluteFile());
    }

    public static void main(String[] args) {
        File file2 = new File("abc");
        System.out.println(file2.getAbsoluteFile());
    }
    @Test
    public void test2(){
        //public File(String parent,String child)
        //参数1:一定是一个文件目录
        //参数2:可以是一个文件,也可以是一个文件目录
        File file1 = new File("d:\\io","abc.txt");
        File file2 = new File("abc","a12");
//        public File(File parent,String child)
        //参数1:一定是一个文件目录
        //参数2:可以是一个文件,也可以是一个文件目录
        File file3 = new File(file2,"ab.txt");
    }
}

文件目录:

java 复制代码
public class FileTest1 {
    /**
     *  public String getAbsolutePath():获取绝对路径
     *  public String getPath() :获取路径
     *  public String getName() :获取名称
     *  public String getParent():获取上层文件目录路径。若无,返回null
     *  public long length() :获取文件长度(即:字节数)。不能获取目录的长度。
     *  public long lastModified() :获取最后一次的修改时间,毫秒值
     */
    @Test
    public void test1(){
        File file1 = new File("hello.txt");
        System.out.println(file1.getName());
        System.out.println(file1.getPath());
        System.out.println(file1.getAbsolutePath());
        System.out.println(file1.getAbsoluteFile());
        System.out.println(file1.getParent());
        System.out.println(file1.getAbsoluteFile().getParent());
        System.out.println(file1.length());
        System.out.println(file1.lastModified());
    }
    @Test
    public void test2(){
        File file1 = new File("D:\\io\\io1");
        System.out.println(file1.getName());
        System.out.println(file1.getPath());
        System.out.println(file1.getAbsolutePath());
        System.out.println(file1.getAbsoluteFile());
        System.out.println(file1.getParent()); //null
        System.out.println(file1.getAbsoluteFile().getParent());
        System.out.println(file1.length());
        System.out.println(file1.lastModified());
    }
    /**
     * 列出目录的下一级
     *  public String[] list() :获取指定目录下的所有文件或者文件目录的名称数组
     *  public File[] listFiles() :获取指定目录下的所有文件或者文件目录的File数组
     */
    @Test
    public void test3(){
        File file1 = new File("D:\\Download\\java资源\\尚硅谷java\\尚硅谷宋红康Java核心基础\\课件笔记源码资料\\新建文件夹\\1_课件\\第2部分:Java高级编程\\第2部分:Java高级编程\\尚硅谷_宋红康_第13章_IO流");
        String[] fileArr = file1.list();
        for(String s : fileArr){
            System.out.println(s);
        }
        System.out.println();
        File[] files = file1.listFiles();
        for(File f : files){
            System.out.println(f.getName());
        }
    }

    /**
     * File类的重命名功能
     * public boolean renameTo(File dest):把文件重命名为指定的文件路径
     *
     * 举例:
     * file1.renameTo(file2):要想此方法执行完,返回true。要求:
     *  file1必须存在,且file2必须不存在,且file2所在的文件目录需要存在。
     */
    @Test
    public void test4(){
        File file1 = new File("hello.txt");
        File file2 = new File("d:\\io\\abc.txt");
        boolean renameSuccess = file1.renameTo(file2);
        System.out.println(renameSuccess ? "重命名成功" : "重命名失败");
    }
    /**
     * File类的判断功能
     *  public boolean isDirectory():判断是否是文件目录
     *  public boolean isFile() :判断是否是文件
     *  public boolean exists() :判断是否存在
     *  public boolean canRead() :判断是否可读
     *  public boolean canWrite() :判断是否可写
     *  public boolean isHidden() :判断是否隐藏
     */
    @Test
    public void test5(){
        File file1 = new File("d:\\io\\abc.txt");
        System.out.println(file1.exists()); //true
        System.out.println(file1.isDirectory()); //false
        System.out.println(file1.isFile()); //true
        System.out.println(file1.canRead()); //true
        System.out.println(file1.canWrite());//true
        System.out.println(file1.isHidden());//false
        System.out.println();
        File file2 = new File("d:\\io");
        System.out.println(file2.exists()); //true
        System.out.println(file2.isDirectory()); //true
        System.out.println(file2.isFile()); //false
        System.out.println(file2.canRead()); //true
        System.out.println(file2.canWrite());//true
        System.out.println(file2.isHidden());//false
        System.out.println();
    }
    /**
     *File类的创建功能
     *  public boolean createNewFile() :创建文件。若文件存在,则不创建,返回false
     *  public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。
     * 如果此文件目录的上层目录不存在,也不创建。
     *  public boolean mkdirs() :创建文件目录。如果上层文件目录不存在,一并创建
     * 注意事项:如果你创建文件或者文件目录没有写盘符路径,那么,默认在项目
     * 路径下。
     *  File类的删除功能
     *  public boolean delete():删除文件或者文件夹
     * 删除注意事项:
     * Java中的删除不走回收站。
     * 要删除一个文件目录,请注意该文件目录内不能包含文件或者文件目录
     */
    @Test
    public void test6() throws IOException {
        File file1 = new File("d:\\io\\hello.txt");
        //测试文件的创、删除
        if(!file1.exists()){
            boolean isSuccessed = file1.createNewFile();
            if(isSuccessed){
                System.out.println("创建成功");
            }
        }else {
            System.out.println("此文件已存在");
            System.out.println(file1.delete() ? "文件删除成功" : " 文件删除失败");
        }
    }
    @Test
    public void test7(){
        //前提:d:\\io文件目录存在,io2和io3目录是不存在的,可以创建,返回值为true
        File file1 = new File("d:\\io\\io2");
        System.out.println(file1.mkdir()); //true
        File file2 = new File("d:\\io\\io3");
        System.out.println(file2.mkdirs()); //true
    }
    @Test
    public void test8(){
        //前提:d:\\io文件目录存在,io2和io3目录是不存在的,可以创建,返回值为true
        File file1 = new File("d:\\io\\io2\\io4");
        System.out.println(file1.mkdir()); //false
        File file2 = new File("d:\\io\\io3\\io5");
        System.out.println(file2.mkdirs()); //true
    }
    @Test
    public void test9(){
//        File file1 = new File("d:\\io\\io3\\io5");
//        System.out.println(file1.delete()); //true
        File file1 = new File("d:\\io\\io3");
        System.out.println(file1.delete()); //false
    }
}

练习1:

复制代码
练习:
创建一个与hello.txt文件在相同文件目录下的另一个名为abc.txt文件

代码:

java 复制代码
public class Exer01 {
    public static void main(String[] args) {
        //创建一个与hello.txt文件在相同文件目录下的另一个名为abc.txt文件
        File file1 = new File("hello.txt");
        //获取file1的绝对路径,获取此路径的上层文件目录
        System.out.println(file1.getAbsolutePath());
//        System.out.println(file1.getAbsoluteFile().getParent());
        File file2 = new File(file1.getAbsoluteFile().getParent(), "abc.txt");
        System.out.println(file2.getAbsolutePath());
    }
}

练习2:

复制代码
练习:
判断指定目录下是否有后缀名为.jpg的文件,如果有,就输出该文件名称
提示:File类提供了文件过滤器方法(拓展)
public String[] list(FilenameFilter filter)

代码:

java 复制代码
public class Exer02 {
    /**
     * 判断指定目录下是否有后缀名为.jpg的文件,如果有,就输出该文件名称
     */
    @Test
    public void test1(){
        File dir = new File("C:\\Users\\nihao\\Pictures\\Screenshots");
        //方式1:
//        String[] listFiles = dir.list();
//        for(String s : listFiles){
//            if(s.endsWith(".jpg")){
//                System.out.println(s);
//            }
//        }
        //方式2:
//        public String[] list(FilenameFilter filter)
        String[] listFiles = dir.list(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) { //name:即为子文件或子文件目录的名称
//                if(name.endsWith(".jpg")){
//                    return true;
//                }else {
//                    return false;
//                }
                return name.endsWith(".jpg");
            }
        });
        for(String fileName : listFiles){
            System.out.println(fileName);
        }
    }
}

练习3:

复制代码
练习:
遍历指定文件目录下的所有文件的名称,包括子文件目录中的文件。
public void printFileName(File file) //file可能是文件,也可能是文件目录
拓展1:删除指定文件目录及其下的所有文件
public void deleteDirectory(File file) //file可能是文件,也可能是文件目录
拓展2:计算指定文件目录占用空间的大小
public long getDirectorySize(File file) //file可能是文件,也可能是文件目录

代码:

java 复制代码
Exer03 
public class Exer03 {
    //public void printFileName(File file)
    @Test
    public void test1(){
        File file = new File("D:\\Download\\java资源\\尚硅谷java\\尚硅谷宋红康Java核心基础\\课件笔记源码资料\\新建文件夹\\1_课件\\第2部分:Java高级编程\\第2部分:Java高级编程\\尚硅谷_宋红康_第13章_IO流");
        printFileName(file);
    }
    public void printFileName(File file){
        if(file.isFile()){
            System.out.println(file.getName());
        }else if(file.isDirectory()){
            File[] files = file.listFiles();
            for(File f : files){
                printFileName(f);
            }
        }
    }
}

MoreExer 
public class MoreExer {
    /**
     * 拓展1:计算指定文件目录占用空间的大小
     */
    public long getDirectorySize(File file){
        //file是文件,那么直接返回file.length()
        //file是目录,把他的下一级的所有大小加起来就是他的总大小
        long size = 0;
        if(file.isFile()){
            size = file.length();
        }else {
            File[] all = file.listFiles(); //获取file的下一级
            //累加all[i]的大小
            for(File f : all){
                size += getDirectorySize(f); //f的大小
            }
        }
        return size;
    }
    /**
     * 拓展2:删除指定文件目录及其下的所有文件
     */
    public void deleteDirectory(File file){
        //如果file是文件,直接delete
        //如果file是目录。先把它的下一级干掉,然后删除自己
        if(file.isDirectory()){
            File[] all = file.listFiles();
            //循环删除的是file的下一级
            for(File f : all) { //f代表file的每一个下级
                deleteDirectory(f);
            }
        }
        //删除自己
        file.delete();
    }
}

IO****流原理及流的分类














总结:

复制代码
1.IO的分类
流向的不同:输入流、输出流
处理单位的不同:字节流、字符流
流的角色的不同:节点流、处理流
2.基础IO流的框架:
抽象基类            4个节点流(也称为文件流)
InputStream        FileInputStream
OutputStream       FileOutputStream
Reader             FileReader
Writer             FileWriter

说明:本章虽然涉及到的流很多,但是使用流进行数据的读写操作是非常标准和规范的。

3.FileReader\FileWriter 的使用
3.1 执行步骤:
第1步:创建读取或写出的File类的对象
第2步:创建输入流或输出流
第3步:具体的读入或写出的过程
    读入:read(char[] cbuffer)
    写出:write(string str)/write(char[] cbuffer,0,len)
第4步:关闭流资源,避免内存泄漏
3.2 注意点:
① 因为涉及到流资源的关闭操作,所以出现异常的话,需要使用try-catch-finally的方式来处理异常
② 对于输入流来讲,要求File类的对象对应的物理磁盘上的文件必须存在。否则,会报FileNotFoundException
   对于输出流来讲,File类的对象对应的物理磁盘上的文件可以不存在。
        > 如果此文件不存在,则在输出的过程中,会自动创建此文件,并写出数据到此文件中。
        > 如果此文件存在,使用 FileWriter(File file)或 FileWriter(File file,false):
                            输出数据过程中,会新建同名的文件对现有的文件进行覆盖。
                         FileWriter(File file,true):输出数据过程中,会在现有的文件的末尾追加写出内容
4.FileInputStream\FileOutputStream 的使用
4.1 执行步骤:
第1步:创建读取或写出的File类的对象
第2步:创建输入流或输出流
第3步:具体的读入或写出的过程
    读入:read(char[] cbuffer)
    写出:write(string str)/write(char[] cbuffer,0,len)
第4步:关闭流资源,避免内存泄漏

4.2 注意点:
> 在3.2 注意点的基础之上,看其他的注意点。
> 对于字符流,只能用来操作文本文件,不能用来处理非文本文件的。
  对于字节流,通常是用来处理非文本文件的。但是,如果涉及到文本文件的复制操作,也可以使用字节流。

说明:
文本文件:.txt、.java、.c、.cpp、.py等
非文本文件:.doc、.xls、.jpg、.pdf、.mp3、.mp4、.avi 等

代码:

java 复制代码
public class FileReaderWriterTest {
    /**
     * 需求:读取hello.txt中的内容,显示在控制台上
     * 异常使用throws的方式处理,不太合适,见test2
     */
    @Test
    public void test1() throws IOException {
        //1.创建File类的对象,对应着hello.txt
        File file = new File("hello.txt");
        //2.常见输入型的字符流,用于读取数据
        FileReader fr = new FileReader(file);
        //3.读取数据,并显示在控制台上
//        System.out.println((char)fr.read());
//        System.out.println((char)fr.read());
//        System.out.println((char)fr.read());
//        System.out.println((char)fr.read());
        //方式1:
//        int data = fr.read();
//        while(data != -1){
//            System.out.println((char)data);
//            data = fr.read();
//        }
        //方式2:
        int data;
        while((data = fr.read()) != -1){
            System.out.println((char)data);
        }
        //4.流资源的关闭操作(必须要关闭,否则会内存泄漏)
        fr.close();
    }

    /**
     * 需求:读取hello.txt中的内容,显示在控制台上
     * 使用try-catch-finally的方式处理异常,确保流一定可以关闭,避免内存泄漏
     */
    @Test
    public void test2() {
        FileReader fr = null;
        try {
            //1.创建File类的对象,对应着hello.txt
            File file = new File("hello.txt");
            //2.常见输入型的字符流,用于读取数据
            fr = new FileReader(file);
            //3.读取数据,并显示在控制台上
            //方式2:
            int data;
            while((data = fr.read()) != -1){
                System.out.print((char)data);
            }
        } catch (IOException e) {
           e.printStackTrace();
        }finally {
            //4.流资源的关闭操作(必须要关闭,否则会内存泄漏)
            try {
                //增加健壮性,避免出现文件找不到的异常,从未fr未被创建,是一个null
                if(fr != null)
                    fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 需求:读取hello.txt中的内容,显示在控制台上
     * 对test2()进行优化,每次读取多个字符存放到数组中,减少了与磁盘交互的次数,提升效率。
     */
    @Test
    public void test3() {
        FileReader fr = null;
        try {
            //1.创建File类的对象,对应着hello.txt
            File file = new File("hello.txt");
            //2.常见输入型的字符流,用于读取数据
            fr = new FileReader(file);
            //3.读取数据,并显示在控制台上
            char[] cbuffer = new char[5];
            int len;
            while((len = fr.read(cbuffer)) != -1){
                //遍历数组:错误的写法
//                for(int i = 0; i < cbuffer.length;i++){
//                    System.out.print(cbuffer[i]);
//                }
                //遍历数组:
                for(int i = 0; i < len;i++){
                    System.out.print(cbuffer[i]);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //4.流资源的关闭操作(必须要关闭,否则会内存泄漏)
            try {
                //增加健壮性,避免出现文件找不到的异常,从未fr未被创建,是一个null
                if(fr != null)
                    fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 需求:将内存中的数据写出到指定文件中
     */
    @Test
    public void test4() {
        FileWriter fw = null;
        try {
            //1.创建File类的对象,指明要写出的文件的名称
            File file = new File("info.txt");
            //2.创建输出流
            //覆盖文件使用的构造器
            fw = new FileWriter(file);
//            fw = new FileWriter(file,false);
            //在现有的文件基础上,追加内容使用的构造器
//            fw = new FileWriter(file,true);
            //3.写出具体的过程
            //输出的方法:write(String str)/write(char[] cdata)
            fw.write("I love U!\n");
            fw.write("You love him!\n");
            fw.write("太惨了...");
            System.out.println("输出成功");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 4.关闭资源
            try {
                if(fw != null)
                    fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 需求:复制一份hello.txt文件,命名为hello_copy.txt
     */
    @Test
    public void test5() {
        FileReader fr = null;
        FileWriter fw = null;
        try {
            //1.创建File类的对象
            File srcFile = new File("hello.txt");
            File destFile = new File("hello_copy.txt");
            //2.创建输入流、输出流
            fr = new FileReader(srcFile);
            fw = new FileWriter(destFile);
            //3.数据的读入和写出的过程
            char[] cbuffer  = new char[5];
            int len; //记录每次读入到cbuffer中的字符的个数
            while((len = fr.read(cbuffer)) != -1){
                //write(char[] cbuffer,int fromIndex,int len)
//                fw.write(cbuffer,0,len); //正确的
//                fw.write(cbuffer); //错误的,会多读一些内容
            }
            System.out.println("复制成功");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流资源
            //方式1:
//            try {
//              if(fw != null)
//                fw.close();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }finally{
//                try {
//                  if(fr != null)
//                    fr.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
            //方式2:
            try {
                if(fw != null)
                    fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(fr != null)
                    fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 需求:复制一份scenery.jpg文件,命名为scenery_copy.jpg
     * 复制失败!因为字符流不适合用来处理非文本文件
     */
    @Test
    public void test6() {
        FileReader fr = null;
        FileWriter fw = null;
        try {
            //1.创建File类的对象
            File srcFile = new File("scenery.jpg");
            File destFile = new File("scenery_copy.jpg");
            //2.创建输入流、输出流
            fr = new FileReader(srcFile);
            fw = new FileWriter(destFile);
            //3.数据的读入和写出的过程
            char[] cbuffer  = new char[5];
            int len; //记录每次读入到cbuffer中的字符的个数
            while((len = fr.read(cbuffer)) != -1){
                //write(char[] cbuffer,int fromIndex,int len)
//                fw.write(cbuffer,0,len); //正确的
//                fw.write(cbuffer); //错误的,会多读一些内容
            }
            System.out.println("复制成功");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流资源
            try {
                if(fw != null)
                    fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(fr != null)
                    fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
java 复制代码
public class FileStreamtTest {
    /**
     * 需求:复制一份scenery.jpg文件,命名为scenery_copy.jpg
     */
    @Test
    public void test1() throws IOException {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            //1.创建相关非File类的对象
            File srcFile = new File("scenery.jpg");
            File destFile = new File("scenery_copy.jpg");
            //2.创建相关的字节流
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);
            //3.数据的读入和写出
            byte[] buffer = new byte[1024]; //1kb
            int len; //记录每次读入到buffer中字节的个数
            while((len = fis.read(buffer)) != -1){
                fos.write(buffer, 0, len);
            }
            System.out.println("复制成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //4.关闭资源
            try {
                if(fis != null) fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fos != null) fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 需求:复制一份hello.txt文件,命名为hello_copy1.txt
     * 可以使用字节流实现文本文件的复制
     */
    @Test
    public void test2() throws IOException {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            //1.创建相关非File类的对象
            File srcFile = new File("hello.txt");
            File destFile = new File("hello_copy1.txt");
            //2.创建相关的字节流
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);
            //3.数据的读入和写出
            byte[] buffer = new byte[5]; //1kb
            int len; //记录每次读入到buffer中字节的个数
            while((len = fis.read(buffer)) != -1){
                fos.write(buffer, 0, len);
            }
            System.out.println("复制成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //4.关闭资源
            try {
                if(fis != null) fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fos != null) fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 需求:读取hello.txt文件,将数据显示在控制台上
     * 可能会出现乱码
     */
    @Test
    public void test3() throws IOException {
        FileInputStream fis = null;
        try {
            //1.创建相关非File类的对象
            File srcFile = new File("hello.txt");
            //2.创建相关的字节流
            fis = new FileInputStream(srcFile);
            //3.数据的读入和写出
            byte[] buffer = new byte[5]; //1kb
            int len; //记录每次读入到buffer中字节的个数
            while((len = fis.read(buffer)) != -1){
                String str = new String(buffer,0,len);
                System.out.print(str);
            }
            System.out.println();
            System.out.println("复制成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //4.关闭资源
            try {
                if(fis != null) fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

节点流**(或文件流)**

读取文件

写入文件

注意点

处理流之一:缓冲流

总结:

复制代码
1.基础IO流的框架
抽象基类            4个节点流(也称为文件流)     4个缓冲流(处理流的一种)
InputStream        FileInputStream         BufferedInputStream
OutputStream       FileOutputStream        BufferedOutputStream
Reader             FileReader              BufferedReader
Writer             FileWriter              BufferedWriter
2.缓冲流的作用:
提升文件读写的效率。
3.
4个缓冲流                         使用的方法
处理非文本文件的字节流:
BufferedInputStream             read(byte[] buffer)
BufferedOutputStream            write(byte[] buffer,0,len) 、flush()

处理文本文件的字符流:
BufferedReader                  read(char[] cBuffer) / readLine()
BufferedWriter                  write(char[] cBuffer,0,len) / write(String )  、flush()

3.实现的步骤
第1步:创建File的对象、流的对象(包括文件流、缓冲流)

第2步:使用缓冲流实现 读取数据 或写出数据的过程(重点)
    读取:int read(char[] cbuf/byte[] buffer):每次将数据读入到cbuf/buffer数组中,并返回读入到数组中
    写出:void write(string str)/write(char[] cbuf):将str或cbuf写出到文件中
    void write(byte[] buffer)将byte[]写出到文件中

第3步:关闭资源

代码:

java 复制代码
测试BufferedReader和BufferedWriter的使用
public class BufferedReaderWriterTest {
    /**
     * 使用BufferedReader将dbcp_utf-8.txt中的内容显示在控制台上
     */
    @Test
    public void test1() throws IOException {
        File file = new File("dbcp_utf-8.txt");
        BufferedReader br = new BufferedReader(new FileReader(file));
        //读取的过程
        //方式1:read(char[] cbuffer)
        char[] cBuffer = new char[1024];
        int len; //记录每次读入到cBuffer中的字符的个数
//        while((len = br.read(cBuffer)) != -1){
            //方法1:
//            for(int i = 0; i<len;i++){
//                System.out.println(cBuffer[i]);
//            }
            //方式2:
//            String str = new String(cBuffer,0,len);
//            System.out.println(str);
//        }
        //方式2:readLine(),每次读取一行的文本数据,返回的字符串是不包含换行符的
        String data;
        while((data = br.readLine()) != null){
            System.out.print(data + "\n");
        }
        //
        br.close();
    }
    /**
     * 使用BufferedReader和BufferedWriter实现文本文件的复制
     */
    @Test
    public void test2() throws IOException {
        //1.造文件,造流
        File file1 = new File("dbcp_utf-8.txt");
        File file2 = new File("dbcp_utf-8_copy1.txt");
        BufferedReader br = new BufferedReader(new FileReader(file1));
        BufferedWriter bw = new BufferedWriter(new FileWriter(file2));
        //2.文件的读写操作
        String data;
        while((data = br.readLine()) != null){
            bw.write(data);
            bw.newLine(); //表示换行操作
            bw.flush();//刷新的方法,每当调用此方法时,就会主动的将内存中的数据写入到磁盘文件
        }
        System.out.println("复制成功");
        //3.关闭资源
        bw.close();
        br.close();
    }
}
java 复制代码
public class BufferedStreamTest {
    /**
     * 需求:使用BufferedInputStream \ BufferedOutputStream复制一个图片
     * 注意:如下的操作应该使用try-catch-finally处理异常
     */
    @Test
    public void test1() throws IOException {
        //1.创建相关非File类的对象
        File srcFile = new File("scenery.jpg");
        File destFile = new File("scenery_copy.jpg");
        //2.创建相关的字节流,缓冲流
        FileInputStream fis = new FileInputStream(srcFile);
        FileOutputStream fos = new FileOutputStream(destFile);
        BufferedInputStream bis = new BufferedInputStream(fis);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        //3.数据的读入和写出
        byte[] buffer = new byte[1024]; //1kb
        int len; //记录每次读入到buffer中字节的个数
        while ((len = fis.read(buffer)) != -1) {
            fos.write(buffer, 0, len);
        }
        System.out.println("复制成功");
        //4.关闭资源
        //外层的流的关闭
        //由于外层流的关闭也会自动的对内层的流进行关闭操作,所以可以省略内层流的关闭
        bos.close();
        bis.close();
        //内层流的关闭
//        fis.close();
//        fos.close();
    }
}
java 复制代码
测试 FileInputStream +File0utputstream 复制文件
 BufferedInputstream +Buffered0utputstream 复制文件
 测试二者的效率。
public class CopyFileTest {
    @Test
    public void testSpendTime(){
        long start = System.currentTimeMillis();
        String src = "C:\\Users\\nihao\\Desktop\\1.mp4";
        String dest = "C:\\Users\\nihao\\Desktop\\3.mp4";
//        copyFileWithFileStream(src, dest); //128
        copyFileWithBufferedStream(src, dest);
        long end = System.currentTimeMillis();
        System.out.println("花费的时间为:" + (end-start));
    }
    /**
     * 使用BufferedInputstream +Buffered0utputstream复制文件
     */
    public void copyFileWithBufferedStream(String src,String dest){
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            //1.创建相关非File类的对象
            File srcFile = new File(src);
            File destFile = new File(dest);
            //2.创建相关的字节流,缓冲流
            FileInputStream fis = new FileInputStream(srcFile);
            FileOutputStream fos = new FileOutputStream(destFile);
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);
            //3.数据的读入和写出
            byte[] buffer = new byte[50]; //1kb
            int len; //记录每次读入到buffer中字节的个数
            while ((len = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
            System.out.println("复制成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //4.关闭资源
            //外层的流的关闭
            //由于外层流的关闭也会自动的对内层的流进行关闭操作,所以可以省略内层流的关闭
            try {
                if (bos != null)
                    bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (bis != null)
                    bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 使用FileInputStream +File0utputstream 复制文件
     */
    public void copyFileWithFileStream(String src,String dest){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            //1.创建相关非File类的对象
            File srcFile = new File(src);
            File destFile = new File(dest);
            //2.创建相关的字节流
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);
            //3.数据的读入和写出
            byte[] buffer = new byte[50]; //1kb
            int len; //记录每次读入到buffer中字节的个数
            while((len = fis.read(buffer)) != -1){
                fos.write(buffer, 0, len);
            }
            System.out.println("复制成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //4.关闭资源
            try {
                if(fis != null) fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fos != null) fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

处理流之二:转换流


字符编码

总结:

复制代码
1.复习
字符编码:字符、字符串、字符数组--->字节、字节数组(从我们能看得懂的--->我们看不懂的)
字符解码:字节、字节数组 --->字符、字符串、字符数组(从我们看不懂的--->我们能看得懂的)

2.如果希望程序在读取文本文件时,不出现乱码,需要注意什么?
> 解码时使用的字符集必须与当初编码时使用的字符集得相同。
> 拓展:解码集必须要与编码集兼容。比如:文件编码使用的是GBK,解码时使用的是utf-8。如果文件中只有abc等英文字符,此情况下
    也不会出现乱码。因为GBK和utf-8都向下兼容了ASCII(或 ascii)
3.转换流:
① 作用: 实现字节与字符之间的转换
② API:
InputstreamReader:将一个输入型的字节流转换为输入型的字符流
0utputstreamWriter:将一个输出型的字符流转换为输出型的字节流。
4.关于字符集的理解
4.1 在存储的文件中的字符:
ascii:主要用来存储a、b、c等英文字符和1、2、3、常用的标点符号。每个字符占用1个字节。
iso-8859-1:了解,每个字符占用1个字节。向下兼容ascii。
gbk:用来存储中文简体繁体、a、b、c等英文字符和1、2、3、常用的标点符号等字符。
    中文字符使用2个字节存储的。向下兼容ascii,意味着英文字符、1、2、3、标点符号仍使用1个字节
utf-8:可以用来存储世界范围内主要的语言的所有的字符。使用1-4个不等的字节表示一个字符。
        中文字符使用3个字节存储的。向下兼容ascii,意味着英文字符、1、2、3、标点符号仍使用1个字节。
4.2 在内存中的字符:
一个字符(char)占用2个字节。在内存中使用的字符集称为Unicode字符集。

代码:

java 复制代码
public class InputStreamReaderTest {
    /**
     * 读取到的数据出现了乱码
     * 因为dbcp_utf-8.txt文件使用的是utf-8的字符集进行的编码,所以在读取此文件时使用的解码集必须也是utf-8
     * 否则会出现乱码
     */
    @Test
    public void test1() throws IOException {
        //
        File file1 = new File("dbcp_utf-8.txt");
        //
        FileInputStream fis = new FileInputStream(file1);
//        InputStreamReader isr = new InputStreamReader(fis); //此时使用的是IDEA默认的UTF-8的字符集
        InputStreamReader isr1 = new InputStreamReader(fis, "gbk"); //显示的使用utf-8或gbk的字符集

        char[] cBuffer = new char[1024];
        int len;
        while((len = isr1.read(cBuffer)) != -1){
            String str = new String(cBuffer, 0, len);
            System.out.println(str);
        }
        //关闭资源
        isr1.close();
    }
    @Test
    public void test2() throws IOException {
        //
        File file1 = new File("dbcp_utf-8.txt");
        //
        FileInputStream fis = new FileInputStream(file1);
//        InputStreamReader isr = new InputStreamReader(fis); //此时使用的是IDEA默认的UTF-8的字符集
        InputStreamReader isr1 = new InputStreamReader(fis, "utf-8"); //显示的使用utf-8的字符集

        char[] cBuffer = new char[1024];
        int len;
        while((len = isr1.read(cBuffer)) != -1){
            String str = new String(cBuffer, 0, len);
            System.out.println(str);
        }
        //关闭资源
        isr1.close();
    }
    @Test
    public void test3() throws IOException {
        //
        File file1 = new File("dbcp_gbk.txt");
        //
        FileInputStream fis = new FileInputStream(file1);
//        InputStreamReader isr = new InputStreamReader(fis); //此时使用的是IDEA默认的UTF-8的字符集
        InputStreamReader isr1 = new InputStreamReader(fis, "gbk"); //显示的使用gbk的字符集

        char[] cBuffer = new char[1024];
        int len;
        while((len = isr1.read(cBuffer)) != -1){
            String str = new String(cBuffer, 0, len);
            System.out.println(str);
        }
        //关闭资源
        isr1.close();
    }
    /**
     * 需求:将gbk格式的文件转换为utf-8格式的文件存储
     */
    @Test
    public void test4() throws IOException {
        //1.造文件
        File file1 = new File("dbcp_gbk.txt");
        File file2 = new File("dbcp_gbk_to_utf-8.txt");
        //2.造流
        FileInputStream fis = new FileInputStream(file1);
        //参数2对应的是解码集,必须与dbcp_gbk.txt的编码集一致
        InputStreamReader isr = new InputStreamReader(fis,"GBK");
        FileOutputStream fos = new FileOutputStream(file2);
        //参数2指明内存中的字符存储到文件中的字节过程中使用的编码集
        OutputStreamWriter oosw = new OutputStreamWriter(fos,"utf-8");

        //3.读写过程
        char[] cBuffer = new char[1024];
        int len;
        while((len = isr.read(cBuffer)) != -1){
            oosw.write(cBuffer,0,len);
        }
        System.out.println("操作完成");
        //4.关闭资源
        oosw.close();
        isr.close();
    }
}

处理流之三:标准输入、输出流**(了解)**

处理流之四:打印流**(了解)**

apache-common包的使用

总结:

复制代码
1. 标准输入、输出流
System.in:标准的输入流,默认从键盘输入
System.out:标准的输出流,默认从显示器输出(理解为控制台输出)

通过调用如下的方法,修改输入流和输出流的位置
setIn(InputStream is)
setOut(PrintStream ps)
2.打印流

3.apache-common包的使用

代码:

java 复制代码
OtherStream 
public class OtherStream {
    /**
     * 从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续
     * 进行输入操作,直至当输入"e"或者"exit"时,退出程序。
     */
    @Test
    public void test1() {
        System.out.println("请输入信息(退出输入e或者exit):");
        //把"标准"输入流(键盘输入)这个字节流包装成字符流,在包装成缓冲流
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s = null;
        try {
            while ((s = br.readLine()) != null) { //读取用户输入的一行数据 ---> 阻塞程序
                if ("e".equalsIgnoreCase(s) || "exit".equalsIgnoreCase(s)) {
                    System.out.println("安全退出");
                    break;
                }
                //将读取到的操作整行字符串转成大写输出
                System.out.println("--->:" + s.toUpperCase());
                System.out.println("继续输入信息");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null)
                    br.close(); //关闭过滤流时,会自动关闭它包装的底层节点流
            } catch (IOException e) {

                e.printStackTrace();
            }
        }
    }
    @Test
    public void test2() throws FileNotFoundException {
        PrintStream ps = new PrintStream("io.txt");
        ps.println("hello");
        ps.println(1);
        ps.println(1.5);
        System.setOut(ps);
        System.out.println("你好,atguigu");
        ps.close();
    }
    @Test
    public void test3(){
        PrintStream ps = null;
        try {
            FileOutputStream fos = new FileOutputStream(new File("D:\\IO\\text.txt"));
            //创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会自动刷新输出缓冲区
            ps = new PrintStream(fos,true);
            if(ps != null){ //把标准输出流(控制台输出)改成文件
                System.setOut(ps);
            }
            for(int i = 0;i<=255;i++){ //输出ASCII字符
                System.out.print((char)i);
                if(i%50 ==0){ //每50个数据一行
                    System.out.println(); //换行
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if(ps != null)
                ps.close();
        }
    }
    //测试自定义的日志类
    @Test
    public void test4(){
        //测试工具类是否好用
        Logger.log("调用了System类的gc()方法,建议启动垃圾回收");
        Logger.log("调用了TeamView的addMember()方法");
        Logger.log("用户尝试进行登录,验证失败");
    }
    @Test
    public void test5() throws IOException {
        //赋值一个图片
        File srcFile = new File("scenery.jpg");
        File destFile = new File("scenery_copy2.jpg");
        FileUtils.copyFile(srcFile,destFile);
        System.out.println("复制成功");
    }
}

Logger 
public class Logger {
    /**
     * 记录日志的方法
     */
    public static void log(String msg){
        try {
            //指向一个日志文件
            PrintStream out = new PrintStream(new FileOutputStream("log.txt",true));
            //改变输出方法
            System.setOut(out);
            //日期当前时间
            Date nowTime = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
            String strTime = sdf.format(nowTime);
            System.out.println(strTime + ":" + msg);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

针对于test5而言的apache-common包

在当前包简历libs文件并引入包,在当前包下面放入需要使用的文件,不可以打开查看具体文件的话,点击右键,选择添加为库即可

处理流之五:数据流**(了解)**

处理流之六:对象流

总结:

复制代码
1.数据流及其作用(了解)
DataOutputstream:可以将内存中的基本数据类型的变量、string类型的变量写出到具体的文件中
DataInputstream:将文件中保存的数据还原为内存中的基本数据类型的变量、String类型的变量。
2.对象流及其作用
2.1 API:
0bjectInputSteam
0bjectOutputStream
2.2 作用:
可以读写基本数据类型的变量、引用数据类型的变量。
3.对象的序列化机制是什么
对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,
或通过网络将这种二进制流传输到另一个网络节点。//当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。
4.如下两个过程使用的流:
序列化过程:使用0bject0utputstream流实现。将内存中的Java对象保存在文件中或通过网络传输出去
反序列化过程:使用0bjectInputSteam流实现。将文件中的数据或网络传输过来的数据还原为内存中的Java对象
5.自定义类要想实现序列化机制,需要满足:
① 自定义类需要实现接口:Serializable
② 要求自定义类声明一个全局常量: static final long serialVersionUID = 42234234L;
    用来唯一的标识当前的类
③ 要求自定义类的各个属性也必须是可序列化的
    > 对于基本数据类型的属性:默认就是可以序列化的
    > 对于引用数据类型的属性:要求实现Serializable接口
6.注意点:
① 如果不声明全局常量serialVersionUID,系统会自动声明生成一个针对于当前类的serialVersionUID,
如果修改此类的话,会导致serialVersionUID变化,进而导致反序列化时,出现InvalidClassException
② 类中的属性如果声明为transient或static,则不会实现序列化。

代码:

java 复制代码
public class ObjectInputOutputStreamTest {
    /**
     * 序列化过程:使用0bject0utputstream流实现。将内存中的Java对象保存在文件中或通过网络传输出去
     */
    @Test
    public void test1() throws IOException {
        //1.
        File file = new File("Object.txt");
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
        //2.写出数据即为序列化的过程
        oos.writeUTF("江山如此多娇,引无数英雄尽折腰");
        oos.flush();
        oos.writeObject("轻轻地我走了,正如我轻轻地来");
        oos.flush();
        oos.close();
    }
    /**
     * 反序列化过程:使用0bjectInputSteam流实现。将文件中的数据或网络传输过来的数据还原为内存中的Java对象
     */
    @Test
    public void test2() throws IOException, ClassNotFoundException {
        //1.
        File file = new File("Object.txt");
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        //2.读取文件中的对象(或反序列化的过程)
        String str1 = ois.readUTF();
        System.out.println(str1);
        String str2 = (String)ois.readObject();
        System.out.println(str2);
        //3.
        ois.close();
    }
    /**
     * 演示自定义类的对象的序列化和反序列化的过程
     */
    //序列化过程:
    @Test
    public void test3() throws IOException {
        //1.
        File file = new File("Object1.txt");
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
        //2.写出数据即为序列化的过程
        Person p1 = new Person("Tom",12);
        oos.writeObject(p1);
        oos.flush();
        Person p2 = new Person("Jerry",23,1001,new Account(2000));
        oos.writeObject(p2);
        oos.flush();
        //3.
        oos.close();
    }
    //反序列化的过程
    @Test
    public void test4() throws IOException, ClassNotFoundException {
        //1.
        File file = new File("Object1.txt");
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        //2.读取文件中的对象(或反序列化的过程)
        Person person = (Person)ois.readObject();
        System.out.println(person);
        Person person1 = (Person) ois.readObject();
        System.out.println(person1);
        //3.
        ois.close();
    }
}
Person 
public class Person implements Serializable { //Serializable:属于一个标识接口
    transient String name;
    static int age;
    int idd;
    Account acct;
    static final long serialVersionUID = 42234234L;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person(String name, int age, int id) {
        this.name = name;
        this.age = age;
        this.idd = id;
    }

    public Person(String name, int age, int idd, Account acct) {
        this.name = name;
        this.age = age;
        this.idd = idd;
        this.acct = acct;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getId() {
        return idd;
    }

    public void setId(int id) {
        this.idd = id;
    }
//        @Override
//    public String toString() {
//        return "Person{" +
//                "name='" + name + '\'' +
//                ", age=" + age +
//                '}';
//    }

//    @Override
//    public String toString() {
//        return "Person{" +
//                "name='" + name + '\'' +
//                ", age=" + age +
//                ", id=" + idd +
//                '}';
//    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", idd=" + idd +
                ", acct=" + acct +
                '}';
    }
}
class Account implements Serializable {
    double balance;
    static final long serialVersionUID = 422574234L;

    public Account(double balance) {
        this.balance = balance;
    }

    @Override
    public String toString() {
        return "Account{" +
                "balance=" + balance +
                '}';
    }
}

随机存取文件流

NIO.2Path**、PathsFiles类的使用**

相关推荐
叶 落1 分钟前
[Java 基础]数组
java·java 基础
KK溜了溜了2 分钟前
JAVA-springboot log日志
java·spring boot·logback
珂朵莉MM4 分钟前
2021 RoboCom 世界机器人开发者大赛-高职组(初赛)解题报告 | 珂学家
java·开发语言·人工智能·算法·职场和发展·机器人
香蕉炒肉19 分钟前
Java优化:双重for循环
java·开发语言
傍晚冰川37 分钟前
FreeRTOS任务调度过程vTaskStartScheduler()&任务设计和划分
开发语言·笔记·stm32·单片机·嵌入式硬件·学习
黄雪超39 分钟前
JVM——打开JVM后门的钥匙:反射机制
java·开发语言·jvm
有梦想的攻城狮1 小时前
spring中的@RabbitListener注解详解
java·后端·spring·rabbitlistener
李斯维1 小时前
循序渐进 Android Binder(二):传递自定义对象和 AIDL 回调
android·java·android studio
androidwork1 小时前
OkHttp 3.0源码解析:从设计理念到核心实现
android·java·okhttp·kotlin
程序员岳焱1 小时前
Java 程序员成长记(二):菜鸟入职之 MyBatis XML「陷阱」
java·后端·程序员