javaSE————文件IO(2)、

news2025/4/1 20:19:57

文件内容的读写——数据流

我们对于文件操作使用流对象Stream来操作,什么是流对象呢,水流是什么样的,想象一下,水流的流量是多种的,可以流100ml,也可以流1ml,流对象就和水流很像,我们可以一次读取100个字节,或者一次读取1个字节;

1,字节流

1)inputStream

先来使用inputStream,这个是字节流的输入,inputStream是抽象类,和下面的outputStream是一样的,我们需要FileInputStream来实例化对象,FileInputStream的构造方法:

签名说明
FileInputStream(File file1)可以使用file构造文件输入流
FileInputStream(String str)也可以使用文件路径构造输入流

那么inputStream有啥方法呢:

返回类型签名说明
int read()一次就读一个字节,读完了返回-1
intread(byte[] byte)一次读字节数组这么长的数据,返回-1就说明读完了
intread(byte[] byte,int start,int len)一次读取start到len的数据,读完了返回-1
voidclose()关闭输入流

用代码展示输入流:我们这里注意使用这些方法会抛异常,

InputStream inputStream = null;
        try {
            inputStream = new FileInputStream("C:/cctalk/java代码容易犯错的知识点/Demo/QQ截图20240915161600.png");
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } finally {
            inputStream.close();
        }

这里推荐使用try-with-resources,可以自动去close,为啥我们一定要去close呀,之间学数据结构都不用像c一样嗷嗷释放,因为文件操作不属于内存管理,GC垃圾回收不管他,我们嘚自己去关闭,不关闭他有什么影响呢,还记得进程中PCB中的文件描述符表吗,我们每打开一个程序就会在文件描述符表上自动创建一个固定长度的顺序表,就会申请一个表项,这个不会去扩容的,一直申请,不关闭,表项就没了;

   }
        try (InputStream inputStream = new FileInputStream("C:/cctalk/java代码容易犯错的知识" +
                "点/Demo/QQ截图20240915161600.png")){
            while (true){
                int a = inputStream.read();
                if(a==-1){
                    break;
                }
                System.out.println(a);
            }
        }

 我们在try中实例对象就相当于打卡了这个文件,如果FileInputStream爆红了,就说明文件不存在了,代码是一次只读取一个字符的情况,读到数据的时候,就会把读到的字符返回给a,因为是字节,所以会返回0-255的数值,在试试一次读取多个字节:

try (InputStream inputStream = new FileInputStream("C:/cctalk/java代码容易犯错的知识" +
                "点/Demo/QQ截图20240915161600.png")){
            while (true){
                byte[] bytes = new byte[20];
                int a = inputStream.read(bytes);
                if(a==-1){
                    break;
                }
                for (int i = 0; i < 20; i++) {
                    System.out.print(bytes[i]+" ");
                }
                System.out.println();
            }
        }

我们创建一个字节数组,每次读取固定byte.length长度的字符,再输出,看看结果

 此外呢,我们还可以通过Scanner来读取,我们在网络编程TCP协议中常常使用Scanner来代替intputStream,但是这里不太行,因为,Scanner会根据inputStreamReader把字节流转化为字符流,我们传的是一个图片,图片是二进制指令,我们需要遵守他们字节的编码方法,我们现在重新弄一个路径,试试读取字符;

我们在test中写3个哈哈哈;

InputStream inputStream = new FileInputStream("C:/cctalk/java代码容易犯错的知识点/Demo/test.txt");
        Scanner scanner = new Scanner(inputStream);
        while (scanner.hasNext()){
            String a = scanner.next();
            System.out.print(a+" ");
        }

 

2)outputStream

outputStream就是字节流的输出了,同样也是一个抽象类,需要FileOutputStream来辅助实例对象,FileOutputStream的构造方法是和FileIntputStream一样的,我们来看看OutputStream的的方法:

返回值签名说明
voidwrite(int b)写入所给的字节数据
voidwrite(byte[] b)写入长度为b.length的字节数据
int write(byte[] b,int set,int len)将字节数组从Set开始,写入len个长度
voidclose()关闭字节流
voidflush()

这里的flush我们拿出来单独说,这个是什么方法呢,我们文件IO操作的数据是很慢的,我们不可能去等这个操作,一个一个的把这些数据写入到设备中,所以我们会先把数据攒到缓冲区中,等到缓冲区满了之后我们再把这些数据一起写入设备,所以我们可以使用这个操作,来冲刷缓冲区,不等他满了,直接把数据写入设备;

还是使用代码来看看:

try (OutputStream outputStream = new FileOutputStream("C:/cctalk/java代码容易犯错的知识点/Demo/test.txt")){
            outputStream.write(97);
            outputStream.write(98);
            outputStream.write(98);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

我们写入几个字符,应该是abb;

test文档中出现了abb,哎不对呀,我们之前不是在这写了哈哈哈三个字吗,哪去了,我们的write操作是会覆盖之前的内容的,如果想要接着写我们要使用追加模式

 try (OutputStream outputStream = new FileOutputStream("C:/cctalk/java代码容易犯错的知识点/Demo/test.txt"
        ,true)){
            outputStream.write(76);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

实例化的构造方法中写true,就可以追加的写了;

这里多了一个l,再试试多行的写入

try (OutputStream outputStream = new FileOutputStream("C:/cctalk/java代码容易犯错的知识点/Demo/test.txt"
                ,true)){
            byte[] bytes = new byte[]{99,98,97,96,95};
            outputStream.write(bytes);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

我们还可以试试,如果我们没有这个test文件会怎么样呢,怎么去写入呢,

 try (OutputStream outputStream = new FileOutputStream("C:/cctalk/java代码容易犯错的知识点/Demo/test4.txt")){
            byte[] bytes = new byte[]{99,98,97,96,95};
            outputStream.write(bytes);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

我们写不存在的test4;

它自己创建了对应的文件并且写入了数据;

读数据有Scanner,那么写有没有对应的呢?有的兄弟有的,像这样的‘’‘’‘’‘’哈哈,不开玩笑了,我们还可以使用PrintWriter,来上代码:

try (OutputStream outputStream = new FileOutputStream("C:/cctalk/java代码容易犯错的知识点/Demo/test4.txt")){
            PrintWriter printWriter = new PrintWriter(outputStream);
            printWriter.print(98);
            printWriter.println(99);
            printWriter.flush();
        }  catch (IOException e) {
            throw new RuntimeException(e);
        }

 

也是可以的;


2,字符流

我们使用字节流读取二进制数据,我们为啥还要字符流呢,通过编码方式,直接得到一堆字符不香吗;

1)Reader

我们使用Reader读数据,

public static void main(String[] args) {
        try(Reader reader = new FileReader("C:/cctalk/java代码容易犯错的知识点/Demo/test4.txt")){
            while (true){
                char[] chars = new char[1024];
                int b = reader.read(chars);
                if(b==-1){
                    break;
                }
                for (int i = 0; i < b; i++) {
                    System.out.print(chars[i]);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

这就是我往test中放的,我们要注意java的编码和idea的编码方式,我这里的都是utf-8,如果不同的话是识别不出来的;

2)Writer

我们使用Writer来写入数据:

try(Writer writer = new FileWriter("C:/cctalk/java代码容易犯错的知识点/Demo/test4.txt")){
            char[] chars = new char[]{'H','E','l','l','o'};
            writer.write(chars);
            
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

2,练习

我们来几个小练习

1)扫描指定⽬录,并找到名称中包含指定字符的所有普通⽂件(不包含⽬录),并且后续询问⽤⼾是否 要删除该⽂件


public class Demo2 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要找的目录");
        String rootDir = scanner.next();
        File file = new File(rootDir);
        if(!file.isDirectory()){
            System.out.println("这不是个目录");
            return;
        }
        System.out.println("请输入要删除的关键字");
        String key = scanner.next();
        find(file,key);

    }
    public static void find(File rootDir,String key){
        File[] files = rootDir.listFiles();

        if(files==null){
            return;
        }
        for (File file:files){
            System.out.println("正在遍历"+file.getAbsoluteFile());
            if(file.isFile()){
                dealFile(file,key);
            }else {
                find(file,key);
            }
        }

    }

    public static void dealFile(File file,String key){
        if(file.getName().contains(key)){
            System.out.println("发现文件,是否要删除呢,删除输入y");
            Scanner scanner = new Scanner(System.in);
            String s = scanner.next();
            if (s.equals("y")){
                file.delete();
            }else {
                return;
            }
        }else {
            return;
        }
    }
}

代码实现,我们现在藏几个文件:

"C:\cctalk\java代码容易犯错的知识点\Demo\demo2\新建文件夹\test4.txt" 

看看他能不能把5个带关键字的都找到,

成功找到了;

2)进行普通文件的复制

"C:\cctalk\java代码容易犯错的知识点\Demo\test4.txt"

"C:\cctalk\java代码容易犯错的知识点\Demo\test1.txt"

我们把后面的文件复制到这个新建文件夹中;

public class Demo3 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入源文件路径");
        String src = scanner.next();
        File file = new File(src);
        if (!file.isFile()){
            System.out.println("输入的不是源文件路径或者源文件不存咋");
            return;
        }

        System.out.println("请输入目标文件路径");
        String destPath = scanner.next();
        File file1 = new File(destPath);
        if(!file1.getParentFile().isDirectory()){
            System.out.println("输入的目标文件路径的父目录不存在");
            return;
        }
        System.out.println(file.getAbsoluteFile());
        System.out.println(file1.getAbsoluteFile());
        try (InputStream inputStream = new FileInputStream(file);
             OutputStream outputStream =new FileOutputStream(file1)){

            while (true){
                byte[] bytes = new byte[1024];
                int a = inputStream.read(bytes);
                if(a==-1){
                    break;
                }
                outputStream.write(bytes,0,a);
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

我们就能看到

text1的数据复制到test4上了;

3)扫描指定内容并找到名称或者内容包含指定字符的文件;

C:\cctalk\java代码容易犯错的知识点

"C:\cctalk\java代码容易犯错的知识点\Demo\demo2\demo3\java.txt"

"C:\cctalk\java代码容易犯错的知识点\Demo\demo2\demo3\demo4\214.txt"

我们在第一个目录中找后面两个,第三个的内容包含java关键字的:

public class Demo4 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要搜索的内容,输入目录");
        String src = scanner.next();
        File file = new File(src);
        if(!file.isDirectory()){
            System.out.println("输入的不是目录");
            return;
        }
        System.out.println("请输入关键字");
        String key = scanner.next();
        find(file,key);

    }

    public static void find(File file,String key){
        File[] files = file.listFiles();
        if(file==null){
            return;
        }

        for (File file1:files){
            if (file1.isFile()){
                dealFile(file1,key);
            }else {
                find(file1,key);
            }
        }
    }

    public static void dealFile(File file,String k){
        if (file.getName().contains(k)){
            System.out.println("文件名包含" + file.getName());
            return;
        }

        StringBuffer stringBuffer = new StringBuffer();

        try (Reader reader = new FileReader(file)){
            while (true){
                char[] chars = new char[1024];
                int a = reader.read(chars);
                if (a==-1){
                    break;
                }
                stringBuffer.append(chars,0,a);
            }

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

        if(stringBuffer.indexOf(k)>=0){
            System.out.println("文件内容包含"+file.getName());
        }
    }
}

OK啦

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

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

相关文章

前端常问的宏观“大”问题详解(二)

JS与TS选型 一、为什么选择 TypeScript 而不是 JavaScript&#xff1f; 1. 静态类型系统&#xff1a;核心优势 TypeScript 的静态类型检查能在 编译阶段 捕获类型错误&#xff08;如变量类型不匹配、未定义属性等&#xff09;&#xff0c;显著减少运行时错误风险。例如&…

智慧电力:点亮未来能源世界的钥匙

在科技日新月异的今天&#xff0c;电力行业正经历着前所未有的变革。智慧电力&#xff0c;作为这一变革的核心驱动力&#xff0c;正逐步改变着我们对电力的认知和使用方式。它不仅是电力行业的一次技术革新&#xff0c;更是推动社会可持续发展、实现能源高效利用的重要途径。 智…

架构师面试(二十三):负载均衡

问题 今天我们聊微服务相关的话题。 大中型微服务系统中&#xff0c;【负载均衡】是一个非常核心的组件&#xff1b;在微服务系统的不同位置对【负载均衡】进行了实现&#xff0c;下面说法正确的有哪几项&#xff1f; A. LVS 的负载均衡一般通过前置 F5 或是通过 VIP keepa…

NSSCTF(MISC)—[justCTF 2020]pdf

相应的做题地址&#xff1a;https://www.nssctf.cn/problem/920 binwalk分离 解压文件2AE59A.zip mutool 得到一张图片 B5F31内容 B5FFD内容 转换成图片 justCTF{BytesAreNotRealWakeUpSheeple}

坚持“大客户战略”,昂瑞微深耕全球射频市场

北京昂瑞微电子技术股份有限公司&#xff08;简称“昂瑞微”&#xff09;是一家聚焦射频与模拟芯片设计的高新技术企业。随着5G时代的全面到来&#xff0c;智能手机、智能汽车等终端设备对射频前端器件在通信频率、多频段支持、信道带宽及载波聚合等方面提出了更高需求&#xf…

LiteDB 数据库优缺点分析与C#代码示例

LiteDB 是一个轻量级的 .NET NoSQL 嵌入式数据库,完全用 C# 开发,支持跨平台(Windows、Linux、MacOS),并提供类似于 MongoDB 的简单 API。它以单文件形式存储数据,类似于 SQLite,支持事务和 ACID 特性,确保数据的一致性和可靠性。 优缺点分析 优点: 轻量级与嵌入式:…

Linux系统中快速安装docker

1 查看是否安装docker 要检查Ubuntu是否安装了Docker&#xff0c;可以使用以下几种方法&#xff1a; 方法1&#xff1a;使用 docker --version 命令 docker --version如果Docker已安装&#xff0c;输出会显示Docker的版本信息&#xff0c;例如&#xff1a; Docker version …

CP15 协处理器

ARMv7-A 一共支持 16 个协处理器&#xff0c;编号从 CP0~CP15。这里仅对CP15进行描述。 1、ARMv7-A 协处理器 ARMv7-A 处理器除了标准的 R0~R15&#xff0c;CPSR&#xff0c;SPSR 以外&#xff0c;由于引入了 MMU、TLB、Cache 等内容&#xff0c;ARMv7-A 使用协处理器来对这些…

网络运维学习笔记(DeepSeek优化版)026 OSPF vlink(Virtual Link,虚链路)配置详解

文章目录 OSPF vlink&#xff08;Virtual Link&#xff0c;虚链路)配置详解1. 虚链路核心特性2. 基础配置命令3. 状态验证命令3.1 查看虚链路状态3.2 验证LSDB更新 4. 关键技术要点4.1 路径选择机制4.2 虚链路的链路优化 5. 环路风险案例 OSPF vlink&#xff08;Virtual Link&a…

【区块链安全 | 第十六篇】类型之值类型(三)

文章目录 函数类型声明语法转换成员合约更新时的值稳定性示例 函数类型 函数类型是函数的类型。函数类型的变量可以通过函数进行赋值&#xff0c;函数类型的参数可以用来传递函数并返回函数。 函数类型有两种类型&#xff1a;内部函数和外部函数。 内部函数只能在当前合约内调…

Kubernetes对象基础操作

基础操作 文章目录 基础操作一、创建Kubernetes对象1.使用指令式命令创建Deployment2.使用指令式对象配置创建Deployment3.使用声明式对象配置创建Deployment 二、操作对象的标签1.为对象添加标签2.修改对象的标签3.删除对象标签4.操作具有指定标签的对象 三、操作名称空间四、…

Java与代码审计-Java基础语法

Java基础语法 package com.woniuxy.basic;public class HelloWorld {//入口函数public static void main(String[] args){System.out.println("Hello World");for(int i0;i< args.length;i){System.out.println(args[i]);}} }运行结果如下: 但是下面那个没有参数…

Xenium | 细胞邻域(Cellular Neighborhood)分析(fixed radius)

上节我们介绍了空间转录组数据分析中常见的细胞邻域分析&#xff0c;CN计算过程中定义是否为细胞邻居的方法有两种&#xff0c;一种是上节我们使用固定K最近邻方法(fixed k-nearest neighbors)定义细胞Neighborhood&#xff0c;今天我们介绍另外一种固定半径范围内(fixed radiu…

Python:爬虫概念与分类

网络请求&#xff1a; https://www.baidu.com url——统一资源定位符 请求过程&#xff1a; 客户端&#xff0c;指web浏览器向服务器发送请求 请求&#xff1a;请求网址(request url)&#xff1b;请求方法(request methods)&#xff1b;请求头(request header)&…

SQLMesh调度系统深度解析:内置调度与Airflow集成实践

本文系统解析SQLMesh的两种核心调度方案&#xff1a;内置调度器与Apache Airflow集成。通过对比两者的适用场景、架构设计和操作流程&#xff0c;为企业构建可靠的数据分析流水线提供技术参考。重点内容包括&#xff1a; 内置调度器的轻量级部署与性能优化策略Airflow集成的端到…

Multism TL494仿真异常

仿真模型如下&#xff1a;开关频率少了一半&#xff0c;而且带不动负载&#xff0c;有兄弟知道为什么吗 这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码…

HarmonyOS NEXT开发进阶(十五):日志打印 hilog 与 console.log 的区别

文章目录 一、前言二、两者区别对比三、HiLog 详解四、拓展阅读 一、前言 在日常开发阶段&#xff0c;日志打印是调试程序非常常用的操作&#xff0c;在鸿蒙的官方文档中介绍了hilog这种方式&#xff0c;前端转过来的开发者发现console.log也可以进行日志打印&#xff0c;而且…

vue 权限应用

目录 一、系统菜单栏权限 二、系统页面按钮权限 在企业开发中&#xff0c;不同的用户所扮演的角色不一样&#xff0c;角色拥有权限&#xff0c;所以用户拥有角色&#xff0c;就会有角色对应的权限。例如&#xff0c;张三是系统管理员角色&#xff0c;登录后就拥有整个系统的…

鸿蒙HarmonyOS NEXT设备升级应用数据迁移流程

数据迁移是什么 什么是数据迁移&#xff0c;对用户来讲就是本地数据的迁移&#xff0c;终端设备从HarmonyOS 3.1 Release API 9及之前版本&#xff08;单框架&#xff09;迁移到HarmonyOS NEXT&#xff08;双框架&#xff09;后保证本地数据不丢失。例如&#xff0c;我在某APP…

利用 PCI-Express 交换机实现面向未来的推理服务器

在数据中心系统的历史上&#xff0c;没有比被 Nvidia 选为其 AI 系统的组件供应商更高的赞誉了。 这就是为什么新兴的互连芯片制造商 Astera Labs 感到十分高兴&#xff0c;因为该公司正在 PCI-Express 交换机、PCI-Express 重定时器和 CXL 内存控制器方面与 Broadcom 和 Marv…