JavaEE(系列18) -- 文件操作I/O

news2024/11/22 16:22:33

前言:

        我们平时所说的文件都是指硬盘上的文件,而我们之前在JavaSE阶段代码绝大部分都是围绕内存展开的,定义个变量,其实就是内存上申请空间。

内存和硬盘的区别:

  • 速度:内存比硬盘快很多。
  • 空间:内存空间比硬盘小。
  • 成本:内存比硬盘贵一点。 

那么我们接下来的知识是如何通过Java进行操作硬盘上的文件. 

目录

1. 文件路径

2. 文件分类

3. 文件系统操作

3.1 构造File对象

3.2 File属性

3.3 构造方法

3.4 Fiel类的方法

4. 文件的读写(数据流) 

4.1 IO流原理 

4.2 流的分类 

4.2.1 字节流

4.2.2 字符流

5. 小练习

6. 如何按照进行读P(通常使用Scanner)

7. 如何按照行进行写(通常使用PrintWriter)


1. 文件路径

 上图就是我们通过电脑的文件系统产看到的文件路径

1. 文系统是以树型结构来组织文件和目录的。N叉树。

文件路径就是以树根节点出发,沿着树杈,一路往下走,到达目标文件,此时这中间经过的内容、

Windows都是以“此电脑”起头的。表示路径的时候,可以把“此电脑”省略,直接从盘符开始表示。

实际表示路径,是通过一个字符串表示,每个目录之间使用斜杠/来分割.

 2. 除了可以从根开始进行路径的描述,我们可以从任意结点出发,进行路径的描述,而这种描述方式就被称为相对路径(relative path),相对于当前所在结点的一条路径.

2. 文件分类

     即使是普通文件,根据其保存数据的不同,也经常被分为不同的类型,我们一般简单的划分为文本文件和二进制文件,分别指代保存被字符集编码的文本按照标准格式保存的非被字符集编码过的文件

  •  txt:文本文件
  • .java/.c:文本文件
  • .class: 二进制文件
  • .exe :二进制文件
  • jpg,mp3:二进制文件

记事本出现乱码的原因:

        二进制都是一个一个的字节,记事本尝试着把当前若干个字节的数据往utf8码表里套,套出来的是啥就是啥。word编辑的docx和excel编辑的表格都是二进制文件。

3. 文件系统操作

Java标准库,给我们提供了File这个类,File对象是硬盘上一个文件的"抽象"表示,文件是存储在硬盘上的,直接通过代码操作硬盘是不方便的,就在内存中创建一个对象,就可以通过操作这个对象进行操作硬盘的内容了.(注意,有 File 对象,并不代表真实存在该文件)

3.1 构造File对象

构造的过程中,可以使用绝对路径/相对路径来进行初始化。这个路径指向的文件,可以是真实存在的,也可以不是真实存在的。

import java.io.File;

public class FileTest{
    public static void main(String args[]){
        File file = new File("d:/test.txt")
    }
}
 

3.2 File属性

3.3 构造方法

3.4 Fiel类的方法

4. 文件的读写(数据流) 

 

4.1 IO流原理 

  • I/O分别是Input与Output的缩写,用于处理数据传输,读写文件、网络通讯等;
  • Java程序中,对于数据的输入输出以流的方式进行;
  • java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过方法输入或输出数据;
  • input表示输入:读取外部数据,即将磁盘、光盘等存储设备的数据读到程序(内存)中;
  • output表示输出:将程序(内存)数据输出到磁盘、光盘等存储设备中。

4.2 流的分类 

针对文本文件,提供了一组类,统称为“字符流”(典型代表,Reader,Writer)

针对二进制文件,提供了一组类,统称为“字节流”(典型代表,InputStream,OutputStream)

4.2.1 字节流

1. 输入:InputStream

修饰符以及返回值类型方法说明

int

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

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

 

代码示例

将文件完全读完的两种方式。相比较而言,后一种的 IO 次数更少,性能更好。

第一种:每次读取一个字符

import java.io.*;
// 需要先在项目目录下准备好一个 hello.txt 的文件,里面填充 "Hello" 的内容
public class Main {
  public static void main(String[] args) throws IOException {
    try (InputStream is = new FileInputStream("hello.txt")) {
      while (true) {
        int b = is.read();
        if (b == -1) {
          // 代表文件已经全部读完
          break;
       }
       
        System.out.printf("%c", b);
     }
   }
 }
}

 第二种:读取指定长度的内容

import java.io.*;
// 需要先在项目目录下准备好一个 hello.txt 的文件,里面填充 "Hello" 的内容
public class Main {
  public static void main(String[] args) throws IOException {
    try (InputStream is = new FileInputStream("hello.txt")) {
      byte[] buf = new byte[1024];
      int len;
     
      while (true) {
        len = is.read(buf);
        if (len == -1) {
          // 代表文件已经全部读完
          break;
       }
       
        for (int i = 0; i < len; i++) {
       System.out.printf("%c", buf[i]);
       }
    }
  }
}
    

上述我们在文件中写入的内容为子母,因为是字节流,所以输出的是二进制字符

我们想要输出为hello需要转成字符

方法一:使用String的构造方法

每次使用 3 字节进行 utf-8 解码,得到中文字符,利用 String 中的构造方法完成, 这个方法了解下即可,不是通用的解决办法

方法2:使用Scanner 

2. OutputStream

修饰符以及返回值类型方法签名说明

void

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

将内容写入到文件(输出)

方法1. 

import java.io.*;
public class Main {
  public static void main(String[] args) throws IOException {
    try (OutputStream os = new FileOutputStream("output.txt")) {
      os.write('H');
      os.write('e');
      os.write('l');
      os.write('l');
      os.write('o');
      // 不要忘记 flush
      os.flush();
   }
 }
}

方法2 

import java.io.*;
public class Main {
  public static void main(String[] args) throws IOException {
    try (OutputStream os = new FileOutputStream("output.txt")) {
      byte[] b = new byte[] {
       (byte)'G', (byte)'o', (byte)'o', (byte)'d'
     };
      os.write(b);
    
      // 不要忘记 flush
      os.flush();
   }
 }
}

方法3

import java.io.*;
public class Main {
  public static void main(String[] args) throws IOException {
    try (OutputStream os = new FileOutputStream("output.txt")) {
     String s = "Nothing";
      byte[] b = s.getBytes();
      os.write(b);
    
      // 不要忘记 flush
      os.flush();
   }
 }
}

上述,我们其实已经完成输出工作,但总是有所不方便,我们接来下将 OutputStream 处理下,使用PrintWriter 类来完成输出,因为PrintWriter 类中提供了我们熟悉的 print/println/printf 方法

代码示例

public static void main(String[] args) throws IOException {
        try (OutputStream outputStream = new FileOutputStream("src/IoDemo2/hello.txt")){
            PrintWriter printWriter = new PrintWriter(outputStream);
            printWriter.println("嘿嘿");
            printWriter.print("哈哈");
            printWriter.printf("%d: 呵呵呵\r\n", 2);
            printWriter.flush();
        }
    }

4.2.2 字符流

 字符流就比较简单了

简单代码如下

1. Reader

package IoDemo2;

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

public class reader {
    public static void main(String[] args) {
        try(Reader reader = new FileReader("src/IoDemo2/hello.txt")){
            while (true){
                int c = reader.read();
                if (c == -1){
                    break;
                }
                char ch = (char) c;
                System.out.println(ch);
            }

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

2. Writer

package IoDemo2;

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

public class writer {
    public static void main(String[] args) {
        try(Writer writer = new FileWriter("src/IoDemo2/hello.txt",true)){
            writer.write("\nhello");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

5. 小练习

扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)
注意:我们现在的方案性能较差,所以尽量不要在太复杂的目录下或者大文件下实验

package IoDemo2;

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

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: YAO
 * Date: 2023-05-25
 * Time: 15:23
 */
public class test1 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要扫描的根目录: ");
        File rooDir = new File(scanner.nextLine());
        if (!rooDir.isDirectory()){
            System.out.println("输入有误,请重新输入:");
            return;
        }

        // 2. 让用户输入一个查询的词
        System.out.println("请输入要查询的词");
        String word = scanner.nextLine();

        //3. 递归的进行目录/文件遍历
        scanDir(rooDir,word);
    }

    private static void scanDir(File rooDir, String word) {
        // 1.列出当前的rootDir中的内容,没有内容,直接递归结束
        File[] files = rooDir.listFiles();
        if(files == null){
            // 当前rootDir是一个空的目录
            // 没必要进行递归
            return;
        }
        for (File f: files){
            System.out.println("当前搜索到: " + f.getAbsolutePath());
            if (f.isFile()){
                // 为普通文件
                // 打开文件,读取内容,比较看是否包含上述关键词
                String content = readFile(f);
                if (content.contains(word)){
                    System.out.println(f.getAbsolutePath() + " 包含要查找的关键字!");
                }
            }else if(f.isDirectory()){
                // 是目录
                // 进行递归操作
                scanDir(f,word);
            }else {
                // 其他文件
                continue;
            }
        }
    }
    private static String readFile(File f){
        // 读取文件的整个内容,返回出来
        // 使用字符流来进行读取,由于我们匹配的是字符串,此处只能按照字符流进行匹配才是有意义的.
        StringBuilder stringBuilder = new StringBuilder();
        try(Reader reader = new FileReader(f)){
            // 一次读一个字符,把读到的结果拼装到StringBuilder中,统一转成String
            while (true){
                int c = reader.read();
                if(c == -1){
                    break;
                }
                stringBuilder.append((char) c);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return stringBuilder.toString();
    }
}

6. 如何按照进行读P(通常使用Scanner)

package IoDemo2;

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

/**
 * Created with IntelliJ IDEA.
 * Description:读取文件的一行
 * User: YAO
 * Date: 2023-05-24
 * Time: 22:46
 */
public class readerRow {
    /**
     * 1.使用BufferedReader
     */
    public static void main1(String[] args) {
        try (BufferedReader bufferedReader = new BufferedReader(new FileReader("src/IoDemo2/hello.txt"))) {
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 2.使用Scanner
     */
    public static void main2(String[] args) {
        try (Scanner scanner = new Scanner(new FileReader("src/IoDemo2/hello.txt"))) {
            while (scanner.hasNextLine()){
                String line = scanner.nextLine();
                System.out.println(line);
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 3.RandomAccessFile
     * 行数达到一定规模,使用此方法读取会非常慢
     */
    public static void main(String[] args) throws FileNotFoundException {
        try (RandomAccessFile randomAccessFile = new RandomAccessFile("src/IoDemo2/hello.txt","r")){
            String line;
            while ((line = randomAccessFile.readLine()) != null) {
                //将readLine读取出来的字符串通过getBytes方法按iso-8859-1编码成字节数组,然后再将字节数组按utf8解码,最后转换成字符串输出。
                String lineNew = new String(line.getBytes("iso-8859-1"),"utf8");
                System.out.println(lineNew);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

7. 如何按照行进行写(通常使用PrintWriter)

public static void main(String[] args) throws IOException {
        try (OutputStream outputStream = new FileOutputStream("src/IoDemo2/hello.txt")){
            PrintWriter printWriter = new PrintWriter(outputStream);
            printWriter.println("嘿嘿");
            printWriter.println("哈哈");
            printWriter.flush();
        }
    }

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

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

相关文章

利用CiteSpace快速锁定领域内最新研究热点并制作精美的可视化专题图

【基于Citespace和vosviewer文献计量学相关论文 】 ​ 01 文献计量学方法与应用 1. 文献计量学方法基本介绍 2. 与其他综述方法区别联系 3. 各学科领域应用趋势近况 4. 主流分析软件优缺点对比 5. 经典高分10SCI思路复盘 6. 软件安装与Java环境配置 02 主题确定、数据检…

Power BI 如何高效管理度量值和字段

内容说明 背景需求&#xff1a; 当分析场景涉及大量数据和分析度量值时&#xff0c;为了更好的区分原始数据和用于分析的度量值&#xff0c;需要合理安排和管理数据字段。 本文总结了三种方法&#xff1a; 移动度量值位置创建字段文件夹&#xff1a;子文件夹和多个文件夹创建…

chatgpt赋能python:Python函数改名:为什么需要改名以及如何改名

Python函数改名&#xff1a;为什么需要改名以及如何改名 在Python编程中&#xff0c;函数是非常常见和重要的代码语句&#xff0c;用于完成特定的任务或操作。然而&#xff0c;在实际开发中&#xff0c;我们可能需要对已有函数进行改名&#xff0c;这个过程可能并不简单&#…

国产BI工具大比拼,帆软Fine BI和观远BI到底该怎么选型?

之前写了一篇关于BI如何选型的文章《「BI选型秘诀」BI工具不知道怎么选择&#xff1f;这张选型评分表你一定要收藏&#xff01;》。 文章发布后&#xff0c;不少朋友私信我&#xff0c;想要我出个国产BI工具的测评&#xff0c;今天就开始第一期&#xff1a;帆软 VS 观远 仍旧…

el-form嵌套el-table编辑,校验信息显示在气泡框中

文章目录 概要整体架构流程技术名词解释技术细节 概要 提示&#xff1a;这里可以添加技术概要 正常情况下&#xff0c;el-table可编辑表格&#xff0c;如果输入框内容不合理的情况下&#xff0c;错误提示会显示在el-input下方对应。 但是&#xff0c;我不得不将错误提示放到el…

chatgpt赋能python:Python几行几列是什么?

Python几行几列是什么&#xff1f; Python几行几列是一款基于Python语言开发的优秀的划线工具。这个工具能够帮助开发者轻松创建、管理和分享自己的Python代码。Python几行几列是一款高效、易用的Python编辑器&#xff0c;它既可以用于快速编写Python代码&#xff0c;也可以用…

PG数据库 column “has_submit_am“ is of type numeric but expression is of type bool

目录 场景&#xff1a; 现象&#xff1a; 复盘分析&#xff1a; 解决方法&#xff1a; 测试&#xff1a; 扩展&#xff1a; 场景&#xff1a; 今天遇到一个问题&#xff0c;现场数据库中做了boolean隐式转换smallint时在执行对应的插入时一直报错 column "has_submit…

【Python NLTK】零基础也能轻松掌握的学习路线与参考资料

Python 自然语言处理工具包&#xff08;Natural Language Toolkit&#xff0c;简称 NLTK&#xff09;是一款 Python 的库&#xff0c;主要用于处理自然语言的相关问题&#xff0c;如文本清洗、标记化、分词、语义分析、词性标注、文本分类等功能&#xff0c;是数据科学家和机器…

Facebook不同账户类型的投放格式【Facebook企业户】

在Facebook企业户中&#xff0c;不同的广告类型具有多样化的投放格式&#xff0c;旨在帮助企业更好地吸引目标受众、提升品牌曝光和实现营销目标。 一、广告类型的概述 Facebook提供了多种广告类型&#xff0c;包括图片广告、视频广告、幻灯片广告、动态产品广告等。每种广告类…

vue项目H5页面在苹果手机点击输入框输入内容时 页面自动放大

遇到的问题 用vue写H5页面时,iPhone手机点击input搜索框,输入内容时,页面会自动放大。 解决方法 在public文件夹下找到html文件&#xff0c;打开后加上user-scalableno 就行 <meta name"viewport" content"widthdevice-width,initial-scale1.0,user-scala…

【从零开始进行高精度手眼标定 eye in hand(小白向)1 原理推导】

从零开始进行高精度手眼标定 eye in hand&#xff08;小白向&#xff09;1 原理推导 前言原理推导公式推导为什么在数据采集中至少需要两个位姿信息 MATLAB编程计算A矩阵的计算和获取matlab计算代码B矩阵的计算和获取matlab计算矩阵B 前言 最近由于组内的相关工作需求&#xf…

pytorch中Dataset、Dataloader、Sampler、collate_fn相互关系和使用说明

参考&#xff1a; https://blog.csdn.net/Chinesischguy/article/details/103198921 参考&#xff1a; https://zhuanlan.zhihu.com/p/76893455 参考&#xff1a;https://blog.csdn.net/lilai619/article/details/118784730 参考&#xff1a;https://pytorch.org/docs/stabl…

06 【Vue数据监视 v-model双向绑定】

1.Vue数据监视 1.1 问题演示 先来个案例引入一下&#xff1a; <!-- 准备好一个容器--> <div id"root"><h2>人员列表</h2><button click"updateMei">更新马冬梅的信息</button><ul><li v-for"(p,inde…

Markdown笔记应用程序Note Mark

什么是 Note Mark Note Mark 是一种轻量、快速、简约&#xff0c;基于网络的 Markdown 笔记应用程序。具有时尚且响应迅速的网络用户界面。 安装 在群晖上以 Docker 方式安装。 ghcr.io 镜像下载 官方的镜像没有发布在 docker hub&#xff0c;而是在 ghcr.io&#xff0c;所以…

总结了几百个ChatGPT模型的调教经验,确定不来看看?

目录 前言 chatgpt调教指南 提示词 1.清晰的问题或请求&#xff1a; 2.上下文设置&#xff1a; 3.具体的主题或领域&#xff1a; 4.陈述性问题&#xff1a; 5.追问和澄清&#xff1a; 6.限定问题范围&#xff1a; 角色扮演 充当 Linux 终端 担任产品经理 充当 SQL…

技术帖——飞凌嵌入式RK3588开发板推理模型转换及测试

RKNN&#xff08;Rockchip Neural Network&#xff09;是一种用于嵌入式设备的深度学习推理框架&#xff0c;它提供了一个端到端的解决方案&#xff0c;用于将训练好的深度学习模型转换为在嵌入式设备上运行的可执行文件。使用RKNN框架可以在嵌入式设备上高效地运行深度学习模型…

易基因:DNA羟甲基化和TET酶在胎盘发育和妊娠结局中的作用 | 深度综述

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 胎盘是支持哺乳动物胚胎和胎儿发育所必需的临时器官。了解滋养层细胞分化和胎盘功能的分子机制可能有助于改善产科并发症的诊断和治疗。印迹基因是调控胎盘发育的基础&#xff0c;表观遗…

chatgpt赋能python:使用Python编写数据接口:如何让您的网站更具吸引力和效率

使用Python编写数据接口&#xff1a;如何让您的网站更具吸引力和效率 在当今数字时代&#xff0c;大多数公司都希望能够从用户生成的数据中收集和分析信息&#xff0c;以了解他们的客户群体并提高他们的营销策略。为此&#xff0c;开发数据接口成为了一项对于互联网公司不可或…

新文本检测算法TextFuseNet

TextFuseNet: Scene Text Detection with Richer Fused Features 自然场景中任意形状文本检测是一项极具挑战性的任务&#xff0c;与现有的仅基于有限特征表示感知文本的文本检测方法不同&#xff0c;本文提出了一种新的框架&#xff0c;即 TextFuseNet &#xff0c;以利用融合…

网络开发过程详细知识点

网络生命周期至少包括系统构思与计划、分析和设计、运行和维护的过程。 常见的迭代周期分为四阶段周期、五阶段周期、六阶段周期。 网络开发过程根据五阶段迭代周期模型可被分为五个阶段&#xff1a; 需求分析、现有网络分析、确定网络逻辑结构、确定网络物理结构、安装与维护。…