Java之文件操作与IO

目录

一.认识文件

1.1文件是什么?

1.2文件的组织

1.3文件路径

1.4文件的分类

二.文件操作

2.1File概述

三.文件内容操作--IO

3.1JavaIO的认识

3.2Reader和Writer

⭐Reader类

⭐Writer类

3.2FileInputStream和FileOutputStream

⭐FileInputStream类

⭐FileOutputStream类

四.总结


🎁个人主页tq02的博客_CSDN博客-C语言,Java,Java数据结构领域博主

🎥 本文由 tq02 原创,首发于 CSDN🙉

🎄 本章讲解内容:文件和IO的讲解

🎥多线程学习专栏:多线程学习专栏

🎥其他学习专栏: C语言 JavaSE MySQL基础

在学习文件操作前,我们需要了解文件的基本信息,才能懂得如何操作文件,使用文件。

一.认识文件

1.1文件是什么?

问:文件,是图片、文档、视频、压缩包又或者是那种文件夹呢?

答:某种意义上,都是文件。

文件:拥有数据内容,以及一些元信息,例如:文件名、文件类型和文件大小等数据

如果你拥有一台电脑,就会经常与文件打交道,例如:ppt、word等。而对于计算机,这些文件都是不一样的,主要区别是后缀名不一样。文件一般存放在硬盘当中。

1.2文件的组织

在计算机上面拥有很多文件,因此我们不得不对文件进行管理、组织。但是如何组织呢?目前通过层序级结构进行组织,类似我们在数据结构里学的树形结构,也就是电脑上的文件夹或者目录的概念。

1.3文件路径

文件路径分2种,一种绝对路径 ,一种相对路径

**绝对路径:**指文件在硬盘上真正存在的路径。它从根目录开始,一直到目标文件所在的目录,包括所有的父级目录。


例如,1.txt文件的绝对路径是"C:\Users\15063\Desktop\1.txt",那么该文件在C盘下Users文件夹中15063文件中Desktop文件夹中。
相对路径: 相对于当前文件所在目录的路径。它描述了从当前目录到目标文件的位置。相对路径可以是简短的,只需指示当前目录和目标文件之间的相对位置即可。


例如:1.txt 文件在C:\Users\15063\1.txt,2.txt 在C:\Users\15064\Desktop\2.txt

因此对于2.txt文件而言,上一级目录是15064目录,再上一级目录是Users目录,而15063目录也在Users目录下的文件夹,在该文件夹中有1.txt文件。

./:当前目录 ../:上级目录 /下级目录

额外补充:在windows上,/ 和 \ 没有区别,都可以使用,

例如:1.txt文件位置:C:\Users\15063\Desktop\1.txt,也可以是C:/Users/15063/Desktop/1.txt

但是在linux当中,必须使用 /

1.4文件的分类

文件根据保存数据的不同,一般分为2种类型,文本文件和二进制文件,

文本文件 二进制文件

存储的是字符(utf8字符集) 存储二进制数据
问:如何判断文件是字符还是二进制?

答:使用记事本打开,如果看的懂,就是文本文件,看不懂就是二进制文件。

二.文件操作

文件操作 是指在计算机中对文件进行读取、写入、修改等各种操作的过程。文件操作可以包括创建和删除文件,打开和关闭文件,读取和写入文件内容等

2.1File概述

本章使用Java的方式进行文件操作。Java 中通过 java.io.File 类来对一个文件(包括目录)进行抽象的描述。注意,有 File 对象,并不代表真实存在该文件。File只能对文件操作,不能操作文件的内容。

|----------------------------------|-----------------------------------|
| File类的构造方法 | 说明 |
| File(File parent,String Child) | 根据父目录和孩子文件路径,创建新的File实例 |
| File(String pathname) | 根据文件路径创建一个新的File实例,路径方式:绝对和相对 |
| File(String parent,String Child) | 根据父目录和孩子文件路径,创建新的File实例, 父目录用路径表示 |

个人认为,这个File就是让编译器找到对应目录,不在乎是否会有这个文件。我们一般使用中间的构造函数:File(String pathname) 如果想确认文件是否存在,获取路径或者创建文件等等,需要使用Filed的方法

|---------------------|---|---|-----------------------------------|
| File类的方法 | 返回类型 || 说明 |
| getParent() | String || 返回 File 对象的父目录文件路径 |
| getName() | String || 返回 Fle 对象的纯文件名称 |
| getPath() | String || 返回 File 对象的文件路径 |
| getAbsolutePath() | String || 返回 File 对象的绝对路径 |
| exists() | boolean || 判断 File 对象描述的文件是否真实存在 |
| isDirectory | boolean || 判断 File 对象代表的文件是否是一个目录 |
| isFile() | boolean || 判断 File 对象代表的文件是否是一个普通文件 |
| createNewFile() | boolean || 根据 File 对象,自动创建一个空文件。成功创建后返 true |
| delet() | boolean || 根据 File 对象,删除该文件。成功删除后返回 true |
| mkdirs() | boolean || 创建 File 对象代表的目录,如果必要,会创建中间目录 |
| renameTo(File dest) | boolean || 进行文件改名,也可以视为我们平时的剪切、粘贴操住 |
| deleteOnExit() | void || 根据 File 对象,标注这个文件,JVM 运行结束时会删除 |
| list() | String[ ] || 返回 Fle 对象代表的目录下的所有文件名 |
| listFiles() | File[ ] || 返回 File 对象代表的目录下的所有文件,以 File 对象表示 |

利用已学知识点,我们现在可以进行文档的创建,查询等操作

先创建一个word文档:文件.txt :

使用其他方法:

以上就是File类的所有知识点了,可是你有没有发现一个问题?似乎只能创建文件,查询文件位置,删除文件,而不能对文件进行操作!!!对文件内容进行操作也有其对应的类。


三.文件内容操作--IO

3.1JavaIO的认识

文件内容的操作缺少不了流,使用的类便是文件流(.stream).

文件流类似水流,例如:有一个1000ml的水桶,可以分为10次接(每次100ml)、也可以分为5次接(每次200ml)等等。而操作文件时,也是一样的,可以分多次读取。


Java IO可以分为输入流和输出流,分别对应于读取和写入数据。其中,输入流包括InputStream和Reader,输出流包括OutputStream和Writer。

关于操作字节流的类有:InputStream、OutputStream ----二进制文件

关于操作字符流的类:Reader、Writer-----文本文件

不同的编程语言对于文件操作都有不同的api,但是它们的核心步骤相同:

  1. 打开文件
  2. 关闭文件
  3. 读文件
  4. 写文件

3.2Reader和Writer

Java中Reader和Writer是用于字符流的输入和输出的抽象类(不可以直接创建的)。它们是用来处理字符数据的,而不是字节数据。Reader和Writer提供了一组方法来读取和写入字符数据,可以用于读取和写入文本文件以及其他字符流。

⭐Reader类

创建:Reader 对象名=new FileReader( 文件路径 或 File对象);

注:会产生异常,可能存在文件无法查找,因此需要抛出异常或者使用try{}catch{}

代码示例:

java 复制代码
//构造方法传递文件路径
Reader read=new FileReader("D:\360安全浏览器");

//构造方法传递File对象
File t1=new File("D:\360安全浏览器");
FileReader raeder=new FileReader(t1);

文件操作中,打开文件,也需要关闭文件。

**关闭文件:**对象名.close();

注:也会产生异常,也需要抛出异常IOException,而创建产生的异常是IOException的子类,因此只需要抛出IOException异常即刻。

未执行close()方法的后果:

  1. 导致文件资源泄露。
  2. 占用进程的PCB的文件描述表会被占满,后续就无法打开新的文件。

对于close()方法,我们可能会发生特殊的情况,导致代码没有执行到close()。

java 复制代码
public int add(){
     FileReader raeder=new FileReader(./src/文件.txt);
     return 10; //该方法调用时,打开了文件,但是还没有关闭文件,就已经使用return结束了。
     raeder.close();
}

而对于以上情况,有一种特殊的用法,使代码自动调用close()方法

try(Reader 对象名=new FileReader( 文件路径 或 File对象)){

//待执行方法

}

注:try代码执行完毕之后,会自动调用close()方法。该方法也适用于其他内容操作类

|--------------|----------|
| Reader类的方法 | 解释 |
| read() | 读取字符 |
| skip(long n) | 跳过的字符数目n |
| ready() | 是否准备好读取 |

代码示例:

java 复制代码
                 //文件中的内容:1 2 3 4 5 6 7 8
  try(FileReader t1=new FileReader("./src/文件.txt"))
   {
        System.out.println( t1.read()); //读取1 对应的字符集数字
        System.out.println( t1.read()); //读取2 对应的字符集数字
        t1.skip(2);      //跳过2个字符
        System.out.println(t1.read()); //读取5 对应的字符集数字
     }

⭐Writer类

创建:Writer 对象名=new FileWriter( 文件路径 或 File对象);

注:会产生异常,因此需要抛出异常或者使用try{}catch{}。

代码示例:

java 复制代码
//构造方法传递文件路径
Writer kk=new FileWriter("kk.txt");

//构造方法传递File对象
 File t1=new File("kk.txt");
 FileWriter kk=new FileWriter(t1);
  • FileWriter构造方法:
java 复制代码
FileWriter(File file)
//用一个打开的文件描述符作为构造参数,数据将输出到该文件描述符对应的节点

FileWriter(File file,FileDescriptor fd)
//append是否以追加的方式写,如果该fd为false,则文件会被覆盖,下边append同义
  • Writer方法

|--------------------------------------------|-----------------------------|
| Writer方法 | 解析 |
| append(char c) | 将指定的字符c附加到此。 |
| append(CharSequence csq) | 将指定的字符序列 csq 写入文件 |
| append(CharSequence csq,int start,int end) | 将指定的字符序列的子序列写入文件 |
| write(char[] cbuf) | 此方法写入字符数组。 |
| write(char[] cbuf, int off, int len) | 写入字符数组的一部分 |
| write(int c) | 写入的单个字符(数字c对应的Unicode位置的字符) |
| write(String str) | 写入一个字符串。 |
| flush() | 此方法刷新流。 |
| close() | 关闭 |

代码示例:

java 复制代码
  public static void main(String[] args) throws IOException {
        CharSequence csq = "Hello World!";
        //writer和append以追加的方式写入,而不是覆盖
       try(Writer kk=new FileWriter("kk.txt",true))
       {
           //write方法
            char[] array={'a','b','c','d'};
            kk.write(array);    //把数组传递到文件当中
            kk.write(100);//对应的Unicode表是d;
            kk.write("\nHello World! \n\n"); //将字符串传递到文件当中
            kk.flush(); //刷新保存数据;

           //append方法
           kk.append('c');
           kk.append(csq,0,5);  //将csq的字符序列的0到5的子序列,传递到文件当中
           kk.append(csq);     //将csq的字符序列传递到文件当中
           kk.flush(); //刷新保存数据;

           //不需要使用close();
       }

注:虽然append方法不可以传递字符串,但是可以借CharSequence,传递字符序列,达成相同的结果。

  • append和write的区别:
  1. append方法是Writer类中的一个重载方法,在Writer类中有多个append方法,用于向输出流中添加字符、字符串、字符数组等。write方法则只有一个,接受一个字符数组或字符串参数。

  2. append方法返回值是调用该方法的Writer对象实例,可以链式调用多个append方法,实现连续的输出。而write方法没有返回值。

  3. append方法可以在输出流中添加任何类型的数据,包括null,而write方法不能输出null,否则会抛出NullPointerException异常。

  4. append方法可以在输出流中追加字符,而write方法只能一次性输出全部字符,不能追加。

综上所述,append方法更加灵活,可用于向输出流中添加不同类型的数据,而write方法则更加简单,只能输出字符串或字符数组,不能追加数据。


3.2FileInputStream和FileOutputStream

在InputStream类和OutputStream类中,我们主要讲解他们的子类FileInputStream类和FileOutputStream类。

注:FileInputStream和FileOutputStream是以字节方式操作文件

⭐FileInputStream类

FileInputStream类用于从文件中读取字节流。它继承自InputStream类,并提供了一些方法来读取文件中的数据。你可以使用它来打开一个文件,并从文件中逐个字节地读取数据。不仅可以读取文本内容,甚至可以读取图像文件。注:一个字节为8个bit

构造方法:

java 复制代码
//利用 File 构造文件输出流
File t1=new File("kk.txt");
FileInputStream t2=new FileInputStream(t1) 

//利用文件路径构造文件输入流
InputStream t2=new FileInputStream(String name) 

注:文本文件也可以使用字节流打开。但由于是读取的是每一个字节,因此可能无法代表完整字符。

FileInputStream方法:

|----------------------------------|-------------------------------------------|
| 方法 | 解析 |
| read(byte[] b,int off,int len) | 一次读取len个字节,从数组off下标开始,填充len个字节数,返回读取的字节个数 |
| read(byte[] b) | 一次读取读取最多b.length个字节的数据到字节数组b,返回读取的字节个数, |
| read() | 读取一个字符,如果没有输入可用,此方法将阻止。返回字节数据 |
| skip() | 跳过并从输入流中丢弃n个字节的数据。 |
| available() | 返回输入流当中剩余字节数的估计数, 文件位置超出EOF时返回0 |
| close() | 关闭此文件输入流并释放与流相关联的任何系统资源。注:使用try可以省略该方法 |

代码示例:

java 复制代码
 public static void main(String[] args) throws IOException {
//使用try,可以不使用close()方法
        try(InputStream inputStream=new FileInputStream("kk.txt")) {
//查询kk文件当中,还有多少字节
    System.out.println(inputStream.available());   
//查询当前字节是什么?        
     System.out.println(inputStream.read());
//将文件内容传递到数组aa当中
     byte[] aa=new byte[10];
     int a=inputStream.read(aa,3,4);  //将数组下标为3开始,存储3个输入流的字节,
                                      //返回,存储的数目
      int b=inputStream.read(aa);   //返回数组存储输入流的数目个数         
    }
}

:如何将读取到的字节转换为原本的内容?例如,文本里是文字等内容,可是读取出来为字节,无法知晓原本的内容。

:2种方法

  1. 借助一些额外的工具类完成字节转换为字符串的工具类
  2. 直接使用String类,使用构造方法。

方法一:

java 复制代码
public static void main(String[] args) throws IOException {
                                        //文档中内容为:我爱你,Java
  try(InputStream inputStream=new FileInputStream("kk.txt")) { 
     byte[] aa=new byte[1024];
     int a=inputStream.read(aa);  将文本内容输入到数组byte当中。
      
      String t1=new String(aa,0,a,"utf8");
    System.out.println(aa);    //输出:我爱你,Java        
    }
}

方法二:工具类:Scanner,可将当前读取到的字节数据进行转换。数据可以是标准输入,也可以是其他来源。注:不可以读取二进制文件

java 复制代码
 try(InputStream inputStream=new FileInputStream("kk.txt")) {
    //从键盘上读取数据
      Scanner scan=new Scanner(System.in);

    //此时就是从文件当中读取数据
      Scanner sc=new Scanner(inputStream);
         String s=sc.next();
         System.out.println(s);
}

额外补充:调整idea的字符集方法:File-->Settings

⭐FileOutputStream类

FileOutputStream类用于将字节流写入文件。它继承自OutputStream类,并提供了一些方法来向文件中写入数据。你可以使用它来创建一个新文件或覆盖已有的文件,并将字节数据写入文件中。例如,你可以使用FileOutputStream将文本数据写入一个新文件,或者将图像数据写入一个图像文件中。

构造方法:

java 复制代码
//利用 File 构造文件输入流
File t1=new File("kk.txt");
FileOutputStream t2=new FileOutputStream(t1) 

//利用文件路径构造文件输入流
OutputStream t2=new FileOutputStream(String name) 

OutputStream的方法:

|------------------------------------|----------------------------|
| 方法 | 解析 |
| close() | 关闭此输出流并释放与此流相关联的任何系统资源。 |
| flush() | 刷新此输出流并强制任何缓冲的输出字节被写出。 |
| write(byte[] b) | 将字节数组输入到文件中 |
| write(byte[ ] b,int off,int len) | 将下标为off的位置开始,输入len个字节到文件当中 |
| write(int b) | 将指定的字节输入到文档当中 |

如同InputStream的方法,可以搭配Scanner()方法,OutputStream可以搭配PrintWriter

java 复制代码
import java.io.*;

public class PrintWriterExample {
    public static void main(String[] args) {
        try {
            OutputStream outputStream = new FileOutputStream("kk.txt");
            PrintWriter printWriter = new PrintWriter(outputStream);

            printWriter.println("Hello, World!");
            printWriter.println("This is an example.");

            printWriter.close();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在上面的示例中,我们创建了一个名为kk.txt的文件,并将其作为输出流的目标。然后,我们创建了PrintWriter对象,并将outputStream作为参数传递给它。最后,我们使用printWriter的println方法来写入文本内容,并在最后关闭printWriter和outputStream。这样,文本将被写入到output.txt文件中。你可以根据自己的需求修改输出的目标和写入的内容。


四.总结

  1. 字节操作: InputStream、OutputStream 字符操作:Reader、Writer
  2. 使用try的方法,可以避免忘记close()方法。
  3. Scanner工具类,可以读取键盘输入的数据,也可以接收文本的数据,但不可以读取二进制文件
  4. PrintWriter搭配OutputStream,可简化代码效果,提供了printf、println等方法直接写入到文件当中
  5. 输出流对象(无论是字节流还是字符流)会打开文件之后,清空文件内容。但可以使用追加的方法,此时不会清空内容。
相关推荐
一只爱打拳的程序猿14 分钟前
【Spring】更加简单的将对象存入Spring中并使用
java·后端·spring
杨荧16 分钟前
【JAVA毕业设计】基于Vue和SpringBoot的服装商城系统学科竞赛管理系统
java·开发语言·vue.js·spring boot·spring cloud·java-ee·kafka
minDuck18 分钟前
ruoyi-vue集成tianai-captcha验证码
java·前端·vue.js
白子寰22 分钟前
【C++打怪之路Lv14】- “多态“篇
开发语言·c++
王俊山IT34 分钟前
C++学习笔记----10、模块、头文件及各种主题(一)---- 模块(5)
开发语言·c++·笔记·学习
为将者,自当识天晓地。36 分钟前
c++多线程
java·开发语言
小政爱学习!38 分钟前
封装axios、环境变量、api解耦、解决跨域、全局组件注入
开发语言·前端·javascript
daqinzl44 分钟前
java获取机器ip、mac
java·mac·ip
k09331 小时前
sourceTree回滚版本到某次提交
开发语言·前端·javascript
激流丶1 小时前
【Kafka 实战】如何解决Kafka Topic数量过多带来的性能问题?
java·大数据·kafka·topic