Java IO流(超详细!)上篇

本文详细介绍了Java中的File类用于操作文件和目录,以及I/O流的分类(输入流、输出流、字节流和字符流),包括各自的子类如FileOutputStream和FileInputStream,以及字符流的Writer和Reader类。实例演示了如何使用这些类进行文件操作和数据读写。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一、File类

在程勋运行的过程中,输入/输出是常用的操作,也是必需的部分。允许程序读取外部数据,包括来自磁盘、光盘、文件等存储设备的数据,这类操作属于输入数据;同时允许程序记录运行状态,将程序数据输出到磁盘、光盘、文件等存储设备中,这类操作属于输出数据,数据的输入和输出离不开文件,经常使用到的文件类型很多,如扩展名为 .txt、.doc、.class的文件等。
File类是java.io包下代表操作与平台无关的文件和目录的类,也就是说,如果需要在程序中操作文件或目录,就可以通过File类实现对文件或目录的新建、删除、重命名等操作。

1、操作文件和目录

在程序中,一个File对象可以代表一个文件或目录。它可以查出与文件相关的信息,如名称、修改日期、文件大小等。File类的构造方法定义如下:

public File(String pathName)

其中,pathName指定文件路径。因此,在创建File对象的时候必须设置文件路径。
例如:

File file=new File("C://test.txt");

注意:在Windows操作系统中,文件路径名中的路径分隔符可以使用正斜杠“ / ”,如“C:/test.txt”,也可以使用反斜杠“ \ ”,但必须写成“ \ ”,其中第一个“ \ ”表示转义符。

方法描述
boolean createNewFile()创建新文件
boolean delete()删除文件
boolean exists()判断文件是否存在
Boolean isFile()判断是否是文件
boolean isDirectory()判断是否是目录
long length()返回文件长度,单位为字节;若文件不存在,则返回0L
String getPath()返回文件名对应的相对路径
String getAbsolutePath()返回此对象文件的绝对路径
String getName()返回此对象表示的文件或目录的名称

在这只列举了File类的一些常用方法,在实际开发中,如需完成对File类的更多操作,则可随时查询API帮助文档

在程序当前目录下创建非空文件test.txt,编码实现创建文件对象,判断文件是否存在,输出路径、文件名、长度及判断File对象存储内存是否为文件。
示例:

import java.io.File;
public class FileTest {
    public static void main(String[] args) {
        File file=new File("text.txt");
        if (file.exists()){
            if (file.isFile()){
                System.out.println("文件名:"+file.getName()+",文件长度:"+file.length()+"字节");
                System.out.println("文件路径是:"+file.getPath());
                System.out.println("文件绝对路径是:"+file.getAbsolutePath());
            }
            if (file.isDirectory()){
                System.out.println("此文件是目录");
            }
        }else {
            System.out.println("此文件不存在!");
        }
    }
}
文件名:test.txt,文件长度:32字节。
文件路径是:test.txt
文件绝对路径是:D:\IdeaProjects\Exam\test.txt

其他方法类似,就不在这坐多解释和实例了!

二、I/O流概述

File类能够实现对文件和目录的创建、删除等基础性操作,但是无法实现对文件内容的操作,也就是无法实现对文件的读写。而在Java中的I/O流能够方便地实现数据的输入和输出,是实现文件读写的基础。
流,是指一连串流动的字符,是以先进先出的方式发送和接收数据的通道。既然是流,必须是源端和目的端,它们可以是计算机内存的某些区域,也可以是磁盘、文件等,甚至可以是Internet上的某个统一资源定位符。所谓I/O流就是实现数据输入和输出的流,在I/O流的基础上,可以实现对文件的读写操作。

注意:
I/O流的 I 即 input,指读入操作;O 即 output,指写出操作。

1、按流向划分:输入流和输出流

流具有明确的方向性,按照流的流向来分,可以分为输入流和输出流。

  1. 输入流:只能从中读取数据,而不能写入数据的流,实现程序从数据源中读数据。
  2. 输出流:只能向其写入数据,而不能从中读取数据的流,实现程序向目标数据中写数据。

注意:
按照流的流向进行分类时,输入流完成数据读入操作,输出流完成数据写出操作,这里的“出”和“入”一定是从程序运行所在内存的角度来论述。如果从文件或磁盘的角度来论述,方向恰恰相反,混淆了概念就会引发错误。

2、按处理单元划分:字节流和字符流

按照处理单元划分,Java中的流可分为字节流和字符流,它们的区别在于操作的数据单元不同。

  1. 字节流:以8位字节为操作数据单元的流,可用于操作二进制数据(如操作图片文件)。
  2. 字符流:以16位的字符为操作数据单元的流,可用于操作文本数据。

通俗地理解,可以把I/O流看作一个水管,这个水管中依次排列着许多水滴,每滴水滴就是一个处理单元,即一个字节或字符。

3、按流的角色划分:节点流和处理流

按照流的角色划分,Java中的流可分为节点流和处理流。

  1. 节点流:可以直接向一个特定的存储介质(如磁盘、文件)读写数据的流。
  2. 处理流:用于对一个已存在的流进行连接和封装,是通过封装后的流实现数据读写操作的流。

三、字节流

java.io包中的流按存储单元分类主要有字节流和字符流量大类,两类都具有输入/输出操作。

1、字节输出流基类:OutputStream

OutputStream类为抽象类,必须使用该类的子类进行实例化对象。如果需要操作文件,则使用FileOutputStream实例化。
OutputStream类中的主要操作方法

方法描述
void close()关闭输出流
void flush()刷新缓冲区
void write(byte[] b)将每个byte数组写入数据流
void write(byte[] b,int off,int len)将每个指定范围的byte数组写入数据流
void write(int b)将一个字节数据写入数据流

2、字节输出流FileOutputStream类

在实际应用中,通常使用OutputStream类的FileOutputStream子类向文本写入数据,常用的构造方法如下表格:

方法描述
FileOutputSteam(File file)用于创建向指定File对象写数据的文件输出流。file:指定目标文件的对象
FileOutputSteam(String name)用于创建向指定路径的文件写数据的文件输出流。name:指定目标文件的路径字符串
FileOutputSteam(String name,boolean append)创建一个向指定路径的文件写入数据的文件输出流。name:指定目标文件的路径字符串。append:表示是否在文件末尾追加数据,若为true则表示可以在文件末尾

注意: 在以上表格中,前两种构造方法在向文件写数据时将覆盖文件中原有的内容。
另外,在使用FileOutputStream类的构造方法创建对象时,如果相应的文件不存在,就会自动新建一个文件。如果参数file或name表示的文件路径是一个目录,则会抛出FileNotFoundexception异常。

下面通过示例介绍使用字节输出流向文本文件写入数据,实现向D:/doc/test.txt文件中写入字符串"I love java!"。

代码示例:

public class OutputstreamTest {
    public static void main(String[] args) {
        OutputStream fos = null;
        try {
            //2.创建文件输出流对象
            fos = new FileOutputStream("D:\\doc\\test.txt", true);
            //3.执行写操作
            String str = "I Love You";//准备一个字符串
            byte[] words = str.getBytes();//将字符串转换为byte数组
            fos.write(words, 0, words.length);
            System.out.println("文件已写入成功!");
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //4.关闭输出流
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

执行以上代码后,打开D:/doc/test.txt,查看运行结果,重复执行,可实现向文件末尾继续追加数据。
在这里插入图片描述

注意:
在编写代码时会发现,以上程序在创建输出流对象、执行写操作、关闭输出流时都可以会有IOException异常发生,因此除FileNotFoundException异常外,还需处理IOException异常。

3、字节输入流基类:InputStream

既然可以使用OutputStream类向文件中写数据,那么也可以通过InputStream类从文件中读数据。
InputStream类同样也是抽象类,该类中定义的主要方法如以下表格:

方法描述
int read()读取一个字节数据
int read(byte[] b)将数据读取到字节数组中
int read(byte[] b,in off,int len)从输入流中读取最多len的长度的字节,将其保存到字节数组中,保存的位置从off开始
void close()关闭输入流
int available()返回输入流读取的字节数

4、字节输入流FileInputStream类

在实际开发中,通常使用InputStream类的FileInputStream子类实现文本内容的读取,其常用构造方法如以下表:

方法描述
FileInputStream(File file)用于创建从指定File对象读取数据的文件输入流。file:指定目录文件数据源对象
FileInputStream(String name)用于创建从指定路径的文件读取数据的文件输入流。name:指定目标文件数据源路径字符串

下面通过示例介绍使用字节输入流从指定文件读取数据。

代码示例:

public class InputStreamTest {
    public static void main(String[] args) {
        InputStream fis = null;
        try {
            //2.创建文件输入流对象
            fis = new FileInputStream("D:\\test.txt");
          System.out.println("可读取的字节数:" + fis.available());
            //3.执行读操作
            byte[] words=new byte[1024];//创建字节数组
            int len=0;//实际读取长度
           int data = 0;
            //循环读取数据
            System.out.println("文件的内容:");
           while ((data = fis.read()) != -1) {
              System.out.print((char) data + "");}
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            //4.关闭输出流
            try{
                if (fis!=null){
                    fis.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

运行结果
在这里插入图片描述

四、字符流

在Java中,一个字符占用内存的两个字节。如果用字节流处理文本文件,则程序内部需要将字节转换成字符,降低了执行效率,所以当输入和输出文本文件时,尽量使用字符流。Java提供了Writer类和Reader类来操作字符。

1、字符输出流基类:Writer

Writer类是字符输出流的抽象基类,Writer类中定义的常用方法如以下表格:

方法描述
void write(String str)将str字符串中包含的字符输出到输出流中
void write(String str,int off,int len)将字符串中从off位置开始、长度为len的字符输出到输出流中
void close()关闭输出流
void flush()刷新输出流

2、字符输出流FileWrite类

FileWriter类是Writer类常用的子类,使用该类可以以字符为数据处理单元向文本中写数据。
下面通过示例完成使用FileWriter类向文本文件中写数据。

代码示例:

public class FileWriterTest {
    public static void main(String[] args) {
        Writer fw=null;
        try {
            //创建FileWriter对象
            fw=new FileWriter("D:/doc/mysaying.txt");
            OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("D:/doc/mysaying.txt"),"UTF-8");
            //向文件写数据
            fw.write("预测未来的最好方式就是创造未来!");
            fw.flush();//刷新缓冲区
            System.out.println("文件写入成功!");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("文件不存在!");
        } finally {
            if (fw!=null){
                try {
                    fw.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

运行结果:
在这里插入图片描述

3、字符输入流基类:Reader

Reader类是字符输入流的基类,它是抽象,Reader类中的常用方法如以下表格:

方法描述
int read()从输入流中读取单个字符,返回所读取的字符数据
int read(char[] c)从输入流中最多读取c.length个字符数据并将其存储在字符数组c中,返回实际读取的字符数
int read(char[] c,int off,int len)从输入流中最多读取len个字符的数据并将其存储在字符数组c中。在存入数组c中,并不是从数组起点开始的,而是从off位置开始的,返回实际读取的字符数

对比Reader类和InputStream类所提供的方法,会发现它们基本是相同的。如果将输入流比作水管,那么可以通过read()方法每次读取一滴“水滴”,也可以通过read(byte[] c)方法或read(char[] c,int off,int len)方法每次读取多滴“水滴”,多次重复执行取水的过程,当以上方法返回值为-1时,表示到了输入流的结束点,也就是取水完毕。

4、字符输入流FileReader

Reader类同样是抽象类,可以使用其子类FileReader创建对象。
代码示例:

public class FileReaderTest {
    public static void main(String[] args) {
        Reader fr = null;
        try {
            //2.实例化FileReader对象
            fr = new FileReader("D:/doc/诗词.txt");
            char[] ch = new char[1024];//创建字符数组作为转储容器
            int len = 0;//保存实际存储的字符数
            //3.循环读取数据
            while ((len = fr.read(ch)) > 0) {
                System.out.println(new String(ch,0,len));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //4.关闭流
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NoloveisGod

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值