Java API:5. IO Stream

目录

1. 相对论理解 I/O 流

**输入/输出流(I/O Stream)**是计算机程序中的核心概念之一,它涉及到数据的读取(输入)和写入(输出)。为了更好地理解I/O流的工作原理,我们可以借助物理学中的相对论和流体流动来做比喻。

I/O 流的基本概念

在字面上,Stream指的是具有方向性的流动,如水流、电流等,它强调的是过程。在计算机中,I/O流通常指的是数据在计算机中从输入源(如键盘、文件等)流向输出目标(如屏幕、文件等)的一种过程。

相对论视角下的 I/O 流

相对论的角度来看,I/O流的输入与输出具有相对性。不同的参照系会导致不同的流动方向和定义:

  1. 冬季旱季的流动

    • 假设我们站在支流的角度,支流中的水从支流流出,进入大江(如长江)。这里,支流是“输出”的源头,长江是“输入”的目标。
  2. 夏季雨季的流动

    • 当进入雨季时,支流可能变成了接收的源头,反过来,长江的水流将从大江流向支流,这时候长江变成了输出源,支流变成了输入目标

类比到 I/O 流:

  • 输入流(Input Stream):就像支流对长江来说,是一个“输入”源。计算机中的输入流指的是从外部设备(如文件、键盘、网络)读取数据的过程。
  • 输出流(Output Stream):类似于长江输出水流的过程,输出流是将数据从程序写入外部设备(如屏幕、文件、网络)的过程。
管道的角色

就像流体流动需要管道来引导水流一样,I/O流也需要管道来传递数据。管道可以是文件流、网络流、缓冲流等,它们为数据流动提供了“通道”。

参照系的选择
  • 谁是输入,谁是输出

    :在不同的程序设计环境和任务中,输入和输出的角色是相对的。就像你可以选择站在支流或长江的角度看待水的流动一样,数据的来源和去向也依赖于你的视角。

    • 输入流:表示从外部源读取数据(比如从文件中读取数据)。
    • 输出流:表示将数据写入到外部目标(比如将数据写入文件)。

总结:

I/O流是一个双向的过程,正如流体流动在不同环境下的表现那样,输入和输出是相对的,取决于程序的需求和任务。理解了这个类比,可以帮助我们更好地理解计算机中的I/O流动。


3. 图解 I/O 流

I/O 流的核心在于数据在程序与外部设备之间的流动,站在不同的视角,输入和输出的方向是不同的。为了更清楚地理解 I/O 流动,我们可以通过图示的方式来帮助理解。

1. 写数据(Program → Data)
  • 图示:

    Program  --->  Data
    (Write data)   (Input to data source)
    
  • 说明:

    • 程序向数据源写数据。从程序的角度,数据是从程序流向数据源(如文件、数据库、网络等)。这时程序执行的是写操作,数据源执行的是输入操作。
    • 这个过程称为“输出”(output),因为程序将数据输出到外部设备或文件系统。对于外部数据源来说,这就是输入(input)。
  • 示例:

    • 程序通过文件输出流将数据写入文件中。
    • 程序通过网络连接将信息发送到服务器。
2. 读数据(Data → Program)
  • 图示:

    Data  --->  Program
    (Read data)   (Input to program)
    
  • 说明:

    • 数据从数据源流入程序。此时数据源(如文件、数据库、网络等)提供数据给程序。程序执行读取操作,而数据源执行输出操作。
    • 这个过程被称为“输入”(input),因为程序正在从数据源读取数据。对于数据源而言,这时是输出(output),因为它将数据提供给程序。
  • 示例:

    • 程序通过文件输入流从文件中读取数据。
    • 程序通过网络连接从服务器获取数据。

程序角度的理解:

从程序的角度来看,所有的操作都是围绕“输入”和“输出”进行的:

  • 输出:当程序将数据传输到外部设备时,程序执行输出操作。
  • 输入:当程序从外部设备获取数据时,程序执行输入操作。

然而,站在数据源的角度,输入和输出的角色是互换的。

  • 数据源的输入:程序写入数据时,数据源是输入。
  • 数据源的输出:程序读取数据时,数据源是输出。

总结:

I/O 流的核心概念就是数据流动的方向,程序与数据源之间的操作方向是相对的,取决于我们站在程序还是数据源的角度来看。


4. 俩亲爹:InputStream 和 OutputStream

在 Java 的 I/O 流中,InputStreamOutputStream 是两个非常重要的类,它们是所有字节流的父类,分别负责数据的输入和输出。

1. InputStream:数据读取的管理者

InputStream 是所有输入流的父类,专门负责读取数据。通过继承 InputStream 的子类(如 FileInputStream, BufferedInputStream 等),我们可以从各种数据源(如文件、网络、内存)中读取数据。

  • 常用方法:

    • int read():从输入流中读取一个字节的数据,返回值是该字节的整数表示,读到文件末尾时返回 -1
    • int read(byte[] b):将输入流中的字节读入一个字节数组。
    • void close():关闭流,释放资源。
  • 示例:

    FileInputStream fis = new FileInputStream("example.txt");
    int data = fis.read();
    while (data != -1) {
         
         
        System.out.print((char) data);
        data = fis.read();
    }
    fis.close();
    
2. OutputStream:数据写入的管理者

OutputStream 是所有输出流的父类,专门负责将数据写入目标设备。通过继承 OutputStream 的子类(如 FileOutputStream, BufferedOutputStream 等),我们可以将数据写入文件、网络等目标。

  • 常用方法:

    • void write(int b):将一个字节的数据写入输出流。
    • void write(byte[] b):将字节数组的数据写入输出流。
    • void close():关闭流,释放资源。
  • 示例:

    FileOutputStream fos = new FileOutputStream("example.txt");
    fos.write(65);  // 写入一个字节数据,ASCII 65对应字母 'A'
    fos.close();
    
3. InputStream 与 OutputStream 的对比:
  • 职责:
    • InputStream 管理 读取 操作。
    • OutputStream 管理 写入 操作。
  • 数据方向:
    • InputStream 中,数据是从外部流向程序(输入)。
    • OutputStream 中,数据是从程序流向外部目标(输出)。
4. 继承结构:

InputStreamOutputStream 是许多具体输入流和输出流类的父类。通过它们,Java 提供了灵活的字节流处理方式。例如:

  • 字节输入流:
    • FileInputStream
    • ByteArrayInputStream
    • ObjectInputStream
  • 字节输出流:
    • FileOutputStream
    • ByteArrayOutputStream
    • ObjectOutputStream
总结:
  • InputStream 负责 读取 数据。
  • OutputStream 负责 写入 数据。
  • 它们是 Java I/O 流的核心父类,其他字节流都继承自这两个类。

5. 使用 FileInputStream 进行字节流文件读取

FileInputStream 是 Java 中用于读取文件字节流的类。它用于从文件中读取数据流,适合读取原始字节数据(如图片、音频等)。以下是你提供的代码,使用 FileInputStream 逐字节读取文件内容并打印到控制台。

代码解析:
import org.junit.Test;
import java.io.FileInputStream;
import java.io.IOException;

public class DemoTest {
   
   
    @Test
    public void inputFile() throws IOException {
   
   
        // 创建FileInputStream对象,指定要读取的文件路径
        FileInputStream fileInputStream = new FileInputStream("file/1.txt");
        
        int filereading = 0;
        
        // 使用read()方法读取文件,直到文件末尾(返回-1)
        while(filereading != -1) {
   
   
            // .read()方法按字节读取文件内容,返回值是字节对应的整数。如果读取到的是文本文件,它会按ASCII码值返回字节。
            filereading = fileInputStream.read();
            
            // 将读取的字节值转换为字符并打印(char对应ASCII值)
            System.out.println((char)filereading);
        }
        
        // 关闭输入流,释放资源
        fileInputStream.close();
    }
}
代码详细解释:
  1. FileInputStream fileInputStream = new FileInputStream("file/1.txt");
    • 通过 FileInputStream 构造函数打开指定的文件 "file/1.txt"。请确保文件路径正确,且文件存在。
  2. filereading = fileInputStream.read();
    • read() 方法读取文件的下一个字节并返回它的值(对应于字节的 ASCII 值)。如果文件读取完毕,read() 返回 -1,表示文件结束。
  3. System.out.println((char)filereading);
    • 将读取到的字节值转换为字符并打印。由于 ASCII 字符编码,(char) 转换后显示为对应的字符。
  4. fileInputStream.close();
    • 使用完输入流后,必须调用 close() 方法关闭文件流,以释放系统资源。
注意事项:
  • 字符编码: 上述代码按字节读取文件并直接转换为字符,适用于文本文件。如果是二进制文件(如图片、音频等),不应将其转换为字符,而应按字节处理。
  • 文件路径: 文件路径 "file/1.txt" 应根据项目的目录结构调整。如果文件位于项目根目录下的 file 文件夹内,代码路径是正确的。
  • 异常处理: 代码中的 throws IOException 说明了方法可能抛出 IOException,实际开发中可以使用 try-catch 捕获并处理异常。
优化建议:

为了提高性能,可以使用 BufferedInputStream 来包装 FileInputStream,以便一次性读取多个字节。


6. 使用 FileOutputStream 进行字节流文件写入

FileOutputStream 是 Java 中用于写入文件字节流的类。它适合用于将原始字节数据(如文本、音频、图片等)写入文件。以下是你提供的代码,演示了如何使用 FileOutputStream 将字节数据写入文件。

代码解析:
import org.junit.Test;
import java.io.FileOutputStream;
import java.io.IOException;

public class DemoTest {
   
   

    // 方式 1:使用 .write() 方法直接写入字节数组
    @Test
    public void outputFile() throws IOException 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值