IO流(字节流与字符流) 和 File对象 详解与使用

IO流 和 File对象 理论概念

为什么需要io流呢?
在这里插入图片描述
如上图这些基本数据类型和对象以及列表都是内存中的数据,只要断电或者程序停止,这些数据将会永久消失。

那么如果我需要长久保存一些数据怎么办?(持久化)

那么就需要使用File对象 和 io流配合了。
在这里插入图片描述

file对象是什么?

File对象是Java中用于表示文件或目录的抽象。它提供了一些方法来查询和操作文件系统中的文件和目录。

通过File对象,你可以获取文件或目录的相关信息,如文件名、路径、大小、修改时间等。你还可以创建新的文件或目录,重命名或删除现有的文件或目录,以及进行文件系统的导航和搜索。

需要注意的是,File对象只是一个路径名的抽象表示,并不一定对应着实际的文件或目录。它可以指向存在的文件或目录,也可以指向还没有创建的文件或目录。

在这里插入图片描述
那么如何读写文件里面存储的数据呢?
那就是使用IO流进行读写了,io流可以读写文件中的数据或者是网络中的数据。

IO流是什么?

IO流指的是输入/输出流,是计算机程序中用于处理输入和输出的数据流。在程序中,输入流用于读取数据,输出流用于写入数据。IO流常用于文件操作、网络通信等场景。
在这里插入图片描述
IO流的分类:IO流主要有两种分类。
1、按照流的方向分类
在这里插入图片描述
2、按照流中数据的最小单位分类
在这里插入图片描述
所以大致的io流体系是:
在这里插入图片描述

file对象使用

创建file对象

Java的File类有三个构造器,分别如下:

1.File(String pathname):使用给定的文件路径字符串创建一个File对象。
示例:

File file1 = new File("E:/path/to/file.txt");

2.File(String parent, String child):将父路径和子路径字符串组合起来创建一个File对象。
示例:

File file2 = new File("E:/path/to", "file.txt");

3.File(File parent, String child):将父File对象和子路径字符串组合起来创建一个File对象。
示例:

File parentDir = new File("E:/path/to");
File file3 = new File(parentDir, "file.txt");

其中构造file对象时路径中的/路径分割符,file对象也提供了一个写法,就是 File.separator 所以也可以写为:

        File file1 = new File("E:"+File.separator+"path"+File.separator+"to"+File.separator+"file.txt");

在这里插入图片描述
一般实际编码中,使用的都是相对路径,便于代码转移。相对路径是从当前工程下寻找文件。
在这里插入图片描述

file对象中一些常用的方法

File类提供了很多常用的方法来操作文件和目录。以下是一些获取文件信息常用的方法和用法:

1.exists():检查文件或目录是否存在,返回值为boolean 。

File file = new File("/path/to/file.txt");
boolean exists = file.exists();

2.isFile():检查File对象是否表示一个文件,返回值为boolean 。

File file = new File("/path/to/file.txt");
boolean isFile = file.isFile();

3.isDirectory():检查File对象是否表示一个目录,返回值为boolean。

File directory = new File("/path/to/directory");
boolean isDirectory = directory.isDirectory();

4.getName():获取文件或目录的名称,包含后缀。

File file = new File("/path/to/file.txt");
String name = file.getName();

5.length():获取文件的长度(大小)(以字节为单位)。

File file = new File("/path/to/file.txt");
long length = file.length();

6.getParentFile():获取文件或目录的父File对象。

File file = new File("/path/to/file.txt");
File parentDir = file.getParentFile();

7.getParent():获取文件或目录的父路径。

File file = new File("/path/to/file.txt");
String parent = file.getParent();

8.listFiles():获取目录中的所有文件和子目录作为File对象的数组。

File directory = new File("/path/to/directory");
File[] files = directory.listFiles();

9.getPath():获取到创建文件对象时使用的路径

File file = new File("E:\\io\\src\\a.txt");
String path = file.getPath();

10..getAbsolutePath()获取到当前文件的绝对路径。

 File file = new File("E:\\io\\src\\a.txt");String absolutePath = file.getAbsolutePath();
File类提供了一些方法来创建和删除文件。下面是创建和删除文件的方法:
  1. 创建文件:

    • createNewFile():创建一个新的空文件。如果文件已存在,则返回 false

      File file = new File("/path/to/newFile.txt");
      boolean created = file.createNewFile();
      
    • mkdir():创建一个新的空目录(只能创建一级)。如果目录已存在或创建失败,则返回 false

      File dir = new File("/path/to/newDir");
      boolean created = dir.mkdir();
      
    • mkdirs():创建一个新的目录,包括所有不存在的父目录(可以创建多级)。如果目录已存在或创建失败,则返回 false

      File dir = new File("/path/to/newDir/subDir");
      boolean created = dir.mkdirs();
      
  2. 删除文件或空目录:

    • delete():删除文件或空目录。如果删除成功,则返回 true;否则,返回 false

      File file = new File("/path/to/file.txt");
      boolean deleted = file.delete();
      
      File dir = new File("/path/to/directory");
      boolean deleted = dir.delete();
      

    请注意,上述方法只能删除空目录或文件。如果要删除非空目录,需要使用递归删除。

    public static void deleteDirectory(File directory) {if (!directory.exists()) {return;}File[] files = directory.listFiles();if (files != null) {for (File file : files) {if (file.isDirectory()) {deleteDirectory(file); // 递归删除子目录} else {file.delete(); // 删除文件}}}directory.delete(); // 删除当前目录
    }
    

    调用 deleteDirectory() 方法以删除非空目录:

    File dir = new File("/path/to/directory");
    deleteDirectory(dir);
    

记住,在进行文件和目录操作时,要小心处理异常情况,并确保在操作之前检查文件和目录的存在性。
在这里插入图片描述

File类提供了一些方法来遍历文件。下面是遍历文件的方法:

在这里插入图片描述

字符集的编码解码操作

主要的字符集编码有 ASCII UTF-8 GBK
在这里插入图片描述

IO流如何使用

FileInputStream(文件字节输入流)和 FileOutputStream(文件字节输出流)

FileInputStream(文件字节输入流)

在这里插入图片描述
使用read()读取,每次返回一个字符,代码示范:
缺点:

  • 读取性能差
  • 中文乱码(中文占两个或者三个字节,一个一个读取把它强行拆分了,所以乱码)
package day0927;import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class demo3 {public static void main(String[] args) {InputStream in = null;try {in = new FileInputStream("src\\a.txt");int b;while ((b = in.read()) != -1){System.out.print((char) b);}} catch (Exception e) {throw new RuntimeException(e);}finally {try {//读取完之后关闭流if (in!= null)in.close();} catch (IOException e) {throw new RuntimeException(e);}}}
}

使用read(byte[] buffer)读取,每次读取字节数组的长度,代码示范:
优点:

  • 性能得到了提升。

缺点:

  • 中文还是可能会乱码。
package day0927;import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class demo3 {public static void main(String[] args) {InputStream in = null;try {in = new FileInputStream("src\\a.txt");//设置每次读取多少字节,一般是写 1024*nbyte[] buffer = new byte[3];int b;while ((b = in.read( buffer )) != -1){//注意:读取多少就倒多少String str = new String(buffer,0,b);System.out.print(str);}} catch (Exception e) {throw new RuntimeException(e);}finally {try {if (in!= null)in.close();} catch (IOException e) {throw new RuntimeException(e);}}}
}

以上两种方式都是读取中文会乱码,可以使用直接读取整个文件字符,则不会乱码。
在这里插入图片描述
第一种方法(获取文件大小,定义一个和文件一样大小的字节数组一次性读取):

package day0927;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class demo3 {public static void main(String[] args) {InputStream in = null;try {//获取文件的file对象File file = new File("src\\a.txt");//获取文件的字节长度long length = file.length();in = new FileInputStream(file);//字节数组的长度改为文件长度byte[] buffer = new byte[(int) length];//一次性读取in.read(buffer);System.out.println(new String(buffer));} catch (Exception e) {throw new RuntimeException(e);}finally {try {if (in!= null)in.close();} catch (IOException e) {throw new RuntimeException(e);}}}
}

第二种方法 JDK11新增的特性readAllBytes()
一顶是JDK11以上才可以使用否则报错。

	FileInputStream in = new FileInputStream("src\\a.txt");byte[] buffer = in.readAllBytes();System.out.println(new String(buffer));
FileOutputStream(文件字节输出流)

在这里插入图片描述
使用write()输出字符。

package day0927;import java.io.FileOutputStream;
import java.io.IOException;public class demo4 {public static void main(String[] args) {FileOutputStream out = null;try {//参数1文件的位置,参数2是否是追加,默认falseout = new FileOutputStream("src\\b.txt",true);out.write("你好,JAVA".getBytes());//out.write('97'); 写入字符a} catch (Exception e) {throw new RuntimeException(e);}finally {try {if (out != null)out.close();} catch (IOException e) {throw new RuntimeException(e);}}}
}
FileInputStream和FileOutputStream案列(文件复制)

当学会了文件输出输入流之后,就可以完成文件的拷贝案例了。
使用文件输出输入流是所有的文件都可以进行复制的,下面是代码示范:

package day0927;
import java.io.*;
public class demo5 {public static void main(String[] args) {InputStream in = null;OutputStream out = null;try {in = new FileInputStream("D:\\asdf.jpg");out = new FileOutputStream("E:\\asdf.jpg");byte[] buffer = new byte[1024];int b;while ((b = in.read(buffer))!= -1){out.write(buffer,0,b);}} catch (Exception e) {throw new RuntimeException(e);}finally {try {if (out != null)out.close();if (in != null)in.close();} catch (IOException e) {throw new RuntimeException(e);}}}
}

如上代码看起来写得特别的臃肿,因为各种释放资源,所以这里就要使用到 JDK7提出得新特性:
在这里插入图片描述
如图在try中写资源,当执行完之后会自动调用其close()方法。示范代码:

package day0927;import java.io.*;public class demo5 {public static void main(String[] args) {try (InputStream  in = new FileInputStream("D:\\asdf.jpg");OutputStream out = new FileOutputStream("E:\\asdf.jpg");){byte[] buffer = new byte[1024];int b;while ((b = in.read(buffer))!= -1){out.write(buffer,0,b);}} catch (Exception e) {throw new RuntimeException(e);}}
}

FileReader(字符输入流)和 FileWriter(文件字节输出流)

FileReader(字符输入流)

在这里插入图片描述
以下代码示范就是字符流读取文件,分别有一次读取一个字符和读取多个字符。

package day0927;import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;public class demo6 {public static void main(String[] args) {try (FileReader reader = new FileReader("src\\a.txt");){//一次读一个字符,性能消耗较高
//            int d;
//            while ((d = reader.read())!=-1){
//                System.out.print((char)d);
//            }//一次读多个字符,性能消耗低char[] buffer = new char[3];int d;while ((d = reader.read(buffer))!=-1){//读多少就倒多少System.out.print(new String(buffer,0,d));}} catch (Exception e) {throw new RuntimeException(e);}}
}
FileWriter(文件字节输出流)

在这里插入图片描述
下面是FileWriter文件字符输出流的代码演示:

package day0927;import java.io.FileWriter;
import java.io.IOException;public class demo7 {public static void main(String[] args) {try (//覆盖的写法
//            FileWriter writer = new FileWriter("src\\c.txt");//追加的写法FileWriter fileWriter = new FileWriter("src\\c.txt",true);){//写一个字符fileWriter.write(97);fileWriter.write("流");fileWriter.write('a');//写一个字符串fileWriter.write("我爱你中国asdf");//写一个字符串得一部分fileWriter.write("我爱你中国asdf",0,5);//写一个字符数组char[] chars = {98,'s','牛','马'};fileWriter.write(chars);//写一个字符数组得一部分出去fileWriter.write(chars,1,2);} catch (IOException e) {throw new RuntimeException(e);}}
}
字符输入输出流复制文本案例:
package day0927;import java.io.FileReader;
import java.io.FileWriter;public class demo8 {public static void main(String[] args) {try (FileReader fileReader = new FileReader("src\\a.txt");FileWriter fileWriter = new FileWriter("src\\d.txt");){char[] buffer = new char[3];int b;while ((b = fileReader.read(buffer)) != -1){fileWriter.write(buffer,0,b);}} catch (Exception e) {throw new RuntimeException(e);}}
}
重点注意:

在这里插入图片描述
因为使用字符流输出数据是先建立了一个缓冲区,把所有要写的字符先存到了这,而不是直接存到目标文件,所以需要flush()刷新或者close()关闭流进行保存,如果不使用flush()刷新或者不使用close()关闭流那么就不会保存,但是当缓冲区数据堆满时,它会自动进行一次flush()刷新也就是自动保存一次。

小结:

在这里插入图片描述

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

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

相关文章

C++ - unordered系列关联式容器介绍 - 和 set map 的比较

前言 C - map 和 set 使用介绍_chihiro1122的博客-CSDN博客 C - map 和 set的 例题_chihiro1122的博客-CSDN博客 C - map 和 set 的模拟实现上篇 - 红黑树当中的仿函数 - 红黑树的迭代器实现-CSDN博客、 C - set 和 map 的实现(下篇)- set 和 map 的迭…

自定义热加载:如何不停机实现核心代码更新

文章目录 1. 常见的几种实现代码热更新的几种方式对于开发环境我们可以使用部署环境1. 使用 Arthas 的 redefine 命令来加载新的 class 文件2. 利用 URLClassLoader 动态加载3. 通过Java的Instrumentation API 也是可以实现的 2. 实现1. ClassScanner扫描目录和加载类2. 定时任…

Grafana 开源了一款 eBPF 采集器 Beyla

eBPF 的发展如火如荼,在可观测性领域大放异彩,Grafana 近期也发布了一款 eBPF 采集器,可以采集服务的 RED 指标,本文做一个尝鲜介绍,让读者有个大概了解。 eBPF 基础介绍可以参考我之前的文章《eBPF Hello world》。理…

【Git】轻松学会 Git(一):掌握 Git 的基本操作

文章目录 前言一、创建 Git 本地仓库1.1 什么是仓库1.2 创建本地仓库1.3 .git 目录结构 二、配置 Git三、认识 Git 的工作区、暂存区和版本库3.1 什么是 Git 的工作区、暂存区和版本库3.2 工作区、暂存区和版本库之间的关系 四、添加文件4.1 添加文件到暂存区和版本库中的命令4…

深度学习-优化器

1.梯度下降 最开始的梯度下降算法,更新权重的方法是theta theta - learning_rate * gradient(loss),loss是损失函数。但是这种方法只关心当前的梯度,如果坡度较缓,则它依然会以一种缓慢的速度下降,我们先举个例子,使…

光耦的原理和作用

光耦又叫光电耦合器。 这个是四脚光耦的电路符号,12之间是一个发光二极管,34之间是一个光电三极管,光藕就相当于把发光二极管和光电三极管封装在一个密闭的壳体中的器件。 当光耦发光二极管两端没有电压或电压不足使他导通时,发光…

2023-9-27 JZ55 二叉树的深度

题目链接:二叉树的深度 import java.util.*; /** public class TreeNode {int val 0;TreeNode left null;TreeNode right null;public TreeNode(int val) {this.val val;}} */ public class Solution {public int TreeDepth(TreeNode root) {if(root null) ret…

什么是HTTP/2?它与HTTP/1.1相比有什么改进?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ HTTP/2 简介⭐ 主要的改进和特点⭐ 总结⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端…

二叉树MFC实现

设有一颗二叉树如下; 这似乎是一颗经常用作示例的二叉树; 对树进行遍历的结果是, 先序为:3、2、2、3、8、6、5、4, 中序为:2、2、3、3、4、5、6、8, 后序为2、3、2、4、5、6、8、3&#xff1b…

Java编译运行结果乱码

一、问题 编译运行结果乱码 二、处理方法 方法1:将.java文件另存为编码设置为ANSI 方法2:使用命令参数 encoding javac -encoding utf-8 csdn.java 当你文件编码格式是utf-8需要指定java编译器的编码格式,如果没有用到encoding参数指定ja…

渗透测试中的前端调试(一)

前言 前端调试是安全测试的重要组成部分。它能够帮助我们掌握网页的运行原理,包括js脚本的逻辑、加解密的方法、网络请求的参数等。利用这些信息,我们就可以更准确地发现网站的漏洞,制定出有效的攻击策略。前端知识对于安全来说,…

代码随想录 Day7 字符串1 LeetCode T344反转字符串 T541 反转字符串II 151翻转字符串的单词

本文更详细解析来自于:代码随想录 (programmercarl.com) LeetCode T344 反转字符串 链接:344. 反转字符串 - 力扣(LeetCode) 题目思路 这题的思路很简单,只需要创建两个指针,一个指向首字母,一个指向末字母,两两进行交换即可,这里我们要说的就是交换,可…

实验室安全教育与考试

目录 我的错题(2个)新知识题目(10个)刚开始不太理解的题目(10个)写在最后(免责声明) 我的错题(2个) 18.发生电气火灾时可以使用的灭火设备包括:&…

WebSocket的那些事(6- RabbitMQ STOMP目的地详解)

目录 一、目的地类型二、Exchange类型目的地三、Queue类型目的地四、AMQ Queue类型目的地五、Topic类型目的地 一、目的地类型 在上节 WebSocket的那些事(5-Spring STOMP支持之连接外部消息代理)中我们已经简单介绍了各种目的地类型,如下图&…

【数据结构】—超级详细的归并排序(含C语言实现)

​ 食用指南:本文在有C基础的情况下食用更佳 🔥这就不得不推荐此专栏了:C语言 ♈️今日夜电波:斜陽—ヨルシカ 0:30━━━━━━️💟──────── 3:20 …

vue项目 H5 动态设置浏览器标题

1,先将要展示的标题存本地 if (that.PromotionInfo.Title) {localStorage.setItem("AcTitle", that.PromotionInfo.Title)} 2,现在路由meta中设置标题,再在路由守卫中设置 import Vue from vue import Router from vue-router import prom…

新手程序员怎么接单?

程序员如何在自己年富力强的时候,最大化发挥自己的能力?将超能力转化为“钞能力”? 有人还在苦哈哈当老黄牛,一身使不完的牛劲,有人已经另辟蹊径,开创了自己的一片致富小天地。 接单找兼职,就…

4k、VR与万兆光网

“全光万兆”对VR意义重大。 pico4的分辨率 PICO 4 的单眼分辨率是 2160 2160,整体分辨率高达 4320 2160。这是一款高性能的 VR 一体机,采用了 2.56 英寸的 Fast-LCD 屏幕,最高可实现 90Hz 刷新率,还有 1200 PPI 和 20.6 PPD 的…

线性约束最小方差准则(LCMV)波束形成算法仿真

常规波束形成仅能使得主波束对准目标方向,从而在噪声环境下检测到目标,但无法对复杂多变的干扰做出响应,所以不能称之为真正意义上的自适应滤波。自适应阵列处理指的是采用自适应算法对空间阵列接收的混合信号进行处理,又可称为自…

Android---打开相机拍照

简单实现打开系统系统相机拍一张图片并显示在UI上&#xff0c;适用与个人主页头像的切换。 1. 添加权限。AndroidManifest.xml里添加使用相机的权限。 <uses-permission android:name"android.permission.CAMERA"/> 2. 布局。布局内容比较交单&#xff0c;一…