【Java EE】文件IO

news2024/12/23 7:32:39

Author:MTingle
major:人工智能

---------------------------------------

Build your hopes like a tower!

目录

一、文件是什么?

二、针对文件系统操作的API

1.文件路径,文件名,文件是否存在

2. 创建文件

3.删除文件(*在线程结束时)

4. 创建File对象代表的⽬录

5. 文件改名及文件移动

三. 针对文件内容的操作(写文件 / 读文件)

1. 字节流(inputStream / outputStream)

1). 打开关闭文件 及 .read()

2). read一次读若干个字节

3). 读取汉字

4).写文件

2. 字符流(Reader / Writer)

3. 查找硬盘上文件的位置

4. 实现文件复制

3. 在目录中搜索,按照文件内容的方式搜索


一、文件是什么?

针对硬盘这种持久化存储的I/O设备,当我们想要进⾏数据保存时, 往往不是保存成⼀个整体,⽽是独⽴成⼀个个的单位进⾏保存,这个独⽴的单位就被抽象成⽂件的概 念,就类似办公桌上的⼀份份真实的⽂件⼀般。

二、针对文件系统操作的API

1.文件路径,文件名,文件是否存在

public class IODemo1 {
    public static void main(String[] args) throws IOException {
        File f=new File("./test.txt");
        System.out.println(f.exists());
        System.out.println(f.isFile());
        System.out.println(f.getName());
        System.out.println(f.getPath());
        System.out.println(f.getAbsolutePath());
        System.out.println(f.getCanonicalPath());

    }
}

2. 创建文件

public class IODemo2 {
    public static void main(String[] args) throws IOException {
        File f=new File("./test.txt");
        boolean ret=f.createNewFile();
        System.out.println("ret: "+ret);
        System.out.println(f.exists());
    }
}

3.删除文件(*在线程结束时)

public class IODemo3 {
    public static void main(String[] args) throws InterruptedException, IOException {
//        File file=new File("./test.txt");
//        boolean ret=file.delete();
//        System.out.println(ret);
        File file=new File("./test.txt");
        boolean ret=file.createNewFile();
        System.out.println("ret: "+ret);
        file.deleteOnExit();
        Thread.sleep(5000);

    }
}

4. 创建File对象代表的⽬录

public class IODemo4 {
    public static void main(String[] args) {
        File file=new File("./aaa/bbb/ccc");
        boolean ret=file.mkdirs();
        System.out.println(ret);
    }
}

5. 文件改名及文件移动

public class IODemo5 {
    public static void main(String[] args) {
        // 改名

//        File src=new File("./test.txt");
//        File dest=new File("./test2.txt");
//        src.renameTo(dest);

        // 移动文件
        File src=new File("./test2.txt");
        File dest=new File("./aaa/test2.txt");
        src.renameTo(dest);
    }
}

三. 针对文件内容的操作(写文件 / 读文件)

在进行文件操作的时候,我们在结束操作的时候一定要调用 .close() 方法关闭文件,否则就会造成 文件资源泄露 / 内存泄漏 问题.

文件描述符表记录了当前进程都打开了哪些文件,每打开一个文件,都需要在文件描述符表中占据一个位置,如果不关闭的话,一直打开会造成文件描述符表被耗尽(文件描述符表有长度上限),当文件描述符表被耗尽,就会造成一系列的逻辑问题

1. 字节流(inputStream / outputStream)

以字节为单位,一次最少读写一个字节

1). 打开关闭文件 及 .read()

public class IODemo6 {
    public static void main(String[] args) throws IOException {
        // 打开文件
//            InputStream inputStream=null;
//        try {
//           inputStream=new FileInputStream("./test.txt");
//        }finally { // 防止文件结束时未执行到关闭位置,使用finally确保文件被关闭
        //关闭文件
//            inputStream.close();
//        }

     try (InputStream inputStream=new FileInputStream("./test.txt")){
         while (true) {
             int b=inputStream.read(); // 读到文件末尾,read会返回 -1 
             if (b==-1) {
                 break;
             }
             System.out.printf("%x ",b);
         }
     }
    }
}

在此处我们更推荐使用第二种方法进行打开关闭文件,一旦出了 try 代码块,此时 try 自动帮我们调用inputStream的close方法.

此处的read方法,看起来是 int 类型,实际上是 byte ,实际的取值是 0- 255 ,此处有一个特殊情况,若读到文件末尾,则返回 -1 ,所以使用 int .

使用无参数版本,每次调用读取一个字节,返回值就表示读到的这个字节的值.

有参数版本中, offset 在此处表示偏移量

2). read一次读若干个字节

public class IODemo7 {
        public static void main(String[] args) throws IOException {
            // 一次读若干个字节
        try (InputStream inputStream=new FileInputStream("./test.txt")){
        while (true) {
           byte[] buffer=new byte[1024];
           int n=inputStream.read(buffer);
            if (n==-1) {
                break;
            }
            for (int i = 0; i < n; i++) {
                System.out.printf ("%x ",buffer[i]);
            }

        }

        }
    }

}

read 的第二三个版本,返回的 int 表示实际读取的字节个数, buffer 是一个常见的术语,表示 "缓冲区",往往是一个内存空间,读文件就是把硬盘数据读取到内存中,上面这种写法,一次读取若干个字节,会比一次读取一个高效,类似的,一次写若干个字节,也比一次写一个字节更高效,操作硬盘本身就是一个比较低效的操作,期望低效的操作出现的次数越少越好,这样效率就会更高

3). 读取汉字

public class IODemo8 {
    public static void main(String[] args) throws IOException {
        // 一次读若干个字节(汉字)
        try (InputStream inputStream=new FileInputStream("./test.txt")){

            while (true) {

                byte[] buffer=new byte[1024];
                int n=inputStream.read(buffer);
                if (n==-1) {
                    break;
                }
                String s=new String(buffer,0,n);
                System.out.println(s);

            }


        }
    }
}

此处的 String 是通过前 n 个字节构造,而不是整个数组,实际读取的文件内容可能不足1024

4).写文件

写文件与读文件类似,三个版本的含义也相似

public class IODemo9 {
    public static void main(String[] args) throws IOException {
//        try (OutputStream outputStream=new FileOutputStream("./test.txt")){
//            byte[] buffer=new byte[]{97,98,99,100,101,102};
//            outputStream.write(buffer);
//
//        }

        try (OutputStream outputStream=new FileOutputStream("./test.txt",true)){
            byte[] buffer=new byte[]{97,98,99,100,101};
            outputStream.write(buffer);
        }
    }
}

注释部分与未注释的部分的区别为少了一个 true ,当我们实施写操作打开文件的时候,注释版本中没有填 true ,系统默认为 false ,此时当我们打开文件时,会清空文件之前的所有内容,若我们不想把文件原来的内容清空,而是继续往下写文件,将内容写到文件的末尾,我们需要在末尾加上一个 true ,此时我们打开文件时就不会将原有的内容清空.

此处的参数 append 的含义为追加.

2. 字符流(Reader / Writer)

以字符为单位进行读写,一次最少读写一个字符,在utf8中,一个汉字需要三个字节来表示,所以读写汉字的时候,每次读写都需要以3个字节为单位进行,不能一次读写半个汉字. Reader 和 Writer 的使用和 inputStream outputStream 类似.只不过此时是按照 char 为单位操作了

public class IODemo10 {
    public static void main(String[] args) throws IOException {
        // 字符流读
//        try (Reader reader=new FileReader("./test.txt")) {
//            while (true) {
//                char[] buffer = new char[1024];
//                int n = reader.read(buffer);
//                if (n==-1) {
//                    break;
//                }
//                String s = new String(buffer, 0, n);
//                System.out.println(s);
//            }
//        }

    // 字符流写
    try (Writer writer=new FileWriter("./test.txt")){
        String s="你好啊";
        writer.write(s);
    }

    }
}

此处的代码里,有一个关键问题, char 占两个字节,但是我们的汉字是占3个字节(utf8),但是此处读取来的每个字节咋就成2个字节了呢?

此处这个代码,相当于把当前文件的 utf8 在按照字符读取的时候,先转换成 unicode ,每个 char 中存储的是对应的 unicode 的值,如果是基于 unicode 最终还可以构造回 utf8 的 String.

文件utf8 => char[] unicode => String utf8

上述的替换过程我们无法直接感知到, java 里面已经封装好了.

public class IODemo11 {
    public static void main(String[] args) {
        try (Writer writer=new FileWriter("./test.txt")){
            String s="你好啊";
            writer.write(s);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

Scanner 也可以辅助我们进行读文件, Scanner(System.in) ,括号内部本质上就是一个 inputStream.

public class IODemo12 {
    public static void main(String[] args) throws FileNotFoundException {
        try (InputStream inputStream=new FileInputStream("./test.txt")){
            Scanner scanner=new Scanner(inputStream);
            while (scanner.hasNextLine()) {
                String s=scanner.next();
                System.out.println(s);
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

3. 查找硬盘上文件的位置

public class IODemo13 {

    // 查找硬盘上的文件位置
    public static void main(String[] args) {
    Scanner scanner=new Scanner(System.in);
        System.out.println("请输入文件名: ");
        String fileName=scanner.next();
        System.out.println("请输入文件目录: ");
        String rootPath=scanner.next();
        File rootFile=new File(rootPath);
        if (!rootFile.isDirectory()) {
            System.out.println("输入文件目录有误!");
            return;
        }
        scanDir(fileName,rootFile);

    }

    private static void scanDir(String fileName, File rootPath) {
        File[] files=rootPath.listFiles();
        if (files==null) {
            return;
        }
        for (File f:files) {
      //      System.out.println("查找中,当前路径为: "+f.getAbsolutePath());
            if (f.isDirectory()) {
                scanDir(fileName,f);
            }else if (f.isFile()) {
                if (fileName.equals(f.getName())) {
                    System.out.println("找到了,绝对路径为: "+f.getAbsolutePath());
                }
            }else {
                ;
            }
        }
    }
}

此处我们使用递归,就是要进行树的遍历,把目录中,以及其中的子目录,所有的文件都遍历一遍,看是否有符合要求的

4. 实现文件复制

public class IODemo14 {
    // 复制文件
    public static void main(String[] args) throws IOException {
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入要复制的源文件: ");
        String srcPath=scanner.next();
        System.out.println("请输入要复制的目标文件: ");
        String destPath=scanner.next();

        // 检查文件合理性
        // 1.复制的源文件
        File srcFile=new File(srcPath);
        if (!srcFile.isFile()) {
            System.out.println("源文件路径有误!");
            return;
        }
        // 2.目标文件
        File destFile=new File(destPath);
        if (!destFile.getParentFile().isDirectory()) {
            System.out.println("目标文件路径有误!");
            return;
        }

        try (InputStream inputStream=new FileInputStream(srcPath);
            OutputStream outputStream=new FileOutputStream(destPath)){

            while (true) {
                // 把内容读到inputStream
                byte[] buffer=new byte[1024];
                int n=inputStream.read(buffer);
                if (n==-1) {
                    break;
                }

                // 把内容写到outputStream
                outputStream.write(buffer,0,n);
            }

        }


    }
}

把一个文件复制一下,成为另一个文件,就是把第一个文件读方式打开,一次读取出这里的每个字节,再把读到的内容写入另一个文件里.

3. 在目录中搜索,按照文件内容的方式搜索

public class IODemo15 {
    public static void main(String[] args) throws IOException {
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入要查找的路径: ");
        String rootPath=scanner.next();
        System.out.println("请输入要查找的词: ");
        String word=scanner.next();


        // 检查路径合理性
        File rootFile=new File(rootPath);
        if (!rootFile.isDirectory()) {
            System.out.println("查询路径有误!!!");
            return;
        }

        // 开始查找
        scanDir(word,rootFile);

    }

    private static void scanDir(String word, File rootFile) throws IOException {
        File[] files=rootFile.listFiles();

        if (files==null) {
            return;
        }

        for (File f:files) {
            System.out.println("当前遍历到: "+f.getAbsolutePath());
            // 1.找到对应目录
            if (f.isFile()) {
                searchInFile(word,f);
            }else if (f.isDirectory()) {
                scanDir(word,f);
            }else {
                ;
            }
        }
    }

    private static void searchInFile(String word, File f) throws IOException {
        try (InputStream inputStream=new FileInputStream(f);){
            // 拼接字符
            StringBuilder stringBuilder=new StringBuilder();
            while (true) {
                byte[] buffer=new byte[1024];
                int n=inputStream.read(buffer);
                if (n==-1) {
                    break;
                }
                String string=new String(buffer,0,n);
                stringBuilder.append(string);
            }
            // 字符匹配
            if (stringBuilder.indexOf(word)!=-1) {
                System.out.println("找到了"+word+"路径为: "+f.getAbsolutePath());
                return;
            }

        }
    }
}

用户输入一个目录,一个要搜索的词,遍历文件的过程中没如果文件包含了要搜索的词,此时就把文件的路径打印出来.


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

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

相关文章

推动公平学习与身份归一化的视网膜神经疾病数据集

人工智能咨询培训老师叶梓 转载标明出处 在机器学习领域&#xff0c;公平性&#xff08;也称为公正性或平等性&#xff09;是一个日益受到关注的话题&#xff0c;它对于社会的福祉至关重要。然而&#xff0c;目前缺乏专门用于公平学习且包含成像数据的公共医学数据集&#xff…

vs2022配置opencv==4.9.0(C++)

1、下载opencv-windows [opencv4.9.0下载地址](Releases - OpenCV) 下载4.9.0版本&#xff1a; 双击下载好的opencv-4.9.0-windows.exe&#xff0c;选择安装路径&#xff1a; 2、配置opencv环境 &#xff08;1&#xff09;添加系统环境变量 此电脑–>右键“属性”–…

小红书治愈插画副业,猛猛涨粉上万+,每天只用5分钟

在这个数字化时代&#xff0c;AI技术正以前所未有的速度改变着我们的生活和工作。特别是在内容创作领域&#xff0c;AI的运用已经催生了一种全新的创作模式。一幅幅温馨可爱的治愈插画如同清流&#xff0c;不仅契合当下年轻人生活的状态&#xff0c;更成为许多人表达生活态度、…

「iOS」push与present

iOS学习 前言push与poppresent与dismiss使用dismiss弹出多级PresentedViewController 与 PresentingViewController区别 总结 前言 在此前就学习过视图的push与present。与之对应的退出方法为pop与dismiss。这里进行一次总结。 push与pop pushViewController 是通过导航控制器…

黑神话:悟空 后话

《黑神话&#xff1a;悟空》在游戏界掀起了波澜。对许多人来说&#xff0c;包括我自己&#xff0c;这款游戏是我们一直期待的——一款纯粹、沉浸且专注于高质量游戏体验的作品。它不追求现代趋势&#xff0c;没有微交易或在线服务模式&#xff0c;也没有为了未来扩展包而设计的…

PumpkinFestival靶机详解

靶机下载地址 https://www.vulnhub.com/entry/mission-pumpkin-v10-pumpkinfestival,329/ 靶机配置 主机发现 arp-scan -l 端口扫描 nmap -sS -Pn -A -p- -n 192.168.229.163 访问网页 http://192.168.229.163/ 这些可能是用户名和账号留存 F12查看页面源码&#xff0c;发…

瑞芯微RK3588开发板Linux系统添加自启动命令的方法,深圳触觉智能Arm嵌入式鸿蒙硬件方案商

本文适用于触觉智能所有Linux系统的开发板、主板添加自启动命令的方法&#xff0c;本次使用了触觉智能的EVB3588开发板演示&#xff0c;搭载了瑞芯微RK3588旗舰芯片。 该开发板为核心板加底板设计&#xff0c;为工业场景设计研发的模块化产品&#xff0c;10年以上稳定供货,帮助…

2024年9月18日历史上的今天大事件早读

1043年9月18日 范仲淹实行改革 1393年9月18日 “活财神”沈万三逝世 1783年9月18日 瑞士著名数学家欧拉逝世 1851年9月18日 《纽约时报》创刊 1903年9月18日 清末爱国将领冯子材逝世 1917年9月18日 护法战争爆发 1931年9月18日 “九一八”事变爆发 1936年9月18日 阎锡山…

SOMEIP_ETS_115: SD_Entry_references_more_options_than_exist

测试目的&#xff1a; 验证DUT能够拒绝一个订阅请求&#xff0c;该请求中的选项引用超出了实际存在的选项数量&#xff0c;并以SubscribeEventgroupNAck作为响应。 描述 本测试用例旨在确保DUT遵循SOME/IP协议&#xff0c;当接收到一个引用了比实际存在的更多选项的Subscrib…

SPI中的CPOL和CPHA

SPI中的CPOL和CPHA学习SPI必须掌握的知识&#xff0c;因为它涉及到“数据位采集”。重点掌握空闲时SCK的电平是怎么定义的。采集时&#xff0c;是怎么规定发生在哪个时钟边沿。CPOL用来决定SPI总线在空闲时,SPI_SCK引脚输出的电平;CPHA用来决定“数据位采集点”发生在第几边沿。…

【Python】从基础到进阶(八):文件操作与上下文管理

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、引言二、Python文件操作基础1. 打开文件2. 读取文件3. 写入文件4. 文件指针定位 三、上下文管理1. 使用with管理文件2. 自定义上下文管理器 四、文件操作的最佳实践五、案例&#xff1a;日志文件管理1. 需求分析2. 实现…

低代码技术:简化应用开发的未来

近年来&#xff0c;低代码技术作为一种新兴的应用开发方法&#xff0c;受到了广泛关注。低代码平台通过图形化的界面和预设的模块&#xff0c;使得用户能够以较少的代码编写工作创建应用程序。这一技术的发展&#xff0c;标志着软件开发过程中的一个重要变革。 低代码技术的基…

【Linux系统编程】第二十弹---进程优先级 命令行参数 环境变量

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、进程优先级 2.1、什么是优先级 2.2、优先级的描述 2.3、优先级与权限的关系 2.4、为什么要有优先级 2.5、Linux优先级的…

【产品更新】中汇保函及汇匠源保证金保函平台

中汇保函 新增 1.新增小程序查询验证功能&#xff0c;手机输入即可查验。 2.新增小程序客户案例案例&#xff0c;合作单位及案例展示页面。 3.履约保函、预付款保函、质量保函、工程款支付保函订单提交及订单状态查验。 4.PC产品官网已经上线&#xff0c;可随时访问了解产品介…

【Java】synchronized 基础线程安全

欢迎浏览高耳机的博客 希望我们彼此都有更好的收获 感谢三连支持&#xff01; 在多线程编程中&#xff0c;线程安全是一个至关重要的概念。Java 提供了多种机制来处理线程安全问题&#xff0c;其中 synchronized 关键字是最常用和最基础的一种。本文将介绍线程安全问题的原因&a…

智创未来,景联文科技提供全方位数据采集服务

随着科技的日新月异&#xff0c;人工智能技术正在改变我们的生活与工作方式&#xff0c;数据成为推动人工智能&#xff08;AI&#xff09;技术发展的基石。 高质量的数据对于训练机器学习模型、提升算法性能以及实现智能应用的广泛部署至关重要。 景联文科技凭借卓越的技术实力…

Android14请求动态申请存储权限

Android14请求动态申请存储权限 Android14和Android15存储权限有增加多了选择部分&#xff0c;还是全部。一个小小的存储权限真的被它玩出了花来。本来Android13就将存储权限进行了3个细分&#xff0c;是图片&#xff0c;音频还是视频文件。 步骤一&#xff1a;AndroidManife…

六种主流ETL工具的比较与Kettle的实践练习指南--MySQL、hive、hdfs等之间的数据迁移

在数据集成和数据仓库建设中&#xff0c;ETL&#xff08;Extract, Transform, Load&#xff09;工具扮演着至关重要的角色。本文将对六种主流ETL工具进行比较&#xff0c;并深入探讨Kettle的实践应用。 一、六种主流ETL工具比较 1. DataPipeline 设计及架构&#xff1a;专为…

Python异常处理:自定义异常②

文章目录 1. 什么是自定义异常&#xff1f;2. 为什么需要自定义异常&#xff1f;3. 如何定义自定义异常&#xff1f;3.1 基本自定义异常3.2 带详细信息的自定义异常3.3 自定义异常的继承层次 4. 使用自定义异常4.1 抛出自定义异常4.2 捕获自定义异常 5. 自定义异常的应用场景5.…

【C++】透析string类

个人主页&#xff1a;CSDN_小八哥向前冲~ 所属专栏&#xff1a;C入门 目录 string类介绍 auto和范围for auto关键字 范围for string类常用接口说明 string类常见构造 string类容量操作 string类的访问及遍历操作 string类修改操作 string的结构说明 vs下的结构 G下的…