Java中输入输出的五种方式

本文介绍Java中输入输出的五种方式:
读取方式:

  1. BufferedInputStream
  2. ByteArrayInputStream 
  3. BufferedReader

写入方式:

  1. BufferedWriter
  2. BufferedOutputStream

什么是BufferedInputStream?
BufferedInputStream是Java中InputStream类的子类。它添加了通过使用缓冲区将数据存储在内存中更有效地从底层输入流读取数据的功能。这有助于减少 I/O 操作的数量,与直接从底层流读取相比,速度更快。


BufferedInputStream 的工作原理
当您创建 BufferedInputStream 时,它会包装现有的 InputStream,例如 FileInputStream 或 ByteArrayInputStream。读取数据时,BufferedInputStream 将数据块加载到内部缓冲区中,从而减少从底层流实际读取的次数。这可以提高性能,尤其是在处理涉及少量读取的 I/O 操作时。

BufferedInputStream 的优点:

  • 1. 提高性能:从内部缓冲区读取更大块的数据,最大限度地减少 I/O 操作的数量。
  • 2.方便的方法:BufferedInputStream提供了额外的方法,使得数据流的处理更加容易。
  • 3. 减少系统调用:缓冲区有助于最大限度地减少系统调用的开销,从而提高整体效率。

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class BufferedInputStreamExample {

    public static void main(String[] args) {
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("example.txt"))) {
            int data;
            while ((data = bis.read()) != -1) {
               
// Process the data
                System.out.print((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在本例中,我们创建了一个包裹在 FileInputStream 周围的 BufferedInputStream。数据从文件中分块读取,从而提高了性能。

将字节读入缓冲区

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class BufferedInputStreamExample2 {

    public static void main(String[] args) {
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("example.txt"))) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = bis.read(buffer)) != -1) {
               
// Process the buffer
                System.out.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用DataInputStream:

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class BufferedDataInputStreamExample {

    public static void main(String[] args) {
        try (DataInputStream dis = new DataInputStream(
                new BufferedInputStream(new FileInputStream("data.bin")))) {
           
// Read data using DataInputStream methods
            int intValue = dis.readInt();
            double doubleValue = dis.readDouble();
            String stringValue = dis.readUTF();

           
// Process the data
            System.out.println(
"Int Value: " + intValue);
            System.out.println(
"Double Value: " + doubleValue);
            System.out.println(
"String Value: " + stringValue);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

本例展示了如何将 BufferedInputStream 与 DataInputStream 结合起来,以高效读取原始数据类型。

Java中的ByteArrayInputStream是什么?
Java 的 ByteArrayInputStream 是一个提供字节数组支持的输入流实现的类。换句话说,它允许您从字节数组创建输入流,将字节数组视为数据源。当处理需要输入流对象的方法或库时,这特别有用。

让我们看一个基本的代码示例:

import java.io.ByteArrayInputStream;
import java.io.IOException;

public class ByteArrayInputStreamExample {
    public static void main(String[] args) {
        // Creating a byte array
        byte[] data =
"Hello, ByteArrayInputStream!".getBytes();

       
// 创建字节数组输入流
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data);

       
// 从字节数组输入流读取数据
        int byteRead;
        try {
            while ((byteRead = byteArrayInputStream.read()) != -1) {
                System.out.print((char) byteRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

为什么使用 ByteArrayInputStream?
1.内存效率:
   ByteArrayInputStream 允许您处理内存中的字节数据,无需创建临时文件或处理复杂的 I/O 操作。
2.与 API 集成:
   许多 Java API 和库都需要输入流对象。通过使用 ByteArrayInputStream,您可以将字节数组数据无缝集成到此类 API 中。
3.性能
   ByteArrayInputStream 提供了一种轻量级、高效的字节数据处理方式,因此适用于对性能要求极高的应用场景。

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

public class Example {
    public static void main(String[] args) {
        // 指定要读取的文件路径
        String filePath =
"path/to/your/file.txt";

        try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在本例中,BufferedReader 用于从文件 (file.txt) 中读取文本行。readLine() 方法读取一行文本,该过程一直持续到文件结束(当 readLine() 返回 null 时)。try-with-resources 语句用于在使用后自动关闭 BufferedReader。

BufferedReader是什么 
在 Java 中,BufferedReader 是 java.io 包中的一个类。它用于通过缓冲字符来有效地从基于字符的输入流读取文本。使用 BufferedReader 的主要目的是通过减少 I/O 操作的数量来提高从输入流读取数据的性能。
以下是 BufferedReader 工作原理的简单解释:

  • 1. 缓冲:BufferedReader 不是一次从底层输入流读取一个字符,而是将一大块字符(缓冲区)读入内存。这有助于减少底层流的读取次数并提高整体性能。
  • 2. 读取方法:BufferedReader 提供了各种从输入流读取字符、行或其他数据类型的方法。一些常见的方法包括 read()、readLine() 和 read(char[] cbuf, int off, int len)。
  • 3. 关闭:需要注意的是,当您使用完 BufferedReader 后,应该使用 close() 方法关闭它以释放系统资源。

为什么需要BufferedReader?
Java 中的 BufferedReader 用于从 Reader(如 FileReader 或 InputStreamReader)中高效读取字符。它提供缓冲,这意味着它将数据从文件、输入流或其他源读取到内部缓冲区,然后从该缓冲区读取,而不是直接从源读取。这可以提高读取大量数据时的性能。
以下是 Java 中常用 BufferedReader 的一些原因:

  • 1. 提高性能:从文件或输入流读取数据涉及 I/O 操作,速度可能相对较慢。通过使用缓冲区,您可以最大限度地减少实际 I/O 操作的数量,从而使整个过程更加高效。
  • 2. 逐行读取:BufferedReader 提供了一个方便的方法 readLine(),它允许您一次读取一行文本。这在处理数据按行组织的文本文件时非常有用。

    BufferedReader reader = new BufferedReader(new FileReader("example.txt"));
    String line = reader.readLine();
    while (line != null) {
        // Process the line
        System.out.println(line);
        line = reader.readLine();
    }
    reader.close();

  • 3.高效读取字符:借助缓冲功能,可以高效读取字符。这在处理大文件或数据流时尤为有益。

  BufferedReader reader = new BufferedReader(new FileReader("largeFile.txt"));
    int character;
    while ((character = reader.read()) != -1) {
       
// Process the character
        System.out.print((char) character);
    }
    reader.close();

  • 4.标记和重置BufferedReader 支持 mark(int readAheadLimit) 和 reset() 方法,允许在输入流中标记一个位置,然后重置回该位置。这在某些情况下非常有用。

BufferedReader reader = new BufferedReader(new FileReader("example.txt"));
    reader.mark(100);
// Marking the current position
   
// 读取和处理一些数据
    reader.reset();
// Resetting back to the marked position
   
// 从标记位置继续阅读


BufferedReader 内部如何工作?
在 Java 中,BufferedReader 是 java.io 包的一部分,用于通过高效缓冲从基于字符的输入流中读取文本。它提供了从文件或输入流等源读取行、字符和其他数据的方法。以下是 BufferedReader 内部工作原理的简要概述:
1.构造函数:
   当您创建 BufferedReader 时,通常会将另一个 Reader(例如 FileReader、StringReader)的实例传递给其构造函数。该底层 Reader 用于从源读取数据。
    Reader reader = new FileReader("example.txt");
    BufferedReader bufferedReader = new BufferedReader(reader);
    
2. 缓冲:
   BufferedReader 使用内部缓冲区来存储从底层 Reader 读取的数据块。这有助于减少从源中实际读取的数量,从而使读取过程更加高效。
   int defaultCharBufferSize  = 8192;
   char[] cb = new char[defaultCharBufferSize];
   
   默认缓冲区大小为 8192 个字符,但您可以根据需要指定不同的大小。
3、读:
   当您在 BufferedReader 上调用 read() 或 readLine() 时,它会检查缓冲区中是否有可用数据。如果缓冲区为空或不包含所需数量的字符,它将从底层 Reader 读取一块数据到缓冲区中。
   整数 n;
   while ((n = in.read(cb, 0, cb.length)) != -1) {
       // 处理缓冲区中的字符
   }
   
   read() 方法返回读入缓冲区的字符数,如果没有更多数据,则返回 -1。
4. 行读取:
   BufferedReader 提供了一个方便的 readLine() 方法来读取一行文本。它从缓冲区读取字符,直到遇到换行符('\n')或到达流的末尾。
     String line = bufferedReader.readLine();
5. 结束:
   当您在 BufferedReader 上调用 close() 方法时,它还会关闭底层 Reader。这可以确保系统资源得到正确释放。
   bufferedReader.close();

总之,BufferedReader 的工作原理是高效地读取和缓冲来自底层 Reader 的数据,该底层 Reader 可以是文件、输入流或任何其他基于字符的数据源。这种缓冲有助于最大限度地减少从源实际读取的次数,从而提高整体性能。

何时在 Java 中使用 BufferedReader
Java 中的 BufferedReader 用于通过缓冲字符来有效地从基于字符的输入流中读取文本。与直接从底层流读取相比,它提供了一种更有效的方式从文件或输入流读取字符、行或其他数据。以下是您可能想要使用 BufferedReader 的一些场景:
1. 高效读取文本文件:
   在 Java 中从文件读取文本时,使用 BufferedReader 比直接从 FileReader 读取更有效。缓冲机制有助于减少 I/O 操作的数量,从而使处理速度更快。
    

try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
        String line;
        while ((line = reader.readLine()) != null) {
           
// Process each line
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

2.从InputStreamReader读取输入:
   当从 InputStreamReader(通常用于从标准输入或网络流读取)读取文本时,使用 BufferedReader 可以提高性能。

     try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
        String userInput = reader.readLine();
        // Process the user input
    } catch (IOException e) {
        e.printStackTrace();
    }

    
3. 解析和标记化:
   当您需要解析或标记输入时,BufferedReader 在读取行然后根据需要进行处理时非常有用。
 
try (BufferedReader reader = new BufferedReader(new FileReader("data.csv"))) {
        String line;
        while ((line = reader.readLine()) != null) {
            String[] tokens = line.split(
",");
           
// Process tokens
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    
4.从网络流中读取数据:
   使用网络流时,使用 BufferedReader 有助于高效读取数据。

   try (Socket socket = new Socket("example.com", 8080);
         BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {

        String response;
        while ((response = reader.readLine()) != null) {
           
// Process the response from the server
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    
一般来说,当您需要以缓冲方式从基于字符的输入源读取数据时,BufferedReader 是一个不错的选择,与无缓冲的替代方案相比,它提供了更好的性能。

读入三种方式比较:
总之:

  • BufferedInputStream当处理二进制数据并且您想要提高从底层输入流读取的效率时使用。
  • ByteArrayInputStream当字节数组中有数据并且希望将其视为输入流时使用。
  • 在处理基于字符的数据时使用BufferedReader,特别是从文件或另一个基于字符的输入流读取文本行时。

BufferedWriter是什么?
BufferedWriter是Java中的一个类,属于java.io包。它旨在通过缓冲输出来有效地将字符写入文件。这种缓冲机制通过减少底层文件或流的写入操作数量来增强性能。

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

public class BufferedWriterExample {
    public static void main(String[] args) {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter("example.txt"))) {
            // Write content to the file using BufferedWriter
            writer.write("Hello, BufferedWriter!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

为什么在 Java 中使用 BufferedWriter?
BufferedWriter 具有多种优势,使其成为各种场景的首选:

  • 1. 提高性能: BufferedWriter 减少了对底层文件的写入操作数量,因为它在将数据刷新到文件之前将数据存储在内部缓冲区中。这会减少磁盘 I/O 操作,从而提高性能。
  • 2.高效处理大数据集:当处理大量数据时,BufferedWriter通过在缓冲区中累积数据并以更大的块刷新它来帮助防止频繁的磁盘写入。
  • 3.您希望有效地处理基于字符的输出。

BufferedWriter 内部工作原理:
在内部,BufferedWriter维护一个内部字符缓冲区,当缓冲区已满或显式刷新时,它将数据写入底层Writer。这种机制显着减少了写操作的次数。

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

public class BufferedWriterExample3 {
    public static void main(String[] args) {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter("example.txt"))) {
           
// 向缓冲区写入数据而不自动冲洗
            writer.write(
"Data 1");
            writer.flush();  
// 手动明确刷新缓冲区
            writer.write(
"Data 2");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

高效写入:

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

public class BufferedWriterExample4 {
    public static void main(String[] args) {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter("example.txt"))) {
           
// 使用 BufferedWriter 高效写入数据
            for (int i = 1; i <= 1000; i++) {
                writer.write(
"Data " + i);
                writer.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

了解 BufferedOutputStream
`BufferedOutputStream` 是一个扩展 `FilterOutputStream` 的类,并为输出流提供缓冲。它可以有效地将字节写入底层输出流,从而减少直接在目标上执行的写入操作的数量。

为什么使用BufferedOutputStream?
使用 BufferedOutputStream 的主要优点在于它能够减少系统调用和磁盘 I/O 操作的数量。“BufferedOutputStream”不是单独写入每个字节,而是在内部缓冲区中收集一组字节,然后将它们刷新到目的地。这减少了与多个小写入相关的开销。

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferedOutputStreamExample {

    public static void main(String[] args) {
        try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("output.txt"))) {
           
// Perform write operations using bos
            bos.write(
"Hello, BufferedOutputStream!".getBytes());
            bos.flush();
// Ensure any remaining data in the buffer is written
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在此示例中,我们创建一个包裹在“FileOutputStream”周围的“BufferedOutputStream”。`try-with-resources` 语句确保流在使用后自动关闭。

设置自定义缓冲区大小
您还可以使用构造函数为 BufferedOutputStream 指定自定义缓冲区大小。这在处理特定 I/O 要求时非常有用。
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("output.txt"), 8192); // 8192 字节缓冲区大小

性能比较
我们来比较一下使用和不使用 BufferedOutputStream 时写入数据的性能。

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;

public class PerformanceComparison {

    public static void main(String[] args) {
        // Without BufferedOutputStream
        long startWithoutBuffer = System.currentTimeMillis();
        try (FileOutputStream fos = new FileOutputStream(
"output_without_buffer.txt")) {
            for (byte b :
"Hello, BufferedOutputStream!".getBytes()) {
                fos.write(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        long endWithoutBuffer = System.currentTimeMillis();
        System.out.println(
"Time without BufferedOutputStream: " + (endWithoutBuffer - startWithoutBuffer) + "ms");

       
// With BufferedOutputStream
        long startWithBuffer = System.currentTimeMillis();
        try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(
"output_with_buffer.txt"))) {
            bos.write(
"Hello, BufferedOutputStream!".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
        long endWithBuffer = System.currentTimeMillis();
        System.out.println(
"Time with BufferedOutputStream: " + (endWithBuffer - startWithBuffer) + "ms");
    }
}

这个简单的性能测试演示了使用 `BufferedOutputStream` 写入数据可能节省的时间。

两种写入方式比较
总之:

  • - 在处理字符型数据时,如果希望提高写入底层字符型输出流的效率,请使用 `BufferedWriter`。
  • - 处理二进制数据时,如果想提高写入底层二进制输出流的效率,请使用 `BufferedOutputStream`。