java之IO篇——File、字节流、字符流

news2024/10/1 19:22:07

前言

IO流是用于读写文件中的数据,要读写文件之前可以创建文件获取文件对象再创建IO流,正文会先介绍File类,通过File类的构造方法获取文件的对象,创建文件或目录以及File类的一些方法获取文件对象的属性。后面还介绍了相关的IO流体系,字节流和字符流的区别用法。

目录

前言

一、File

1.常用的成员方法

(1) 判断、获取

(2)创建、删除

(3)获取并遍历 

2. 实操

(1)遍历C盘下的以.avi结尾的文件

(2)删除一个多级文件夹(里面的有些文件有内容) 

(3)统计各种文件的数量 

二、IO流分类

三、IO体系

1.字节流

 2.字符流

四、字节流

1.字节输出流

(1)用法

(2)进阶用法(换行和续写)

 2.字节输入流

(1)用法

3.拷贝

五、try-with-resources

六、字符集(ASCLL、GBK、Unicode)

七、读取出现乱码

1.原因

2.解决方法

3.编码和解码

八、字符流

1.特点

2.使用场景

3.字符输出流

(1)用法

(2)底层原理

4.字符输入流

(1)用法

(2)底层原理

 九、字节流和字符流实战

1.拷贝文件夹

2.加密解密

3.将文件排序


一、File

1.常用的成员方法

(1) 判断、获取

注意: 1.length返回文件的大小(字节数量)

                细节1:这个方法只能获取文件的大小,单位是字节

                如果单位我们要是M,G,可以不断的除以1024

                细节2:这个方法无法获取文件夹的大小

                如果我们要获取一个文件夹的大小,需要把这个文件夹里面所有的文件大小都累加在一起。

           2.getName获取名字

                细节1:file是文件会返回文件的文件名和扩展名(如.txt  .cpp)

                细节2:file是文件夹就返回文件夹的名字。

(2)创建、删除

注意:1.createNewFile创建一个新的空的文件

                细节1:如果当前路径表示的文件是不存在的,则创建成功,方法返回true

                             如果当前路径表示的文件是存在的,则创建失败,方法返回false

                细节2:如果父级路径是不存在的,那么方法会有异常IOException

                细节3:createNewFile方法创建的一定是文件,如果路径中不包含后缀名,则创建一个没有后缀的文件

           2.mkdir创建一个文件夹(目录)

                细节1:windows当中路径是唯一的,如果当前路径已经存在,则创建失败,返回false

                细节2:mkdir方法只能创建单级文件夹,无法创建多级文件夹。

          3. mkdirs创建多级文件夹

                细节:既可以创建单级的,又可以创建多级的文件夹

          4.delete删除文件、空文件夹

                细节:如果删除的是文件,则直接删除,不走回收站。

                          如果删除的是空文件夹,则直接删除,不走回收站

                          如果删除的是有内容的文件夹,则删除失败  

(3)获取并遍历 

注意:细节: 

  

//1.创建File对象
File f = new File("D:\\aaa");
//2.listFiles方法
//作用:获取aaa文件夹里面的所有内容,把所有的内容放到数组中返回
File[] files = f.listFiles();
for (File file:files) {
    //file依次表示aaa文件夹里面的每一个文件或者文件夹
    System.out.println(file);
}

2. 实操

(1)遍历C盘下的以.avi结尾的文件

递归,一定要先用if判断文件数组是否为空,否则会抛出空指针异常

(2)删除一个多级文件夹(里面的有些文件有内容) 

(3)统计各种文件的数量 

 /*
    * 作用:
    *       统计一个文件夹中每种文件的个数
    * 参数:
    *       要统计的那个文件夹
    * 返回值:
    *       用来统计map集合
    *       键:后缀名 值:次数
    *
    *       a.txt
    *       a.a.txt
    *       aaa(不需要统计的)
    *
    *
    * */
    public static HashMap<String,Integer> getCount(File src){
        //1.定义集合用来统计
        HashMap<String,Integer> hm = new HashMap<>();
        //2.进入src文件夹
        File[] files = src.listFiles();
        //3.遍历数组
        for (File file : files) {
            //4.判断,如果是文件,统计
            if(file.isFile()){
                //a.txt
                String name = file.getName();
                String[] arr = name.split("\\.");
                if(arr.length >= 2){
                    String endName = arr[arr.length - 1];
                    if(hm.containsKey(endName)){
                        //存在
                        int count = hm.get(endName);
                        count++;
                        hm.put(endName,count);
                    }else{
                        //不存在
                        hm.put(endName,1);
                    }
                }
            }else{
                //5.判断,如果是文件夹,递归
                //sonMap里面是子文件中每一种文件的个数
                HashMap<String, Integer> sonMap = getCount(file);
                //hm:  txt=1  jpg=2  doc=3
                //sonMap: txt=3 jpg=1
                //遍历sonMap把里面的值累加到hm当中
                Set<Map.Entry<String, Integer>> entries = sonMap.entrySet();
                for (Map.Entry<String, Integer> entry : entries) {
                    String key = entry.getKey();
                    int value = entry.getValue();
                    if(hm.containsKey(key)){
                        //存在
                        int count = hm.get(key);
                        count = count + value;
                        hm.put(key,count);
                    }else{
                        //不存在
                        hm.put(key,value);
                    }
                }
            }
        }
        return hm;
    }
}

二、IO流分类

纯文本文件,就是Windows自带的记事本打开能读懂的。比如(.txt  .md)

三、IO体系

1.字节流

 文件操作是程序通过IO流来读写文件。

 输入的意思是将文件的数据读进来,进到程序来,加上操作的对象是本地文件,所以实现类FileInputStream叫做操作本地文件的字节输入流。

相反的,输出的意思就是,文件的操作者——程序,将修改的数据写到文件里面,即输出到文件去。加上操作的对象是本地文件,所以实现类FileOutputStream叫做操作本地文件的字节输出流。

字节流不仅有文件流 ,还有缓冲流BufferedInputStream、BufferedOutputStream,数据流DataInputStream、DataOutputStream,对象流ObjectInputStream、ObjectOutputStream,打印流PrintStream等等还有很多。

 2.字符流

 字符流的输入和输出和字节流的输入输出一个意思,不同的就是字符流的底层是字节流+字符集。字节流是一个字节一个字节读取的,而字符流是普通字符就一个字节,遇到中文就按字符集的规则多个字节读。

字符流不仅有文件字符流,还有缓冲字符流等等

 

四、字节流

以文件流FileInputStream、FileOutputStream为例

1.字节输出流

(1)用法

1.创建字节输出流对象

2.写数据

3.释放资源

详解:

1.创建字节流对象(2+2)

下面是两个构造方法 传递一个绝对/相对路径的字符串    或者   传递一个File对象

//通过文件的路径创建文件输出流
FileOutputStream fos = new FileOutputStream("files\\test1.txt");
//通过文件对象创建文件输出流
File file = new File("files\\test1.txt");
FileOutputStream fos1 = new FileOutputStream(file);

 细节:参数是字符串表示的路径或者是File对象都是可以的

            如果文件不存在构造方法会创建一个新的文件,但是要保证父级路径是存在的。

            如果文件存在造方法会清空文件

如果我们不想要创建字节流的时候把原本文件内容清空,我们必须使用另外的两个构造器,

在原来一个参数的构造器的基础上,加上第二个参数,true表示续写。

2.写数据(write方法3种参数)

细节:write方法的参数是整数,但是实际上写到本地文件中的是整数在ASCII上对应的字符

一个一个查ASCLL这样子写下来会不会太麻烦了?

还有更简便的方法,将想要的数据传入一个String字符串,再通过String类的getBytes()方法将字符串转换为字节数组,最后将字节数组传递给write方法。

3.释放资源

每次使用完流之后都要释放资源

细节:如果流不关闭,并且当前使用流的程序没有停止,那么这个文件就不能被删除。

(2)进阶用法(换行和续写)

1.换行写:

再次写出一个换行符就可以了(每一个操作系统的换行符都不一样)

windows:  \r\n

Linux:       \n

Mac:         \r

写入文件的内容为:

kankelaiyezuishuai

666

2.续写

续写就是创建输出流的时候选用有第二个参数append的构造器。如下

 

 2.字节输入流

(1)用法

1.创建字节输入流对象

2.读数据

3.释放资源

 1.创建字节输入流对象

通过输入流的构造方法,创建输入流对象,一样都是传入一个绝对/相对路径的字符串或File对象

 细节:如果文件不存在,就直接报错。

Java为什么会这么设计呢?

看前面的输出流:不存在,就创建,把数据写到文件当中

而为什么输入流不存在是报错呢?

因为创建出来的文件是没有数据的,没有任何意义。所以Java就没有设计这种无意义的逻辑,文件不存在直接报错。

2.读数据(read方法3个)

int read()读取一个字节,读完后指针后移一位

int read(byte[] b)从该输入流读取最多b.length字节的数据到字节数组。以整数形式返回实际读取的字节数。

细节:无参的read方法一次读一个字节,读出来的是数据在ASCII上对应的数字

           读到文件末尾了,read方法返回-1。

          有参的read方法一次读一个字节数组的数据,读到的数据是以覆盖的形式覆盖原本的字节数组,比如说一个文件内容为abcde以长度为2的字节数组读取

FileInputStream fis = new FileInputStream("files\\test1.txt");
byte[] buffer = new byte[2];
int len;
//字节个数是2 读到的数据ab覆盖空数组
len = fis.read(buffer);//2
System.out.println("读取了" + len + "个字节,数据为"+ new String(buffer,0,2));//ab
//字节个数是2 读到的数据cd覆盖掉原本的ab
len = fis.read(buffer);//2
System.out.println("读取了" + len + "个字节,数据为"+ new String(buffer,0,2));//cd
//字节个数是1 读取的数据e只覆盖掉原本的cd的第一个字节
len = fis.read(buffer);//1
System.out.println("读取了" + len + "个字节,数据为"+ new String(buffer,0,2));//ed
//字节个数是-1 无覆盖还是ed
len = fis.read(buffer);//-1
System.out.println("读取了" + len + "个字节,数据为"+ new String(buffer,0,2));//ed

优化后代码(实际上用的)

3.释放资源

每次使用完流必须要释放资源。

注意:用字节流读取文件中的中文,会输出乱码。原因后面第七有讲

3.拷贝

顾名思义就是将一个文件的内容复制到另外一个文件。

拷贝的核心思想就是边读边写

一个字节从文件读到程序,程序写到文件

上面这种拷贝仅适用于拷贝小文件,内存比较小的。

弊端:一次读写一个字节,太慢了,大文件拷贝不适用

优化后:一个5M的字节数组读写拷贝

五、try-with-resources

注意:try后面括号里面的流类型必须实现AutoCloseable接口,它爹实现也行。

六、字符集(ASCLL、GBK、Unicode)

ASCLL:一个字节,0~127一共128个字符

GBK:两个字节,第一个字节的第一个二进制数一定是1,所以第一个字节一定是负数,第二个字节可正可负

Unicode:不同编码规则不同字节数,以UTF-8为例 是1~4个字节(一个英文占一个字节,一个中文占3个字节)

七、读取出现乱码

1.原因

1.读取数据时未读完整个汉字

2.编码和解码的方式不统一 

2.解决方法

1.不要使用字节流读取文本文件

2.编码和解码的时候使用同一个码表,即同一个编码方式

注意:拷贝的时候,出现乱码跟使用字节流无关,使用字节流出现乱码的情况是读取单个数据的时候,拷贝是整个文件的所有字节。如果拷贝出现乱码原因就只有编码和解码的方式不统一 。

3.编码和解码

idea默认编码方式是utf-8  中文占3个字节

Eclipse则是GBK  中文占2个字节

示例

String str = "ai你余";
//编码
byte[] bytes = str.getBytes();
System.out.println(Arrays.toString(bytes));
//以GBK解码
System.out.println(new String(bytes,"GBK"));

运行结果

 

编码和解码的编码格式不一样,导致乱码。

八、字符流

 

1.特点

字符输入流:一次读一个字节,遇到中文读多个字节 (具体读几个与字符集有关)

字符输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中

2.使用场景

对于纯文本文件进行读写

3.字符输出流

(1)用法

1.创建字符输出流对象

2.写数据

3.释放资源

详解: 

1.创建字符输出流对象

前两个构造方法打开一个文件的输出流就会清空文件,如果文件不存在就创建文件,后面两个第二个参数传入true表示不会清空文件 

 2.写数据

 细节:如果write方法的参数是整数,但是实际上写到本地文件中的是整数在字符集上对应的字符

虽然字节流也有一样的int参数的write方法,但是字节流的只能传入0~127的范围,不然写到文件中的是乱码。而字符流写入文件会按照字符集来编码,超过127的编码成中文。

(2)底层原理

字符流写数据的时候是先将数据编码成字节写到缓冲区,缓冲区达到上面三种情况,就会写到文件里面。 刷新缓冲区flush和关闭流close是有区别的。

4.字符输入流

(1)用法

1.创建字符输入流对象

2.读取数据

3.释放资源

详解:

1.创建字符输入流对象

细节:如果文件不存在,就直接报错

 2.读取数据

使用无参的read方法是返回的是一个或多个(中文)的字节码的解码(已解码转十进制),要得到文件原本的内容就必须强转 (char)返回值

使用有参的read方法与字节流不同的是读到的数据用字符数组接收。

细节: 按字节进行读取,遇到中文,一次读多个字节,读取后解码,返回一个整数

           读到文件末尾了,read方法返回-1。

 3.释放资源

(2)底层原理

细节:如果缓冲区的8192个字节读完,缓冲区就会刷新,重新向文件读取新的字节数据,如果新的字节数据长度没有达到8192,新的字节数据只会覆盖缓冲数组前面的部分,后面部分保持原来的数据。

 九、字节流和字符流实战

应用场景

字节流  拷贝任意类型的文件

字符流  拷贝纯文本文件

1.拷贝文件夹

    public static void main(String[] args) throws IOException {
        File src = new File("files");
        File dest = new File("copy");
        copy(src,dest);
    }
    private static void copy(File src,File dest) throws IOException {
        if (src.exists()){
            return;
        }else if (src.isDirectory()){
            File[] files = src.listFiles();
            if (files != null) {
                for (File file : files) {
                    String name = file.getName();
                    String destPath = dest.getAbsolutePath();
                    String path = destPath+ File.separator+name;
                    File file1 = new File(path);
                    if (file.isDirectory()){
                        file1.mkdir();
                        copy(file,file1);
                    }else {
                        try (FileWriter fileWriter = new FileWriter(file1,true);
                             FileReader fileReader = new FileReader(file)) {
                            int len;
                            while ((len = fileReader.read()) != -1) {
                                fileWriter.write(len);
                                fileWriter.flush();
                            }
                        }
                    }
                }
            }
        }
    }

2.加密解密

加密就是,将一个文件写到另外一个文件的时候,对流中的每一个字节做处理,比如下面的例子就是异或一个2

解密就是,将一个无法解读的文件,写到另外一个文件,对每一个字节做解密处理,下面的例子加密时是异或一个2,那么解密就是继续异或一个2异或回来

3.将文件排序

文件里的内容是[1-9-2-6-5-4-3]

重新排序成[1-2-3-4-5-6-9]

        //1.获取文件中的数据
        FileReader fr = new FileReader("files\\test1.txt");
        StringBuilder sb = new StringBuilder();
        int len;
        while ((len = fr.read()) != -1) {
            sb.append((char) len);
        }
        //2.排序
        String[] strings = sb.toString().substring(1, sb.length() - 1).split("-");
        Integer[] arr = Arrays.stream(strings)
                .map(Integer::parseInt)
                .sorted()
                .toArray(Integer[]::new);
        //3.写出
        FileWriter fw = new FileWriter("files\\test1.txt");
        fw.write(Arrays.toString(arr).replace(", ", "-"));
        fr.close();
        fw.close();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1979244.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Radxa ROCK 3C开发板编译Opencv,支持调用树莓派摄像头模块V2

目录 1、ROCK 3C和树莓派摄像头模块V2介绍2、ROCK 3C在rsetup开启支持3、测试指令4、编译Opencv4.1 增加swap&#xff0c;确保内存够用4.2 安装依赖和下载opencv4.3 编译参考链接 5、使用opencv调用树莓派摄像头模块V2 1、ROCK 3C和树莓派摄像头模块V2介绍 ROCK 3C 是一款基于…

刷题篇 - 01

目录 题目一&#xff1a; 题目二&#xff1a; 题目三&#xff1a; 题目四&#xff1a; 题目五&#xff1a; 题目六&#xff1a; 题目七&#xff1a; 题目一&#xff1a; 387. 字符串中的第一个唯一字符 - 力扣&#xff08;LeetCode&#xff09; public int firstUniqC…

订单定时状态处理业务(SpringTask)

文章目录 概要整体架构流程技术细节小结 概要 订单定时状态处理通常涉及到对订单状态进行定期检查&#xff0c;并根据订单的状态自动执行某些操作&#xff0c;比如关闭未支付的订单、自动确认收货等. 需求分析以及接口设计 需求分析 用户下单后可能存在的情况&#xff1a; …

鸿蒙(API 12 Beta2版)NDK开发【内存管理purgeable内存开发指导】

场景介绍 HarmonyOS提供Purgeable Memory内存管理机制&#xff0c;开发者可以使用相关接口创建PurgeableMemory对象&#xff0c;从而管理purgeable内存。 开发者可以通过本指导了解在HarmonyOS应用中&#xff0c;如何使用Native层相关接口操作purgeable内存。功能包括purgeab…

Jupyter-Notebook常用操作看这一篇就够啦

来源&#xff1a; “码农不会写诗”公众号 链接&#xff1a;Jupyter-Notebook常用操作看这一篇就够啦 文章目录 01 概括02 快捷键总结03 运行外部python文件04 魔法命令4.1 运行计时4.2 查看变量与函数4.3 其它常用指令 书接上文 Jupyter-Notebook是一个基于 Web 的交互式开发环…

第十四节、受伤、死亡的逻辑和动画

一、受伤的动画效果 1齿轮控制当前动画图层的权重 2、层级 当前动画层为add&#xff0c;所以不会覆盖之前的动画层&#xff0c;而是添加一个动画层 3、受伤闪烁 调用颜色的值&#xff0c;实现受伤闪烁 4、录制动画 点击时间轴&#xff0c;插入关键帧 伤害图层选择add&…

2024华数杯C题解题思路、参考论文已出(无偿分享)~

C题&#xff1a;老外游中国 “数模加油站”团队出品~ 问题1&#xff1a; 解题思路&#xff1a; 1、数据准备&#xff1a; 导入352个城市的csv文件&#xff0c;提取每个城市中的100个景点的信息。 将每个景点的评分数据提取出来&#xff0c;形成一个包含35200个景点评分的列…

centos虚拟机restart网络后隔一会断联

1. 前言 不知道各位有没有遇到过虚拟机网络设置的坑&#xff0c;往往前一段时间用的好好的&#xff0c;突然网络又不行了无法连接外部网络&#xff0c;而且使用 service network restart 一瞬间可以&#xff0c;但是过一会就断连了… 2. 解决方案 根据对虚拟机网络的学习了解…

五、一个quad同时支持pcie和sfp两种高速接口的ref时钟配置

项目描述 上位机将截图数据通过 XDMA 写入到 FPGA 侧的 DDR 内存区域 1 中通过 axi_lite 接口给 axi_read_start 信号&#xff0c;通知 AXI_read 模块启动读取数据&#xff0c;然后通过 GTP TX 模块发送出去。经过光纤回环&#xff0c;GTP RX 端接收到数据&#xff0c;送给 AX…

今天的一件小事,亲身感受:付费是提高效率的重要途径

今天需要修改一个单页网站源码&#xff0c;有一个小问题困住我3个小时了。 毕竟我也不是专业的&#xff0c;没有系统学习过这些&#xff0c;搜答案都不知道怎么搜哈哈 吃过午饭&#xff0c;想着不能这么耗下去了&#xff0c;于是及时去了某宝&#xff0c;找到一个修改代码的 …

搭建nexus上传jar包,并结合jenkins运行项目

一、搭建nexus 1、docker拉取镜像 需要将docker原更新一下 https://blog.csdn.net/qx020814/article/details/140908006?spm1001.2014.3001.5502 docker pull sonatype/nexus3 创建nexus挂载文件、增加权限&#xff1a; mkdir docker_nexus3 mkdir docker_nexus3/nexus-data c…

TreeSize:免费的磁盘清理与管理神器,解决C盘爆满的燃眉之急

目录 TreeSize&#xff1a;免费的磁盘清理与管理神器&#xff0c;解决C盘爆满的燃眉之急 一、TreeSize介绍 二、下载安装TreeSize 2.1、下载地址 2.2、下载步骤 ​2.3、安装步骤 三、professional版的TreeSize试用 3.1、分析磁盘空间 3.2、显示拓展名统计信息 3.3、显…

将本地的业务写成成可供RPC远程调用的方法

第一步&#xff1a;首先我们先定义proto文件&#xff0c;这些proto文件将会为远程调用者提供调用的方法&#xff0c;为login方法。 2.重写UserServiceRpc类中的Login方法。 在Login中做的操作主要是&#xff0c;得到requst里面的参数&#xff0c;然后调用本地的Login方法&#…

可解释性终极追问,什么才是第一性解释?20篇CCF-A+ICLR论文给你答案

一、前言 长期以来&#xff0c;我们团队一直在思考可解释性领域的一个终极问题&#xff0c;即什么才是解释性领域的第一性原理&#xff1f;所谓第一性原理&#xff0c;目前没有一个被广泛接受的框架&#xff0c;世上本无路&#xff0c;我们需要逐渐去定义这样一个路。我们需要在…

Linux系统中的高级内核模块调试技术

引言 在Linux系统中进行高级内核模块开发时&#xff0c;调试是不可或缺的重要环节。调试技术能够帮助开发人员发现和解决代码中的错误和问题&#xff0c;提高开发效率和代码质量。本文将深入探讨Linux系统中高级内核模块调试的技术和方法&#xff0c;包括常用的调试工具、调试…

JAVA—面向对象编程高级

学习了一定基础后&#xff0c;开始更加深入的学习面向对象&#xff0c;包含static,final两个关键字&#xff0c;面向对象编程三大特征之继承和多态。以及对于抽象类&#xff0c;内部类&#xff0c;接口&#xff0c;枚举&#xff0c;泛型的学习。 目录 1.static &#xff08;…

cdn 内容分发网络

cdn 内容分发网络 CDN的全称是Content Delivery Network&#xff0c;即内容分发网络。 其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节&#xff0c;使内容传输得更快、更稳定。通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层…

Milvus与Zilliz Cloud:向量数据库高可用性的双重飞跃

向量数据库高可用性的重要性及其在现代数据分析中的关键作用 在数据爆炸式增长的今天,企业对于高效、准确地处理和分析大规模数据集的需求日益迫切。尤其是在人工智能、机器学习、图像识别、自然语言处理等领域,向量数据库因其对高维数据的高效存储与检索能力,成为了不可或…

【数据结构算法经典题目刨析(c语言)】括号匹配问题(图文详解)

&#x1f493; 博客主页&#xff1a;C-SDN花园GGbond ⏩ 文章专栏&#xff1a;数据结构经典题目刨析(c语言) 目录 一、题目描述 二、解题思路 三、代码实现 一、题目描述 二、解题思路 问题要求将三种类型括号匹配&#xff0c;其中包括顺序匹配和数量匹配 使用栈的后进先…

Linux压缩命令:zip命令详解

目录 一、概述 二、术语 三、基本语法 1、语法 2、常用选项 四、选项和示例 1. -r - 递归压缩目录及其子目录。 2. -j - 只加入文件而不保留目录结构。 3. -m - 压缩后从文件系统中删除原文件。 4. -u - 更新已存在的 ZIP 文件中的文件。 5. -q - 静默模式&#xff…