Java文件IO操作

article/2025/10/5 16:25:10

目录

一、了解什么是文件

   狭义的文件:

  广义的文件:

二、文件的路径

①文件的绝对路径

②文件的相对路径

三、Java对于文件的操作

    File类的构造方法    

     File类的普通方法

 四、对于文件的内容操作

①FileInputStream(文件输入流)

      常用构造方法:传递一个字符串

       read方法

   (1)无参数的方式:read()

    (2)有参数的版本,参数为一个byte数组

 ②FileOutputStream(文件输出流)

 五、close()方法      

     需要及时关闭"流"的原因:

 六、更加优雅的close()方式

          采用Scanner来读取磁盘的内容:

  七、字符流      


一、了解什么是文件

   文件,File这个概念,在计算机当中,也是非常常见的一个词语。

   狭义的文件:

  指的的是计算机硬盘上面的文件和目录(文件夹)。

   如图:

   


  广义的文件:

 泛指计算机当中的很多的软硬件资源。

  操作系统把很多的硬件设备软件资源抽象成了文件,例如网卡等待...

下面将要重点讨论的,就是狭义的文件


二、文件的路径

       文件的路径,主要是有以下两种表示方式:

①文件的绝对路径

       绝对路径,也比较好理解,可以视为文件相对于某个盘,所存储的位置,一般情况下面,以D:/***/***这样的形式表示。

    例如在上图当中,jdk1.88这个文件夹,它的绝对路径就是:D:\jdk1.88

    

       需要注意的是,虽然在windows当中,现在表示一个文件的目录都是采用“\"作为目录的分隔符的。

       但是,实际上在代码的书写当中不可以采取反斜杠作为路径的分隔符,一般都是采取正斜杠的方式作为分隔符。 因为,反斜杠通常搭配一个普通的字符,都会把"\+某个字符"转义为其他的字符。

       这样,容易引发歧义。因此在代码的书写当中,还是要采取正斜杠"/"的方式。


②文件的相对路径

        相对路径,通常以当前所在目录作为基准,以"."或者".."开头,找到指定的路径。

        举个例子:

        当点击进入了:D:\jdk1.88\lib这个文件夹之后,当前的目录就是:D:\jdk1.88\lib       


       如果想在当前的D:\jdk1.88\lib 目录下面定位到第一个文件夹,也就是missioncontrol。就可以表示为:./missioncontrol

       其中: “./” 就表示当前的目录。


      同理可得:如果当前目录是D:\jdk1.88

      那么,想定位到lib目录,就是:./lib


三、Java对于文件的操作

    分为以下两类:

    1、针对文件的系统操作(创建、删除、重命名等等);

    2、针对文件内容的操作(针对某个文件的读写)。


    下面,首先介绍对于文件的系统操作,需要使用的类为File这个类。

    File类的构造方法    

构造方法说明
File(String pathname)

根据文件的路径创建一个File实例,实例可以是绝对路径,

也可以是相对路径

File(File parent,String child)根据父目录+孩子文件路径,创建一个新的File实例
File(String parent,String child)

根据父目录+孩子文件路径,创建一个新的File实例,与第2个不同的是,

父目录用路径表示


 其中,第一行的构造方法是最常见的

代码实现:

  File file=new File("D:/bookBook.txt");

 这样,就成功创建出来一个file的实例了。

 需要注意的事项有下面两点:


       ①file对象代表的文件,此时不一定在对应的位置当中存在。如果不存在,可以在后续调用file.mkdir()方法创建。

       如果已经存在了再次调用mkdir()方法创建,那么不会重新创建一个文件,也不会覆盖掉原来已经存在的文件的内容。

       ②如果是单个斜杠,代表创建一个文件,例如(...txt/...doc)

          如果两个及以上的斜杠,代表创建一个文件夹


     File类的普通方法

修饰符及返回
值类型
方法签名 方法签名 
StringgetParent()返回 File 对象的父目录文件路径
StringgetName()返回 FIle 对象的纯文件名称
StringgetPath()返回 File 对象的文件路径
String

 
getAbsolutePath()返回 File 对象的绝对路径
StringgetCanonicalPath()返回 File 对象的修饰过的绝对路径
booleanexists()判断 File 对象描述的文件是否真实存在
booleanisDirectory()判断 File 对象代表的文件是否是一个目录
booleanisFile()判断 File 对象代表的文件是否是一个普通文件
boolean
 
createNewFile()根据 File 对象,自动创建一个空文件。成功创建后返
回 true
booleandelete()根据 File 对象,删除该文件。成功删除后返回 true
voiddeleteOnExit()根据 File 对象,标注文件将被删除,删除动作会到JVM 运行结束时才会进行
String[]list()返回 File 对象代表的目录下的所有文件名
File[]listFiles()返回 File 对象代表的目录下的所有文件,以 File 对象表示
booleanmkdir()创建 File 对象代表的目录
booleanmkdirs()
创建 File 对象代表的目录,如果必要,会创建中间目
booleanrenameTo(File
dest)
进行文件改名,也可以视为我们平时的剪切、粘贴操作
booleancanRead()判断用户是否对文件有可读权限
booleancanWrite()判断用户是否对文件有可写权限

 下面,将演示几个常见的普通方法代码实现:

 ①file.getName(String name)

 假设此时文件"bookBook1.txt"已经存在了

 如下面的代码:

 //不一定在D盘当中一定存在这一个路径File file=new File("D:/bookBook.txt");System.out.println(file.getName());

  就会输出bookBook.txt,为对应文件的名称。


如果执行下面的代码:

File file=new File("./bookBook.txt");System.out.println(file.getName());

  也会输出bookBook.txt。 


 ②file.getParent()

File file=new File("D:/bookBook/hello.txt");System.out.println(file.getParent());

  此时,将输出hello.txt的最近一级的目录:即:D:\bookBook 


③file.getPath(),getAbsolutePath()

       此时,将分情况讨论:

       如果file的构造方法当中指定的是一个绝对路径,也就是类似于D:/***/***这样的路径,那么二者输出的时候没有任何差别。

        File file=new File("D:/bookBook/hello.txt");System.out.println(file.getAbsolutePath());System.out.println(file.getPath());

        File file=new File("./hello.txt");System.out.println(file.getAbsolutePath());System.out.println(file.getPath());

        如果file的构造方法当中指定的是一个相对路径,也就是类似于./***这样的路径,那么二者的差别在于:

        file.getAbsolutePatrh()返回的是”绝对路径“,也就是从D盘开始的路径。

        由于此时hello.txt位于idea当中,因此,返回的路径就是当前idea项目的路径+hello.txt

        file.getPath()返回的是这一个文件的”工作路径"。

        运行结果截图:

       


④file.isDirectory(String name)

   输出是否为一个目录。

  如果传递的参数为一个目录,也就是一个文件夹,那么返回true。

  如果传递的参数为一个文件的地址,那么返回false。

        //demo26为一个具体的项目文件夹File file=new File("D:/demo26");//test为一个txt文本文档File file1=new File("./test.txt");//输出trueSystem.out.println(file.isDirectory());//输出falseSystem.out.println(file1.isDirectory());

⑤file.createNewFile:在指定的目录创建一个文件,如果创建成功返回true,否则false

        //test为一个txt文本文档File file1=new File("./test1.txt");//创建成功返回true,创建失败返回falseSystem.out.println(file1.createNewFile());

 同理,file.delete()也是删除一个指定目录的文件。


 四、对于文件的内容操作

       在三当中,提到了对文件内容进行读取操作,那么,下面将介绍对于文件内容的读取操作的一些介绍。

       我们常说的IO流,就是内存和硬盘资的数据交互的一种工具。

       图解:输入流、输出流:

       

 从磁盘读取数据到内存的流,就是输入流------->FileInputStream。

 从内存读取数据到磁盘的流,就是输出流------->FileOutputStream。

 因此,所谓的输入输出流,都是相对于应用程序来讲的。


①FileInputStream(文件输入流)

      常用构造方法:传递一个字符串

       此处的字符串,可以是相对目录,也可以是绝对目录。下面代码采用的是绝对目录的方式

            //如果文件不存在,就会抛出异常FileInputStream inputStream=new FileInputStream("./test.txt");

   需要注意的是,读取的字符串一定要是一个确确实实存在的文件,否则会抛出                  FileNotFoundException


       read方法

        此方法在FileInputStream内部是存在多态的:       

       下面,将简单介绍一下read方法的三个多态形式:


        (1)无参数的方式:read()

           FileInputStream是按照一个一个字节的顺序读取的

           相当于一次只读取一个字节的数据。

           read()方法的返回值却是int类型的。

                 那么它的含义就是,每次只读取一个字节的数据,读取的是它的ASCII码值。

          读取完一个数据之后,再次调用read()方法,会接着读取接下来的一个数据。

          当把整个文件都读取完毕之后,如果继续调用read()方法,那么会直接返回-1.

          代码实现

             

public static void main(String[] args) {try {FileInputStream inputStream= new FileInputStream("./test.txt");while (true){int b=inputStream.read();//当读取到的值为-1的时候,意味着已经读取完毕了,直接跳出循环if(b==-1){break;}//此处需要强制类型转换,才可以读取到对应的真实的字符System.out.print(""+(char)b);}//使用完毕之后,需要手动关闭这个流inputStream.close();} catch (IOException e) {e.printStackTrace();}

     运行结果截图:

         


    (2)有参数的版本,参数为一个byte数组

      byte数组为read读取到的值所传递的数组。

      当第一次调用inputStream.read(byteArray)的时候,会一次性把目标文件当中的所有内容一次保存到byteArray当中,并且返回实际读取的文件的字节数量。

      读取完毕之后,第二次再次读取,会返回-1.


      代码实现:

public static void main(String[] args) {try {//如果文件不存在,就会抛出异常FileInputStream inputStream=new FileInputStream("./test.txt");//read无参数版本:一次读取一个字节byte[] buffer=new byte[1024];while (true){//读取到某一个值,让字符数组对这一个buffer进行读取//尽可能让int len=inputStream.read(buffer);if(len==-1){break;}//遍历buffer数组for(int i=0;i<len;i++){System.out.println(buffer[i]);}}//使用完毕之后,需要手动关闭这个流inputStream.close();} catch (IOException e) {e.printStackTrace();}}

     

        此时,运行结果为:

        从上往下依次对应hello的ASCII值 


  灵魂拷问:为什么第(2)种方式的效率更高?

       首先需要了解一个前提条件,就是,使用FileInputStream进行IO操作的时候,每IO一次的时间是相同的。

       而第一种方式当中,每循一次,read一次,相当于只IO一次,读取了一次文件,就把所有的内容读取到内存当中了。

       因此,第二种方式减少了IO次数,提高了执行的效率。


 ②FileOutputStream(文件输出流)

       文件专门是把内存当中的数据读取到文件(磁盘)当中。

       也是在构造方法当中指定了需要传输的对应的文件。

OutputStream outputStream=new FileOutputStream("./hello.txt");

       需要注意的是,构造方法当中指定的字符串一定要合法,合法的体现性为字符串一定要以文件目录的形式开头,例如./某某文件这样的格式。或者D:/***/***这样的格式,需要指定文件的目录。


       如果对应的目录下面不存在这个文件,那么会首先创建一个这样的文件出来;


        write()方法

        跟FileInputStream一样,也是存在多态的

       这个write() 方法的操作和read()类似,只是一个输入,一个输出。

       需要注意的是,如果程序启动之前,原来的文件当中仍然有内容,那么,第一次write()的时候,会把原来文件当中的内容全部清空。


 五、close()方法      

       这个方法的含义就是关闭当前的"流”。

       当进行完对应的读写操作之后,应当及时把这个"流"给关闭掉。

       就是调用inputStream.close()或者outputStream.close()。


     需要及时关闭"流"的原因:

        根据前面的知识,我们了解到,进程当中有一个重要的属性,就是文件描述符表,这样的一个"表"。其实相当于一个数组,记录了进程打开了哪些文件。

        一个进程当中的所有线程,共用一个文件描述符表

        每次打开文件的操作,就会在文件描述表当中,申请一个位置,把对应文件的信息存放进去。  每一个被打开了的文件,在内核当中,都是一个file_struct对象。 

        每关闭一个文件,都会把对应的表项释放掉。也就是销毁对应的file_struct对象

        而调用fileInputStream.close()或者fileOutputStream.close(),就相当于上面的"释放"操作。

        如果没有这个操作,那么会造成什么后果呢?

       也就是会让这个file_struct对象一直保留在文件描述符表当中,无法被销毁。这样,会造成极大的内存空间浪费。

       并且,当打开的文件数量越来越多的时候,有可能很快就会让这个"数组"被填满了。也就是当需要再次打开文件的时候,已经无法操作了。

       虽然Java当中有gc垃圾回收机制,会在inputStream或者outputStream被回收的时候释放资源。但是,如果打开的文件太多,有可能gc也来不及释放了。


     


 六、更加优雅的close()方式

       在了解了close()方法的含义之后,可以得出一个结论,就是close()操作一定是在打开文件之后必定进行的一个操作,也就是close()操作是必不可少的。因此,最好把close()操作放在finally代码块当中执行:如下代码:

 FileOutputStream outputStream=null;try {outputStream=new FileOutputStream("./hello.txt");outputStream.write(99);}finally {outputStream.close();}

      这样,就可以让close()操作一定被执行到了。 

      但是,Java当中提供了下面的更加"优雅"的关闭方式:

try (FileOutputStream outputStream = new FileOutputStream("./hello.txt")) {outputStream.write(99);outputStream.write(100);outputStream.write(101);outputStream.write(103);}

     这样,会在write()完所有的内容之后,自动关闭流,释放资源。

     但是,需要注意的是,不是任何一个对象都可以放到try()的括号当中的。

      一定要实现closeable接口:


          采用Scanner来读取磁盘的内容:

           我们通常想从控制台获取输入的时候,会创建Scanner对象:

Scanner scanner=new Scanner(System.in)

            其中,System.in就是一个输入流对象: 

             如果想让Scanner从磁盘当中读取内容,可以考虑这样操作:

public static void main(String[] args) {try (InputStream inputStream=new FileInputStream("./hello.txt")){Scanner scanner=new Scanner(inputStream);//此时读取的内容,就是从hello.txt当中读取的//这里将一次读取全部的内容System.out.println(scanner.next());} catch (IOException e) {e.printStackTrace();}}

           那么这样,读取到的内容就是对应hello.txt文件的全部内容了。

           同时,inputStream对象也已经被关闭了。,也就意味着scanner也被关闭了。 


  七、字符流      

         前面介绍的FileInputStream和FileOutputStream都是字节流,以字节为单位进行读写的。

         下面,将介绍字符流:FileReader以及字节流:FileWriter,以字符为单位进行读写的。

public static void main(String[] args) {try (Writer writer=new FileWriter("./hello.txt")){//写入的时候,如果是数字,那么会转化为对应的ASCII码的字母//如果是’单引号的字符,那么会直接写入单引号的字符writer.write('?');writer.flush();} catch (IOException e) {e.printStackTrace();}}

         当传入的为一个数字的时候,会把它转换为一个字符来进行读写。

   当传入的为一个字符的时候,直接写入一个对应的字符。


         flush方法

        当直接调用writer.write()方法的时候,其实是写入一个缓冲区当中。

        写操作执行完毕之后,内容可能还残留在缓冲区当中,还没有真正进入磁盘当中。

         因此,调用flush()方法,可以确保缓冲区当中的内容被同步到磁盘。

         


 

   

        

     

          

        

        


http://chatgpt.dhexx.cn/article/t5D5jkE4.shtml

相关文章

IO操作

一、简介 IO流是用来处理设备之间的数据传输的&#xff0c;数据一般储存在设备上 设备&#xff1a;硬盘&#xff0c;光盘&#xff0c;内存等等&#xff0c;内存是临时储存的 Java对数据的操作是采用流的方式 按照操作的数据分为&#xff1a;字节流和字符流 暗照流向&#x…

Java基础--IO操作

一、IO原理及分类 一、IO原理 1、I/O是Input/Output的缩写&#xff0c;I/O技术是非常实用的技术&#xff0c;用于处理设备之间的数据传输&#xff0c;如读写文件&#xff0c;网络通信等。 2、java程序中对于数据的输入/输出操作一般都是以流的方式进行 3、java.io包下提供各…

关于I/O操作

https://blog.csdn.net/deram_boy/article/details/51191425 提及这个&#xff0c;就想到了各种文件操作&#xff0c;这种流&#xff0c;什么reader 啊&#xff0c; writer啊&#xff0c;buffer啊&#xff0c;file啊。但是综合的东西与总结&#xff0c;只是曾经了解。因为工作…

IO操作概念

IO&#xff1a;输入输出&#xff0c;对程序的输入与输出 文件&#xff1a;一组有关数据的集合 文件名&#xff1a;这组数据的名字 linux系统中所有文件均属于文件&#xff08;通过文件系统进行管理&#xff09; 按类型分类&#xff1a; 1、普通文件 &#xff08;…

I/O操作

前言 I/O操作即操作存储器&#xff0c;所以想了解I/O操作&#xff0c;需要了解一点存储器相关知识点。 计算机存储器 存储器是计算机的核心部件之一&#xff0c;在完全理想的状态下&#xff0c;存储器应该要同时具备以下三种特性&#xff1a; &#xff08;1&#xff09;速度…

操作系统_04_IO相关(个人总结)

声明: 1. 本文为我的个人复习总结, 并非那种从零基础开始普及知识 内容详细全面, 言辞官方的文章 2. 由于是个人总结, 所以用最精简的话语来写文章 3. 若有错误不当之处, 请指出 软硬链接 软链接(快捷方式): 删除原文件时, 软链接则失效 硬链接…

gcc 命令

gcc 命令 GCC 编译器 gcc 命令格式 gcc 选项 文件名字主要选项 -c&#xff1a; 只编译不链接为可执行文件&#xff0c;编译器将输入的.c 文件编译为.o 的目标文件。-o&#xff1a; <输出文件名>用来指定编译结束以后的输出文件名&#xff0c;如果不使用这个选项的话 G…

Ubuntu Linux gcc的常用命令

目录 一、gcc简介 二、简单的gcc编译 1 预处理 2 编译为汇编语言代码 3 汇编 4 连接 三、多个程序文件的编译 四、检查错误 五、连接库文件 1 编译成可执行文件 2 链接 3 强制链接时使用静态链接库 六、总结 一、gcc简介 Linux系统下的Gcc&#xff08;GNU C Compi…

Linux GCC 编译详解

文章目录 一、GCC 编译器简介二、GCC 工作流编程语言的发展GCC 工作流程gcc 和 g 的区别 三、使用 GCC 编译GCC 编译格式GCC 编译流程多个源文件编译 一、GCC 编译器简介 首先&#xff0c;什么是编译器呢&#xff1f; 我们可以使用编辑器&#xff08;如 linux 下的 vi、window…

gcc编译命令的常用选项——强烈推荐大家使用 -Wall 选项

C程序编编译的过程分为如下四个阶段 1.预处理&#xff1a;头文件展开&#xff08;#include&#xff09;、宏替换&#xff08;#define&#xff09;、条件编译&#xff08;#ifdef&#xff09;(.i)使用预处理器&#xff08;预处理阶段处理的都是以#开头的代码&#xff09; 2.编译…

Linux(gcc编译原理、过程以及常用调试命令)

PS&#xff1a;红色字体表示重点&#xff0c;绿色字体表示重要标题&#xff0c;块引用中表示Linux终端中的命令。 1.gcc / g的安装 命令&#xff1a;sudo apt install gcc /gcc 2.gcc编译连接 //main.c文件 &#xff08;1&#xff09;预编译 ①删除所有的“#define”&#…

Linux中gcc编译步骤

我们这里以C语言为例&#xff0c;看看C语言程序在Linux中编译执行的详细步骤 1.创建一个.c文件 2.写入一些简单的代码 我们使用gcc -E filename.c -o filename.i 命令对程序先进行预处理&#xff1a;处理头文件、宏定义&#xff0c;接下来我们修改一下头文件&#xff0c;使用错…

Linux GCC常用命令

目录 一、示例一 1.简单编译 1.1预处理 1.2编译为汇编代码 1.3汇编 1.4连接 2.多个程序文件的编译 3检错 4库文件连接 二、示例二 1.准备hello.c 2.预处理 3.编译 4.汇编 5.链接 6.分析ELF文件 6.1ELF文件的段 6.2反汇编ELF 一、示例一 1.简单编译 创建文件mkd…

GCC编译过程及基本命令总结

一、GCC简介 GCC即GNU Compiler Collection&#xff0c;原本只是针对C语言的编译工具&#xff0c;现在已经变成了一个工具集&#xff0c;包含了C、C、JAVA等语言的集合体。 管理和维护&#xff1a;由GNU项目负责。 二、GCC对C、C的编译流程 (1) 预处理&#xff08;Preproce…

Linux 下的 gcc 编译常用命令

gcc&#xff1a;Linux下的一款编译器。 gcc工作流程&#xff1a; 完整编译流程&#xff1a; 创建一个c语言源文件&#xff1a; gcc -E hello.c -o hello.i&#xff08;头文件展开&#xff0c;进行源文件中的宏替换&#xff0c;注释过滤&#xff09; gcc -S hello.i -o hello.…

GCC命令编译

1.GCC编译过程&#xff08;原理如下&#xff0c;使用命令请见2&#xff09; 从 hello.c 到 hello(或 a.out)文件&#xff0c; 必须历经 hello.i、 hello.s、 hello.o&#xff0c;最后才得到 hello(或a.out)文件&#xff0c;分别对应着预处理、编译、汇编和链接 4 个步骤&#…

gcc 命令详解及最佳实践

介绍 GCC&#xff08;英文全拼&#xff1a;GNU Compiler Collection&#xff09;是 GNU 工具链的主要组成部分&#xff0c;是一套以 GPL 和 LGPL 许可证发布的程序语言编译器自由软件&#xff0c;由 Richard Stallman 于 1985 年开始开发。 GCC 原名为 GNU C语言编译器&#…

使用GCC编译程序常用命令

一、编译器驱动程序 首先梳理一下源文件到可执行文件的整个过程&#xff0c;下面是两个源文件的组成main.c和sum.c // main.c int sum(int *a, int n); int array[2] { 1, 2 }; int main() {int val sum(array, 2);return val; }// sum.c int sum(int *a, int n) {int i, s…

matlab 反向二值化,MATLAB:图像二值化、互补图(反运算)(im2bw,imcomplement函数)...

图像二值化、反运算过程涉及到im2bw&#xff0c;imcomplement函数&#xff0c;反运算可以这么理解&#xff1a;原本黑的区域变为白的区域&#xff0c;白的区域变为黑的区域。 实现过程如下&#xff1a; close all;%关闭当前所有图形窗口&#xff0c;清空工作空间变量&#xff0…

图像处理Matlab阈值的设置imadjust(),graythresh(),im2bw()函数使用

1、imadjust()函数调节图像的对比度(若图像较暗&#xff0c;可用imadjust函数命令来调节图像的对比度) I1imadjust(I,stretchlim(I),[0;1]); % stretchlim(I2)自适应找到一个分割阈值向量来改变一幅图像的对比度 figure,imshow(I1); 2、matlab中DIP工具箱函数im2bw使用阈值&…