文件内容的读写 (IO) —— 数据流

news2024/11/28 8:37:18

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

  • 一、什么是数据流
  • 二、字节流输入InputStream
    • 2.1 InputStream 概述
    • 2.2 FileInputStream 的使用
  • 三、字节流输出OutputStream
    • 3.1 OutputStream 概述
    • 3.2 FileOutputStream 的使用
  • 四、字符流输入 Reader
    • 4.1 Reader 与 FileReader
    • 4.2 利用 Scanner 进行字符读取
  • 五、字符流输出 Writer
    • 5.1 Writer 与 FileWriter
    • 5.2 利用 PrintWriter 进行字符写入
  • 六、内存泄漏问题
  • 七、例题

一、什么是数据流

在这里插入图片描述

流:stream
把读写文件操作比喻成"水流",水的特点:流动起来绵延不断~~
在这里插入图片描述
在这里插入图片描述

输入还是输出,是以CPU/内存为中心来判断!!!

二、字节流输入InputStream

2.1 InputStream 概述

方法

返回值类型方法签名说明
intread()读取一个字节的数据,返回 -1 代表已经完全读完了
intread(byte[] b)最多读取 b.length 字节的数据到 b 中,返回实际读到的数量;-1 代表以及读完了
intread(byte[] b, int off, int len)最多读取 len - off 字节的数据到 b 中,从 off 开始放入,返回实际读到的数量;-1 代表以及读完了
voidclose()关闭字节流

说明
InputStream 只是一个抽象类,要使用还需要具体的实现类。关于 InputStream 的实现类有很多,基本可以认为不同的输入设备都可以对应一个 InputStream 类,我们现在只关心从文件中读取,所以使用 FileInputStream

2.2 FileInputStream 的使用

构造方法

签名说明
FileInputStream(File file)利用 File 构造文件输入流
FileInputStream(String name)利用文件路径构造文件输入流

在这里插入图片描述
代码示例

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class Demo {
    public static void main(String[] args) throws IOException {
        InputStream inputStream = new FileInputStream("./bbb.txt");  // 内容为"hello world"
        while (true) {
            int b = inputStream.read();
            if (b == -1) {
                break;
            }
            System.out.println(b);
        }
        inputStream.close();
    }
}

运行结果:
在这里插入图片描述

三、字节流输出OutputStream

3.1 OutputStream 概述

方法

返回值类型方法签名说明
voidwrite(int b)写入要给字节的数据
voidwrite(byte[] b)将 b 这个字符数组中的数据全部写入 os 中
intwrite(byte[] b, int off, int len)将 b 这个字符数组中从 off 开始的数据写入 os 中,一共写 len 个
voidclose()关闭字节流
voidflush()重要:我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置,调用 flush(刷新)操作,将数据刷到设备中。

说明
OutputStream 同样只是一个抽象类,要使用还需要具体的实现类。我们现在还是只关心写入文件中,所以使用 FileOutputStream。

3.2 FileOutputStream 的使用

构造方法

签名说明
FileOutputStream(File file)利用 File 构造文件输出流
FileOutputStream(String name)利用文件路径构造文件输出流

在这里插入图片描述
代码示例

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Demo {
    // 进行写文件
    public static void main(String[] args) throws IOException {
        OutputStream outputStream = new FileOutputStream("./bbb.txt");

        outputStream.write(97);
        outputStream.write(98);
        outputStream.write(99);

        outputStream.close();
    }
}

四、字符流输入 Reader

4.1 Reader 与 FileReader

同样,Reader是一个抽象类,需要实现类FileReader!

方法
在这里插入图片描述
代码示例

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class Demo {
    public static void main(String[] args) throws IOException {
        // 使用字符流读文件
        Reader reader = new FileReader("./bbb.txt");
        while (true) {
            int ret = reader.read();
            if (ret == -1) {
                break;
            }
            char ch = (char)ret;
            System.out.println(ch);
        }
        reader.close();
    }
}

4.2 利用 Scanner 进行字符读取

上述例子中,我们看到了对字符类型直接使用 InputStream 进行读取是非常麻烦且困难的,所以,我们使用一种我们之前比较熟悉的类来完成该工作,就是 Scanner 类。

构造方法

签名说明
Scanner(InputStream is, String charset)使用 charset 字符集进行 is 的扫描读取

代码示例

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;

public class Demo {
    public static void main(String[] args) throws IOException {
        // 使用 Scanner 读文本文件
        InputStream inputStream = new FileInputStream("./bbb.txt");

        Scanner scanner = new Scanner(inputStream);
        while (scanner.hasNext()) {
            System.out.println(scanner.next());
        }

        inputStream.close();
    }
}

五、字符流输出 Writer

5.1 Writer 与 FileWriter

同样,Writer是一个抽象类,需要实现类FileWriter!

方法
在这里插入图片描述

代码示例

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class Demo {
    public static void main(String[] args) throws IOException {
        // 使用字符流来写文件.
        Writer writer = new FileWriter("./bbb.txt");
        writer.write("hello world");
        writer.close();
    }
}

5.2 利用 PrintWriter 进行字符写入

代码示例

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;

public class Demo {
    public static void main(String[] args) throws IOException {
        // 针对写文本文件来说, 还可以使用 PrintWriter 来简化开发.
        try (OutputStream outputStream = new FileOutputStream("./bbb.txt")) {
            PrintWriter writer = new PrintWriter(outputStream);

            writer.println();
            writer.printf("a = %d\n", 10);
        }
    }
}

若没有写进文件中,可能是因为没有刷新缓冲区,此时可以调用 flush() 方法!!!

在这里插入图片描述

在这里插入图片描述

六、内存泄漏问题

在这里插入图片描述

客户端一般不害怕这种资源泄露问题 (客户端程序用一会儿就关了);服务器是害怕这种问题的 (服务器需要长期运行)!!!

一些代码中,如果 close() 前面代码抛出异常了,此时 close() 就执行不到了!因此我们通常要使用 finally 或 try with resources 结构来避免内存泄漏问题!!!:
把要关闭的对象写到 try() 里,当 try 结束,就会自动调用到对应对象的 close() 方法!
并且支持一个 () 放多个对象,多个对象的创建之间使用 ; 分隔就行了~~

七、例题

例一: 扫描指定目录,并找到名称中包含指定字符的所有普通文件 (不包含目录),并且后续询问用户是否要删除该文件

在这里插入图片描述
代码实现:

import java.io.File;
import java.io.IOException;
import java.util.Scanner;

public class Demo {
    public static void main(String[] args) throws IOException {
        // 1. 让用户输入了必要的信息
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要扫描的路径: ");
        File rootDir = new File(scanner.next());
        if (!rootDir.isDirectory()) {
            System.out.println("您输入的目录不存在!");
            return;
        }
        System.out.println("请输入要搜索的关键词: ");
        String toDelete = scanner.next();

        // 2. 遍历目录, 需要借助一个核心方法, listFiles()
        scanDir(rootDir, toDelete);
    }

    // 借助这个方法进行递归遍历
    private static void scanDir(File rootDir, String toDelete) throws IOException {
        System.out.println("当前访问: " + rootDir.getCanonicalPath());
        File[] files = rootDir.listFiles();
        if (files == null) {
            // 说明 rootDir 是一个空的目录~~
            return;
        }
        // 如果目录非空, 则循环遍历每个元素.
        for (File f : files) {
            if (f.isDirectory()) {
                scanDir(f, toDelete);
            } else {
                // 不是目录, 普通文件, 判定文件名是否符合要求, 是否要进行删除
                checkDelete(f, toDelete);
            }
        }
    }

    private static void checkDelete(File f, String toDelete) throws IOException {
        if (f.getName().contains(toDelete)) {
            System.out.println("该单词" + toDelete + " 被 " + f.getCanonicalPath() + " 包含了, 是否要删除? (Y/N)");
            Scanner scanner = new Scanner(System.in);
            String choice = scanner.next();
            if (choice.equals("Y") || choice.equals("y")) {
                f.delete();
            }
        }
    }
}

例二: 进行普通文件的复制

在这里插入图片描述
代码实现:

import java.io.*;
import java.util.Scanner;

public class Demo {
    public static void main(String[] args) {
        // 实现文件复制.
        // 1. 先输入要复制哪个文件(源文件), 以及把这个文件复制到哪里去(目标文件)~~
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入源文件: ");
        // srcFile 形如 d:/cat.jpg
        File srcFile = new File(scanner.next());
        System.out.println("请输入目标文件: ");
        // destFile 形如 d:/cat2.jpg
        File destFile = new File(scanner.next());
        if (!srcFile.isFile()) {
            System.out.println("输入的源文件有误!");
            return;
        }
        if (!destFile.getParentFile().isDirectory()) {
            System.out.println("输入的目标文件有误!");
            return;
        }
        if (destFile.isDirectory()) {
            System.out.println("输入的目标文件有误!");
            return;
        }
        // 2. 打开源文件, 按照字节读取内容, 依次写入到目标文件中.
        try (InputStream inputStream = new FileInputStream(srcFile);
             OutputStream outputStream = new FileOutputStream(destFile)) {
            // 读 src 的每个字节, 写入到 dest 中.
            while (true) {
                int ret = inputStream.read();
                if (ret == -1) {
                    break;
                }
                outputStream.write(ret);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

例三: 扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)

在这里插入图片描述
代码实现:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;

public class Demo {
    public static void main(String[] args) throws IOException {
        // 1. 输入路径和要查询的关键词
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要扫描的路径: ");
        File rootDir = new File(scanner.next());
        System.out.println("请输入要查询的词: ");
        String toFind = scanner.next();

        // 2. 递归的扫描目录.
        scanDir(rootDir, toFind);
    }

    private static void scanDir(File rootDir, String toFind) throws IOException {
        File[] files = rootDir.listFiles();
        if (files == null) {
            return;
        }
        for (File f : files) {
            if (f.isDirectory()) {
                scanDir(f, toFind);
            } else {
                checkFile(f, toFind);
            }
        }
    }

    private static void checkFile(File f, String toFind) throws IOException {
        // 1. 先检查文件名
        if (f.getName().contains(toFind)) {
            System.out.println(f.getCanonicalPath() + " 文件名中包含 " + toFind);
        }
        // 2. 再检查文件内容
        try (InputStream inputStream = new FileInputStream(f)) {
            StringBuilder stringBuilder = new StringBuilder();
            Scanner scanner = new Scanner(inputStream);
            // 这个地方需要按行读取了~~
            while (scanner.hasNextLine()) {
                stringBuilder.append(scanner.nextLine() + "\n");
            }
            if (stringBuilder.indexOf(toFind) > -1) {
                System.out.println(f.getCanonicalPath() + " 文件内容包含 " + toFind);
            }
        }
    }
}

注意:我们现在的方案性能较差,所以尽量不要在太复杂的目录下或者大文件下实验!!!

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

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

相关文章

[Java]图论进阶--最小生成树算法

专栏简介 :MySql数据库从入门到进阶. 题目来源:leetcode,牛客,剑指offer. 创作目标:记录学习MySql学习历程 希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长. 学历代表过去,能力代表现在,学习能力代表未来! 目录 1. 最小生成树 1.1 Kruskal(克鲁斯卡尔) 算法 …

计算机毕设Python+Vue校园社团信息管理系统(程序+LW+部署)

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

Teams app LukcyDraw 的升级之路

我已经有很长一段时间没有更新我的 Teams App:LuckyDraw 了,有很多用户反馈给我,因为快到圣诞,新年和春节了,很多公司都开始要使用LuckyDraw来搞抽奖活动,希望LuckyDraw能支持大用户量的抽奖,所…

当打造一款极速湖分析产品时,我们在想些什么

作者:王有卓,StarRocks Contributor 随着开源数据湖技术的快速发展以及湖仓一体全新架构的提出,传统数据湖在事务处理、流式计算以及数据科学场景的限制逐渐得以优化解决。 为了满足用户对数据湖探索分析的需求,StarRocks 在 2.…

jsp+ssm计算机毕业设计ssm实验教学资源管理系统【附源码】

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: JSPSSM mybatis Maven等等组成,B/S模式 Mave…

【linux】linux实操篇之进程管理

目录前言进程介绍和查询进程基本介绍显示系统执行的进程终止进程服务管理监控服务动态监控进程监控网络状态结语前言 本篇博客总结linux中的进程管理相关知识,主要有进程介绍,终止进程,服务管理以及监控服务,一起来看看吧&#x…

模拟电路设计(40)---你真的懂“接地”吗?

概念 接地是指将一个电路、设备乃至分系统与一个基准“地”电位连接的电气要求,目的在于提供一个等电位点或等电位面。接地可以接真正的大地,也可以不接,例如飞机上的电子电气设备接飞机机壳就是接地。 接地必须有接地导体和接地平面才能够…

ChatGPT和InstructGPT 对比,ChatGPT将改变世界,影响力不亚于2007年新一代iPhone智能手机的发布

ChatGPT ChatGPT 的模型,它以对话方式进行交互。对话格式使 ChatGPT 可以回答后续问题、承认错误、挑战不正确的前提并拒绝不适当的请求。ChatGPT 是InstructGPT的兄弟模型,它经过训练可以按照提示中的说明进行操作并提供详细的响应。 ChatGPT 网址&am…

vue打包优化一

webpack.dll.config.js配置 相关文章 https://www.cnblogs.com/echoyya/p/16413591.html 步骤一:创建webpack.dll.config.js(不一定要是这个名字,只要执行指令的时候路径正确就行) // webpack.dll.config.js const path requi…

FIX:FusionCharts Suite XT 3.19.x

FusionCharts Suite XT:探索 100 多张图表和 2000 多张地图 FusionCharts 提供了 100 多张图表和 2000 多张地图。凭借广泛的文档、一致的 API 和一系列自定义选项 - FusionCharts 是最全面的 JavaScript 图表库,受到全球 750,000 名开发人员的喜爱。Fus…

JAVA实训第四天

目录 异常 什么是异常? 为什么要进行异常处理? 方法的调用堆栈 方法调用堆栈中异常对象的传递 Java中的异常类 常见的异常类 常见的异常类及出现此异常的原因 •1、java.lang.NullpointerException(空指针异常) •2、 java.lang.ClassNotFoundExcept…

rocketmq源码-broker接收消息

前言 这篇笔记,主要记录producer在通过netty发送了请求之后,在broker这边是如何处理的消息的 org.apache.rocketmq.remoting.netty.NettyRemotingServer.NettyServerHandler#channelRead0 这里是broker的nettyServer端接收客户端发送消息的入口&#x…

Android中GRPC的使用-4种通信模式

GRPC的通信模式 GRPC四种基础通信模式:一元RPC、服务器端流RPC、客户端流RPC以及双向流RPC。下面分别四种模式进行介绍,并在Android环境中来实现服务和客户端。 一元RPC 一元RPC模式也被称为简单RPC模式。在该模式中,当客户端调用服务端的远程…

破记录!国产数据库KunDB 单节点TPC-C事务性能超180万tpmC

近日,星环科技KunDB在TPC-C事务性能测试中,采用常规国产服务器,实现了单节点tpmC超180万,体现其世界级领先的事务处理能力。 TPC-C是全球 OLTP 数据库最权威的性能测试基准,由TPC组织(国际事务性能委员会&…

【数字IC基础】TestBench功能

文章目录 一、TestBench的目的?二、TestBench的功能?三、TestBench(验证)的四要素?一、TestBench的目的? 对使用硬件描述语言(HDL)设计的电路(DUT)进行仿真验证,测试设计电路的功能、部分性能是否符合预期二、TestBench的功能? TestBench和DUT的关系是一个马蹄形结…

React - 项目初始化设置

React - 项目初始化设置一. 页面零边距二. 路径别名配置三. 安装使用 scss四. 安装 router一. 页面零边距 可以手写 css 重置页面样式,也可使用 reset-css 自动配置 手写样式不多说,这里使用 reset-css 安装依赖 yarn add reset-css src/App.js 文件中引…

阿里技术人分享的三本书豆瓣评分8.5分,让你的架构思维略窥门径

又逢“金九银十”,年轻的毕业生们满怀希望与忐忑,去寻找、竞争一个工作机会。已经在职的开发同学,也想通过社会招聘或者内推的时机争取到更好的待遇、更大的平台。 然而,面试人群众多,技术市场却相对冷淡,…

ssm+Vue计算机毕业设计校园疫情管理系统(程序+LW文档)

ssmVue计算机毕业设计校园疫情管理系统(程序LW文档) 项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技…

我用了几行代码就实现了界面变灰效果

前言 前段时间,各个大厂的 App 首页都变成了灰色,网上还有不少人问界面变灰怎么做到的。有人说是后台换了图片,这个回答显然是不懂技术了,对于个性化推荐系统来说,使用的图片那么多张,怎么可能一一替换。还有一种说法是说后台将图片处理后再返回给前端的,这个显然也不太…

$ORACLE_BASE和$ORACLE_HOME下xml文件误删

问题描述: 某项目安装环境grid管理的oracle,环境已经搭建好许久,执行上线检查PSU版本时发现opatch lsinventory报错 但实例的sqlpatch显示已经应用成功且oracle client版本也显示为19.13 怀疑是Central Inventory(/oracle/oraInv…