File类与IO流 2

File类与IO流 2

2.2流的分类

java.io包下提供了各种“流"类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据。·

  • 按数据的流向不同分为:输入流和输出流。
    • 输入流︰把数据从其他设备上读取到内存中的流。
      -以InputStream、Reader结尾
    • 输出流:把数据从内存中写出到其他设备上的流。
      -以outputStream、Writer结尾
  • 按操作数据单位的不同分为:字节流(8bit)和字符流(16bit) 。
    • 字节流︰以字节为单位,读写数据的流。
      以InputStream、OutputStream结尾。
    • 字符流∶以字符为单位,读写数据的流。
      -以Reader、Writer结尾
  • 根据lo流的角色不同分为:节点流和处理流。
    • 节点流:直接从数据源或目的地读写数据
    • 处理流:不直接连接到数据源或目的地,而是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。

image-20230906140442656

2.3流的API

.Java的Io流共涉及40多个类,实际上非常规则,都是从如下4个抽象基类派生的。

(抽象基类) 输入流 输出流
字节流 InputStream OutputStream
字符流 Reader Writer

字节与字符的区别

字节和字符的区别是一个常见的计算机基础知识问题,它涉及到数据的存储和编码方式。简单地说,字节是计算机存储数据的最小单位,它由8位二进制数字组成,可以表示0到255之间的任意数值。字符是计算机中使用的字母、数字、符号等,它们可以用不同的编码方式来表示,例如ASCII码、UTF-8码、Unicode码等。不同的编码方式对应不同的字符集,也就是可以表示的字符范围。一个字符可能占用一个或多个字节,这取决于它所属的字符集和编码方式。

例如,在ASCII码中,一个英文字母(不分大小写)为一个字节,一个中文汉字为两个字节。在UTF-8编码中,一个英文字母为一个字节,一个中文汉字为三个字节。在Unicode编码中,一个英文字母或一个中文汉字都为两个字节。这些编码方式都有各自的优缺点,你可以根据你的需求和场景来选择合适的编码方式。

image-20230906140915631

4个节点流(也称为文件流)

  • FileInputStream
  • FileOutputStream
  • FileReader
  • FileWriter
    //需求:读取hello.txt中的内容,显示在控制台上。
    //异常使用throws的方式处理,不太合适。见test2()
    public void test1() throws IOException {
        //1.创建File类的对象,对应着hello.txt文件
        File file = new File("hello.txt");
        //2.创建输入型的字符流,用于读取数据
        FileReader fr = new FileReader(file);
        //3.读取数据,并显示在控制台上
        //方式1
//        int data = fr.read();
//        while (data!=-1){
//            System.out.print((char)data);
//            data=fr.read();
//        }
        //方式2
        int data;
        while ((data=fr.read())!=-1){
            System.out.print((char) data);
        }

        //4.流资源的关闭操作(必须要关闭,否则会内存泄漏)
        fr.close();
    }

    /*
    需求:读取hello.txt中的内容,显示在控制台上。
使用try-catch-finally的方式处理异常。确保流一定可以关闭,避免内存泄瀛

     */
    public void test2(){
        FileReader fr = null;
        try {
            //1.创建File类的对象,对应着hello.txt文件
            File file = new File("hello.txt");
            //2.创建输入型的字符流,用于读取数据
            fr = new FileReader(file);
            //3.读取数据,并显示在控制台上
            int data;
            while ((data=fr.read())!=-1){
                System.out.print((char) data);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //4.流资源的关闭操作(必须要关闭,否则会内存泄漏)
            try {
                if (fr!=null)//避免没创建成功,关闭导致空指针
                fr.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }
    /*
需求:读取hello.txt中的内容,显示在控制台上。
对test2()进行优化,每次读取多个字符存放到字符数组中,减少了与磁盘交互的次数,提升效率。

     */
    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 < len; i++) {
                    System.out.print(cbuffer[i]);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //4.流资源的关闭操作(必须要关闭,否则会内存泄漏)
            try {
                if (fr!=null)//避免没创建成功,关闭导致空指针
                fr.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
   /*
        需求:将内存中的数据写出到指定的文件中

     */
    public void test4() {
        FileWriter fw = null;
        try {
            //1.创建File类的对象,指明要写出的文件的名称
            File file = new File("info.txt");
            //2.创建输出流
            //fw = new FileWriter(file);表示文件覆盖
            fw = new FileWriter(file,true);//true:表示在后面追加
        //在现有的文件基础上,追加内容使用的构造器:

            //3.写出的具体过程
            //输出的方法: write (String str) / write(char[ ] cdata)
            fw.write("I Love U \n");
            fw.write("You love him \n");
            fw.write("I'm sorry... \n");
            System.out.println("输出成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //4.关闭资源
            try {
                fw.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

3.FileReader \ FileWriter 的使用3.1执行步骤;
第1步:创建读取或写出的File类的对象
第2步:创建输入流或输出流
第3步:具体的读入或写出的过程。
读入: read(char[ ] cbuffer)
写出: write(String str) / write(char[ ] cbuffer ,0,len)第4步:关闭流资源,避免内存泄漏

 //需求:复制一份hello.txt文件,命名为hello_copy.txt
    public void test5(){
        FileReader fileReader = null;
        FileWriter fileWriter = null;
        try {
            //1.创建File类的对象  2个
            File srcFile = new File("hello.txt");
            File destFile = new File("hello_copy.txt");
            //2.创建输入流、输出流
            fileReader = new FileReader(srcFile);
            fileWriter = new FileWriter(destFile);
            //3.数据的读入和写出的过程
            char[] cbuffer = new char[5];
            int len;//记录每次读入到cbuffer中的字符的个数
            while ((len=fileReader.read(cbuffer))!=-1){
                fileWriter.write(cbuffer,0,len);//写入char[] cbuffer的从0到len字符,左闭右开
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //4.关闭流资源
            try {
                if (fileWriter!=null)
                fileWriter.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                if (fileReader!=null)
                fileReader.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }

3.2注意点:

因为涉及到流资源的关闭操作,所以出现异常的话,需要使用try-catch-finally的方式来处理异常

  • 对于输入流来讲,要求File类的对象对应的物理磁盘上的文件必须存在。否则,会报FileNotFoundException
  • 对于输出流来讲,File类的对象对应的物理磁盘上的文件可以不存在。
    • 如果此文件不存在,则在输出的过程中,会自动创建此文件,并写出数据到此文件中。
    • 如果此文件存在,使用FileWriter(File file)或FileWriter(File file,false):
      输出数据过程中,会新建同名的文件对现有的文件进行覆盖。
      FileWriter(File file , true)︰输出数据过程中,会在现有的文件的末尾追加写出内容。

//需求:复制一份playgirl.jpg文件,命名为playgirl_copy.jpg
    //复制失败!因为字符流不适合用来处理非文本文件。

    public void test6(){
        FileReader fileReader = null;
        FileWriter fileWriter = null;
        try {
            //1.创建File类的对象  2个
            File srcFile = new File("playgirl.jpg");
            File destFile = new File("playgirl_copy.jpg");
            //2.创建输入流、输出流
            fileReader = new FileReader(srcFile);
            fileWriter = new FileWriter(destFile);
            //3.数据的读入和写出的过程
            char[] cbuffer = new char[5];
            int len;//记录每次读入到cbuffer中的字符的个数
            while ((len=fileReader.read(cbuffer))!=-1){
                fileWriter.write(cbuffer,0,len);//写入char[] cbuffer的从0到len字符,左闭右开
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //4.关闭流资源
            try {
                if (fileWriter!=null)
                    fileWriter.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                if (fileReader!=null)
                    fileReader.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }

4.FileInputStream \ File0utputstream的使用

4.1执行步骤:

第1步:创建读取或写出的File类的对象

第2步:创建输入流或输出流

第3步:具体的读入或写出的过程。
读入:read(byte[] buffer)
写出: write(byte[] buffer ,0,len)

第4步:关闭流资源,避免内存泄漏

    //需求:复制一份playgirl.jpg文件,命名为playgirl_copy.jpg。

    public void test1(){
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;

        try {
            //1.创建File类的对象  2个
            File srcFile = new File("playgirl.jpg");
            File destFile = new File("playgirl_copy.jpg");
            //2.创建输入流、输出流
            fileInputStream = new FileInputStream(srcFile);
            fileOutputStream = new FileOutputStream(destFile);
            //3.数据的读入和写出的过程
            byte[] buffer = new byte[1024];//1kb
            int len;//记录每次读入到buffer中的字节的个数
            while ((len=fileInputStream.read(buffer))!=-1){
                fileOutputStream.write(buffer,0,len);//写入byte[] buffer的从0到len字符,左闭右开
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流资源
            if (fileOutputStream!=null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

            if (fileInputStream!=null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

4.2注意点:

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

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

posted @   新至所向  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示