【Java】什么是 FileInputStream


我听见有人猜
你是敌人潜伏的内线
和你相知多年
我确信对你的了解
你舍命救我画面
一一在眼前浮现
司空见惯了鲜血
你忘记你本是娇娆的红颜
感觉你我彼此都那么依恋
                     🎵 许嵩《内线》


在 Java 中,FileInputStream 是最常用的文件输入流类之一,用于从文件中读取字节数据。它是 Java I/O 流的一部分,允许程序以字节为单位读取文件内容,非常适合处理二进制文件(如图片、音频、视频等)以及文本文件的读取。本文将详细介绍 FileInputStream 的基本用法、内部实现及其适用场景。

1. 什么是 FileInputStream?

FileInputStream 是 Java 中 java.io 包的一部分,它继承自 InputStream 类。它主要用于从文件中读取数据,并且是以 字节流 的形式读取的,这意味着它处理的是原始的字节数据,而不是像 FileReader 那样处理字符数据。

FileInputStream 通常用于读取文件的原始内容,适合处理包括文本、图片、音频、视频等在内的各种文件类型。

FileInputStream 类的主要构造函数:
FileInputStream(String name):通过文件路径名称创建文件输入流。
FileInputStream(File file):通过文件对象创建文件输入流。

2. FileInputStream 的基本用法

FileInputStream 最基本的功能是从文件中逐字节读取数据。下面是一个简单的示例,展示如何使用 FileInputStream 读取文本文件。

示例 1:读取文件并输出内容
import java.io.FileInputStream;
import java.io.IOException;

public class FileInputStreamExample {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            // 创建 FileInputStream 对象,指定要读取的文件路径
            fis = new FileInputStream("example.txt");

            int content;
            // 逐字节读取文件内容,直到文件结尾
            while ((content = fis.read()) != -1) {
                // 输出文件的内容(字符形式)
                System.out.print((char) content);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 确保文件流被正确关闭
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}

示例输出:
假设 example.txt 文件内容如下:

Hello, World!

程序将输出:

Hello, World!

在这个例子中,我们使用 FileInputStream 创建了一个文件输入流,并通过 read() 方法逐字节读取文件内容。当文件的末尾到达时,read() 方法返回 -1,表示读取结束。

3. FileInputStream 的方法

FileInputStream 继承自 InputStream 类,因此它具有一些基础的输入流方法。以下是 FileInputStream 的常用方法:

3.1 int read()

读取文件中的下一个字节,并返回该字节的值(0-255 范围内的整数)。如果到达文件末尾,返回 -1。

int content = fis.read();
3.2 int read(byte[] b)

一次性读取多个字节,并将其存储在指定的字节数组 b 中。返回实际读取的字节数,如果到达文件末尾则返回 -1。

byte[] buffer = new byte[1024];
int bytesRead = fis.read(buffer);
3.3 int available()

返回当前输入流中可以读取的字节数,但不一定准确。这个方法可以用来检查文件中是否还有字节可读。

int bytesAvailable = fis.available();
3.4 void close()

关闭文件输入流,释放与该流相关的所有系统资源。每次使用 FileInputStream 时,应当确保在使用完之后关闭流,以防资源泄漏。

fis.close();

4. 使用 read(byte[] b) 方法读取文件

除了单字节读取外,FileInputStream 还支持一次性读取多个字节,这种方式更高效,尤其是当文件较大时。通过将数据读取到字节数组中,可以减少对文件的多次访问。

示例 2:使用 read(byte[] b) 方法读取文件
import java.io.FileInputStream;
import java.io.IOException;

public class FileInputStreamBufferExample {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("example.txt");

            // 创建一个缓冲区,用于存储读取的数据
            byte[] buffer = new byte[1024];
            int bytesRead;

            // 每次最多读取 buffer.length 字节
            while ((bytesRead = fis.read(buffer)) != -1) {
                // 将字节数组转化为字符串,并输出
                String output = new String(buffer, 0, bytesRead);
                System.out.print(output);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}

在这个示例中,文件被读取到一个字节缓冲区中,每次最多读取 1024 字节。使用 byte[] 数组可以有效减少对磁盘的多次访问,提升性能,尤其是读取大文件时非常有用。

5. 文件不存在时的处理

当试图打开一个不存在的文件时,FileInputStream 会抛出 FileNotFoundException 异常。因此,应该在代码中捕获这个异常并处理。

示例 3:处理文件不存在的情况
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileNotFoundExample {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            // 尝试打开一个不存在的文件
            fis = new FileInputStream("non_existent_file.txt");
        } catch (FileNotFoundException e) {
            System.out.println("文件未找到:" + e.getMessage());
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}

在这种情况下,程序将输出类似如下的消息:

文件未找到:non_existent_file.txt (系统找不到指定的文件。)

6. 适用场景

FileInputStream 适用于读取任何类型的文件,尤其是需要读取 二进制文件(如图片、音频、视频等)时。以下是 FileInputStream 的一些典型应用场景:

读取文本文件:虽然 FileInputStream 可以处理文本文件,但通常建议使用 FileReader 或 BufferedReader 来处理字符数据。
读取二进制文件:处理图片、音频、视频等二进制文件是 FileInputStream 的主要用途。
流式读取大文件:通过 FileInputStream 逐步读取大文件的内容,避免一次性将整个文件加载到内存中,节省内存资源。

7. FileInputStream 的局限性

尽管 FileInputStream 在处理文件读取时非常有用,但它也有一些局限性:

7.1 低级 API

FileInputStream 是面向字节的低级 API,每次只能读取字节数据。对于处理字符数据(如文本文件),建议使用更高级的 API,如 BufferedReader 或 FileReader。

7.2 没有缓冲机制

FileInputStream 本身没有缓冲机制,意味着每次读取时都会直接访问底层文件系统。这在读取大文件或频繁的文件读取操作中性能不佳。为了提高读取效率,通常结合 BufferedInputStream 使用。

7.3 文件关闭

使用 FileInputStream 时必须手动关闭流,以释放资源。如果忘记关闭流,可能导致资源泄漏问题。在 Java 7 及以后的版本中,推荐使用 try-with-resources 语句来自动关闭流。

示例 4:使用 try-with-resources 自动关闭流
import java.io.FileInputStream;
import java.io.IOException;

public class TryWithResourcesExample {
    public static void main(String[] args) {
        // try-with-resources 语法,自动关闭文件输入流
        try (FileInputStream fis = new FileInputStream("example.txt")) {
            int content;
            while ((content = fis.read()) != -1) {
                System.out.print((char) content);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用 try-with-resources 可以确保流在使用完毕后自动关闭,即使发生异常,也无需显式调用 close() 方法。

8. 总结

FileInputStream 是 Java 中处理文件输入的基础工具,它通过字节流的方式读取文件内容,非常适合用于读取二进制文件。在使用 FileInputStream 时,开发者可以灵活选择是逐字节读取还是通过缓冲区批量读取数据。同时,在处理完文件输入后,务必要记得关闭流,以避免资源泄漏。

尽管 FileInputStream 是一个底层 I/O 工具,它在处理文件读取时仍然非常强大,但对于文本文件的处理来说,使用 BufferedReader 或其他高级 API 可能更加高效。

在日常开发中,FileInputStream 是文件读取的基础工具之一,理解它的工作方式和使用场景可以帮助开发者更好地处理 Java 中的文件操作。

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值