Flyinsky's Codes
1366 字
7 分钟
JavaIO文件流
2024-10-14

JavaIO文件流#

​ 在Java编程中,输入输出(I/O)是一个必不可少的部分,因为大多数应用程序都需要与外部世界进行某种形式的数据交换。其中,Java的I/O系统主要由字符流和字节流组成,这两种流各有其适用场景。此外,Java还提供了缓冲流(Buffered Stream)来提高I/O操作的效率。本文将详细介绍Java中的字符流、字节流以及缓冲流的概念和使用。

字节流(Byte Stream)#

字节流主要用于处理原始的二进制数据。字节流适合任何类型的数据传输,包括图像、音频、视频等无格式的数据。Java中,字节流的基本类是InputStreamOutputStream

  • InputStream:这是所有字节输入流类的超类。常用的子类包括FileInputStreamByteArrayInputStreamFilterInputStream等。

  • OutputStream:这是所有字节输出流类的超类。常用的子类包括FileOutputStreamByteArrayOutputStreamFilterOutputStream等。

示例代码:#

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class ByteStreamExample {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("input.txt");
             FileOutputStream fos = new FileOutputStream("output.txt")) {

            int byteData;
            while ((byteData = fis.read()) != -1) {
                fos.write(byteData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

这种用法非常适合处理非文本数据,但在处理文本数据时会比较麻烦,因为没有字符编码的概念,这时候字符流就派上用场了。

字符流(Character Stream)#

字符流主要用于处理字符数据,适合处理文本。字符流依赖于字符编码来正确地进行数据转换。Java通过ReaderWriter类提供字符流支持。

  • Reader:这是所有字符输入流类的超类。常用的子类包括FileReaderBufferedReaderInputStreamReader等。

  • Writer:这是所有字符输出流类的超类。常用的子类包括FileWriterBufferedWriterOutputStreamWriter等。

示例代码:#

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CharacterStreamExample {
    public static void main(String[] args) {
        try (FileReader fr = new FileReader("input.txt");
             FileWriter fw = new FileWriter("output.txt")) {

            int charData;
            while ((charData = fr.read()) != -1) {
                fw.write(charData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用字符流可以很方便地处理文本数据,因为它自动处理了字符到字节的转化。

缓冲流(Buffered Stream)#

缓冲流通过减少与底层系统进行交互的次数来提高I/O操作的效率。这是通过在程序与实际I/O设备之间引入一个内部缓冲区来实现的。

  • BufferedInputStreamBufferedOutputStream:用于字节流的缓冲。通过减少每次读写操作的系统调用次数来提升效率。

  • BufferedReaderBufferedWriter:用于字符流的缓冲。它们不仅提高速度,还增加了一些有用的功能,例如,以行为单位读取文件的能力。

示例代码:#

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedStreamExample {
    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new FileReader("input.txt"));
             BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {

            String line;
            while ((line = br.readLine()) != null) {
                bw.write(line);
                bw.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在以上代码中,BufferedReaderBufferedWriter提高了读取和写入的效率,并提供了按行读取文本的额外功能,这在处理大型文本文件时尤其有用。

实践#

1. 字节流实际场景:处理图片文件#

场景描述: 假设你正在开发一个图像处理工具,需要从磁盘读取一张图片,然后进行一些图像分析或处理(例如,滤镜效果、缩放)。

解决方案: 由于图片文件是二进制文件,使用字节流来读取和写入图片数据是最有效的方式。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class ImageProcessing {
    public static void main(String[] args) {
        try (FileInputStream inputStream = new FileInputStream("source.jpg");
             FileOutputStream outputStream = new FileOutputStream("processed.jpg")) {

            int byteData;
            while ((byteData = inputStream.read()) != -1) {
                // 对图像字节数据进行处理,例如应用滤镜之类的
                outputStream.write(byteData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2. 字符流实际场景:处理文本配置文件#

场景描述: 假设你正在开发应用的配置管理模块,需要读取和写入应用配置文件。这些文件通常是文本格式,比如JSON或XML。

解决方案: 由于这些配置文件是文本文件,使用字符流来读取和写入文本数据更为合适。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class ConfigManager {
    public static void main(String[] args) {
        try (BufferedReader reader = new BufferedReader(new FileReader("config.json"));
             FileWriter writer = new FileWriter("updated_config.json")) {

            String line;
            while ((line = reader.readLine()) != null) {
                // 进行配置的更新或修改
                writer.write(line);
                writer.write(System.lineSeparator());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3. 缓冲流实际场景:日志系统的日志写入#

场景描述: 假设你正在设计一个日志记录系统。日志系统需要能够高效地写入大量日志信息到文本文件中,特别是在高并发场景下。

解决方案: 使用缓冲流进行写入,减少磁盘写操作的次数,从而提高写入效率。

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDateTime;

public class Logger {
    private BufferedWriter logWriter;

    public Logger(String logFilePath) throws IOException {
        logWriter = new BufferedWriter(new FileWriter(logFilePath, true));
    }

    public void log(String message) {
        try {
            String timestampedMessage = LocalDateTime.now() + " - " + message;
            logWriter.write(timestampedMessage);
            logWriter.newLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void close() throws IOException {
        logWriter.close();
    }

    public static void main(String[] args) {
        try {
            Logger logger = new Logger("application.log");
            logger.log("程序启动");
            //其他日志打印...
            logger.log("程序终止");
            logger.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这些示例中,每种流都被用来解决特定类型的I/O问题,展示了如何选择最合适的流来达到最佳的效率和效果。