当前位置: 首页 > news >正文

文件IO(Java)

注:此博文为本人学习过程中的笔记

1.概念

狭义上的文件是指保存在硬盘上的文件,广义上指操作系统进行资源管理的一种机制,很多软件/硬件资源都可以抽象成文件,这里我们针对的是狭义上的文件。

在硬盘里还有文件夹,这是通俗的说法,我们一般称其为目录。

2.硬盘,内存和寄存器

1.区别

存储空间

硬盘很大(几TB),内存更小(几十GB),寄存器非常小(不到1KB)

访问速度

硬盘很慢,内存快,寄存器很快

成本

硬盘便宜,内存贵,寄存器不单独卖,很贵

2.硬盘

硬盘分为固态硬盘和机械硬盘,机械硬盘受限于内部结构,速度非常慢。

3.路径

一台计算机中能够保存的文件有很多,那么要怎么识别唯一的文件呢?此时就需要用到路径。路径就是定位到文件的一系列过程。在计算机中,目录套目录形成了树形结构,从树根开始到最终的文件,都需要经过哪些目录,就形成路径。

1.使用

一般用“/”(正斜杠)表示。主流操作系统中都是使用/表示,windows比较特殊,使用“\”(反斜杠)表示。不过windows里是兼容正斜杠的,所以我们都使用正斜杠。在编写代码的时候,正斜杠可以直接使用,反斜杠需要转义。

2.相对路径和绝对路径

1.绝对路径

从盘符开始逐级表示

2.相对路径

相对路径需要明确一个基准,使用.表示基准的位置。使用..表示基准的上一层。使用../..表示基准的上两层。

在代码中写一个相对路径,它的基准是不确定的。如果在IDEA上运行,基准就是项目的目录。如果打一个jar包,单独运行jar包,那么是在哪个目录执行运行命令,基准就是哪个目录。

4.文件的种类

从开发的角度把文件分成两类,二进制文件和文本文件。图片,视频,压缩包之类的都是二进制文件。

所有的文件都是二进制文件,有一些文件是特殊的,二进制数据刚好能构成一些字符,能狗仔码表查到,并且构成有意义的内容。判断文本文件的方法很简单,直接用记事本打开看即可。注意word里的docx是二进制文件,里面不只有文本,还有格式,图表之类的东西。

5.Java标准库中操作文件的类

1.文件系统操作

创建文件,删除文件,重命名,创建目录

File - Java17中文文档 - API参考文档 - 全栈行动派 (qzxdp.cn)

进行文件系统操作时使用File这个类。里面的方法大多比较简单,查看文档即可,这里只写一些需要注意的点。

1.方法注意点

1.list()和listFile()

这个方法的作用是返回当前目录的子元素有哪些,需要注意的是它是无法获得子元素的子元素或孙子元素的,如果想,需要我们通过代码来实现。list返回的是字符串,而listFile返回的是File类,可以进行更多操作。

2.renameTo()

这个方法的作用是重命名目录,对于操作系统来说,重命名和移动本质上是一样的,因为定位文件是靠路径完成的。

2.文件内容操作

针对一个文件的内容进行读和写,通过一组“流对象”实现。流是操作系统层面的术语,和语言无关,其他语言操作文件内容也叫流。输入和输出是以cpu为参考的。

字节流读数据时是文件的原始数据。而字符流会根据文件内容的编码格式进行解析,比如可以把utf-8编码下3个字节的汉字解析后放到2个字节的char里。

其中的操作大部分是很相似的,这里就只详细介绍InputStream,其他都一笔带过。

1.字节流

读写文件以字节为单位,是针对二进制文件进行使用的。字节流主要有两个类InputStream和OutputStream,其他类都直接或间接继承这两个类。

1.InputStream
1.new操作
//注意InputStream是个抽象类
InputStream inputStream = new FileInputStream(文件路径);

这里的创建操作一旦成功,就认为打开了文件。要先打开文件才能进行操作,这是操作系统定义的流程。这个时候就不能忘记操作完成之后要关闭文件。

2.close()
inputStream.close();

不手动释放文件资源,就会引起文件资源泄露问题。 每次打开一个文件,就会在文件描述符表(固定长度的顺序表)中占据一个表项,如果光打开,不关闭,这里的文件描述符表的表项就会耗尽,后续再打开文件就会失败。文件操作附表是不能自动扩容的,操作系统内核里的操作是给所有进程提供的,如果能自动扩容会进一步增加内核的不可控因素。

close和unlock一样,容易因为各种原因漏掉,所以我们可以使用finally语句或者try语句的变种来保证close操作一定执行。

try {InputStream inputStream = new FileInputStream();
} finally {inputStream.close();
}//括号里可以new多个,在括号里new的东西会在try的代码块结束后自动调用close关闭
try(InputStream inputStream = new FileInputStream();) {}
//能自动关闭的类都实现了Closable接口
3.read() 

int read()

调用一次,读取一个字节,返回的是int而不是byte,返回值是正常数字时对照码表查具体是什么,返回-1是表示文件已经读完

try(InputStream inputStream = new FileInputStream("./text.txt")) {//开始进行读文件操作while(true) {int data = inputStream.read();if(data == -1) {//如果读完就退出break;}System.out.println(data);}
}

int read(byte[] b)

一次读若干个字节,读取到的数据放到参数b中。

这个方法使用参数作为方法的返回值。一般来说,方法都是把参数作为需要加工的材料,把返回值当作生产出来的产品。有时也会使用参数来接收返回值,当参数是一个引用类型时,方法内部修改对象内容也能影响到方法外部。

这种"输出型参数"本质上是语法的限制,因为语法限制方法只能有一个返回值,如果希望返回多个数据,只能通过参数来凑。

try(InputStream inputStream = new FileInputStream("./text.txt")) {byte[] data = new byte[1024];while(true) {//read方法会尽可能读完数据,直到把data填满为止。int n = inputStream.read(data);//这里的n表示实际读了几个字节for(int i = 0; i < n; i++) {System.out.println(data[i]);}}
}

int read(byte[], int off, int len)

这里的off表示offset指的是偏移量,也可以理解成数组下标,len表示长度。这个方法和第二个类似,多了指定下标和长度。

2.OutputStream
1.new

对于OutputStream来说,默认情况下会尝试创建不存在的文件。打开文件的一瞬间是会清除上次文件的内容的,可以设置成追加写的模式,避免文件被清空。

OutputStream outputStream = new FileOutputStream("./text.txt", true);
2.write

void write(int b)

一次写一个字节

void write(byte[] b)

一次写若干个字节

void write(byte[] b, int off, int, len)

一次写若干个字节,可以指定下标和长度

2.字符流

读写文件以字符为单位,是针对文本文件进行使用的。字符流主要有两个类Writer和Reader,其他类都直接或间接继承这两个类。

1.Reader
1.read()

int read()

一次读一个字符

int read(char[] cbuf)

一次读一个字符数组

int read(CharBuffer target)

CharBuffer相当于对char[]进行了封装

int read(char[] cbuf, int off, int len)

一次读一个字符数组,可以指定下标和长度

2.Writer
write()

void write(int c)

void write(String str)

void write(char[] cubf)

void write(String str, int off, int len)

void write(char[] cubf, int off, int len)

3.提高效率的方法

1.手动创建缓冲区,手动减少read和write的次数

2.使用标准库提供的"BufferedStream"缓冲区流


http://www.mrgr.cn/news/100271.html

相关文章:

  • 【2025计算机网络-面试常问】http和https区别是什么,http的内容有哪些,https用的是对称加密还是非对称加密,流程是怎么样的
  • XSS跨站--原理和分类
  • 第七讲 | list的使用及其模拟实现
  • java—12 kafka
  • 【专题三】二分查找(2)
  • UOJ 228 基础数据结构练习题 Solution
  • 第一部分:git基本操作
  • 皖维 大病救助办理手续说明
  • IOT项目——DIY 气象站
  • 【深度强化学习 DRL 快速实践】逆向强化学习算法 (IRL)
  • Shell 脚本入门:从零开始写自动化脚本
  • QT窗口相关控件及其属性
  • 再来1章linux 系列-11 系统的延迟任务及定时任务 ,名单,at ,crontab,mail;/etc/at.allow,/etc/at.deny
  • 使用spring boot vue 上传mp4转码为dash并播放
  • 【深度强化学习 DRL 快速实践】深度确定性策略梯度算法 (DDPG)
  • 【深度强化学习 DRL 快速实践】近端策略优化 (PPO)
  • 【FreeRTOS】事件标志组
  • C语言实现对哈希表的操作:创建哈希表与扩容哈希表
  • Mysql日志undo redo binlog relaylog与更新一条数据的执行过程详解
  • 软考中级-软件设计师 知识点速过1(手写笔记)