017 二进制 I/O

本贴最后更新于 2040 天前,其中的信息可能已经水流花落

本文为《Java 语言程序设计》第十版 章节笔记

17.1 引言

文件可分为 文本 或者 二进制 的。

17.2 在 Java 中如何处理文本 I/O

使用 Scanner 类读取文本数据,使用 PrintWrite 类写文本数据。

写入数据:

PrintWrite output = new PrintWrite("temp.txt");

output.print("Java 101");

outpout.close();

读取数据:

Scanner input = new Scanner(new File("temp.txt");
System.out.println(input.nextLine());

17.3 文本 I/0 与 二进制 I/O

二进制 I/O 不涉及编码和解码,因此比文本 I/O 更高效。

17.4 二进制 I/O 类

抽象类 InputStream 是读取二进制数据的根类,抽象类 OutputStream 是写入二进制数据的根类。

java.io.InputStream 抽象类的方法:
+read(): int
+read(b: byte[]): int
+read(b: btye[], off: int, len: int): int
+available(): int
+close(): void
+skip(n: long): long
+markSupported(): boolean
+mark(readlimit: int): void
+reset(): void
java.io.OutputStream 抽象类的方法:
+write(int b): void
+write(b: byte[]): void
+write(b: byte[], off: int, len: int): void
+close(): void
+flush(): void

FileInputStream 和 FileOutputStream

FileInputStream 类和 FileOutputStream 类用于从/向 文件 读取/写入字节:

java.io.FileInputStream 类(继承 java.io.InputStream)的构造方法:
+FileInputStream(file: File)
+FileInputStream(filename: String)
java.io.FlieOutputStream 类(继承 java.io.OutputStream)的构造方法:
+FileOutputStream(file: file)
+FileOutputStream(filename: String)
+FileOutputStream(file: file, append: boolean)
+FileOutputStream(filename: String, append: boolean)

可以创建一个 PrinterWtiter 对象来向文件中追加文本。如果 temp.txt 不存在,就会创建这个文件。如果 temp.txt 已经存在,就将新数据追加到该文件中。

new PrintWriter(new FileOutputStream("temp.txt", true));

FilterInputStream 和 FilterOutputStream

FilterInputStream 和 FilterOutputStream:过滤数据的基类。需要处理基本数值类型时,就使用 DataInputStream 和 DataOutputStream 类来过滤字节。

DataInputStream 和 DataOutputStream

<<interface>> java.io.DataInput
+readBoolean(): boolean
+readByte(): byte
+readChar(): char
+readFloat()float
+readDouble(): double
+redInt()int
+readLong(): long
+readShort(): short
+readLine(): String
+readUTF(): String
<<interface>> java.io.DataOutput:
+writeBoolean(b: boolean): void
+writeByte(v: int): void
+writeBytes(s: String): void
+writeChar(c: char): void
+writeChars(s: String): void
+writeFloat(v: float): void
+writeDouble(v: double): void
+writeInt(v: int): void
+writeLong(v: long): void
+writeShort(v: short): void
+writeUTF(s: String): void

创建 DataInputStream 类和 DataOutputStream 类:

public DataInputStream(InputStream instream)
public DataOutputStream(OutputStream outstream)

创建数据流:

DataInputStream input = new DataInputStream(new FileInputStrem("in.dat");
DataOutputStream output = new DataOutputStream(new FileOutputStream("out.dat");

BufferedInputStream 类和 BufferedOutputStream 类

BufferedInputStream 类和 BufferedOutputStream 类可以通过减少磁盘读写次数来提高输入输出的速度。

java.io.BufferedInputStream:
+BufferedInputStream(in: InputStream)(默认缓冲大小为 512字节)
+BaufferedInputStream(in: InputStream, bufferSize: int)
java.io.BufferedOutputStream:
+BufferedOutputStream(out: OutputStream)
+BufferedOutputStream(out: OutputStream, bufferSizeint)

使用:

DataOutputStream output = new DataOutputStream(new BufferedOutputStream(new FileOutputStrem("temp.dat")));
DataInputStream input = new DataInputStream(new BufferedInputStream(new FileInputStream9"temp.dat")));

对于超过 100MB 的大文件,我们将会看到使用缓冲的 I/O 带来的实质性的性能提升。

// 命令行执行f复制程序:java Copy source target(给定源文件 source和目标文件 target)
import java.io.*;

public class Copy {
  /** Main method
     @param args[0] for sourcefile
     @param args[1] for target file
   */
  public static void main(String[] args) throws IOException {
    // Check command-line parameter usage
    if (args.length != 2) {
      System.out.println(
        "Usage: java Copy sourceFile targetfile");
      System.exit(1);
    }

    // Check if source file exists
    File sourceFile = new File(args[0]);
    if (!sourceFile.exists()) {
       System.out.println("Source file " + args[0]
         + " does not exist");
       System.exit(2);
    }

    // Check if target file exists
    File targetFile = new File(args[1]);
    if (targetFile.exists()) {
      System.out.println("Target file " + args[1]
        + " already exists");
      System.exit(3);
    }

    try (
      // Create an input stream
      BufferedInputStream input =
        new BufferedInputStream(new FileInputStream(sourceFile));
  
      // Create an output stream
      BufferedOutputStream output =
        new BufferedOutputStream(new FileOutputStream(targetFile));
    ) {
      // Continuously read a byte from input and write it to output
      int r, numberOfBytesCopied = 0;
      while ((r = input.read()) != -1) {
        output.write((byte)r);
        numberOfBytesCopied++;
      }

      // Display the file size
      System.out.println(numberOfBytesCopied + " bytes copied");
    }
  }
}

对象 I/O

DataInputStream 类 和 DataOutputStream 类 可以实现基本数据类型与字符串的输入和输出。而 ObjectInputStream 类和 ObjectOutputSream 类 除了可以实现基本数据类型与字符串的输入和输出之外,还可以用于 读/写 可序列化的对象。

java.io.ObjectInputStream:
+ObjectInputStream(in: InputStream)

java.io.ObjectOutputStream:
+ObjectOutputStream(out: OutputStream)
<<interface>> ObjectInput:
+readObject(): Object // 读取一个对象

<<interface>> ObjectOutput:
+writeObject(o: Object): void // 写入一个对象

Serializable 接口

并不是每个对象都可以写到输出流。可以写入输出流中的对象称为可序列化的(serializable)。

序列化数组

如果数组中的所有元素都是可序列化的,这个数据就是可序列化的。

一个完整的数组可以用 writeObject 方法存入文件随后用 readObject 方法恢复。

随机访问文件

到现在为止,所使用的所有流都是只读的(read.only)或只写的(write.only)。这些流称为顺序(sequential)流。使用顺序流打开的文件称为 顺序访问文件。顺序访问文件的内容不能更新。

然而,经常需要修改文件。Java 提供了 RandomAccessFile 类,允许在文件的任意位置上进行读写。使用 RandomAccessFile 类打开的文件称为 随机访问文件。

RandomAccessFile 类 实现了 DataInput 和 DataOutput 接口。

Java 提供了 RandomAccessFile 类,允许从文件的任何位置进行数据的读写。

java.io.RandomAccessFile:
+RandomAccessFile(file: File, mode: String)
+RandomAccessFile(name: String, mode: String)
+close(): void
+getFilePointer(): long
+length(): long
+read() int
+read(b: byte[], off: int, len: int): int
+seek(pos: long): void
+setLength(newLength: long): void
+skipBytes(int n): int
+write(b: byte[]): void
+write(b: byte[], off: int, len: int): void

当创建一个 RandomAccessFile 时,可以指定两种模式("r"(只读) 或 "rw"(读写))之一。

RandomAccessFile raf = new RandomAccessFile("test.dat","rw");

如果文件 test.dat 已经存在,则创建 raf 以便访问这个文件;如果文件不存在,则创建一个名为 test.dat 的新文件,再创建 raf 来访问这个新文件。

设 raf 是 RandomAccessFile 的一个对象,可以调用 raf.seek(position) 方法将文件指针移到指定的位置。 raf.seek(0) 方法将文件指针移到文件的起始位置,而 raf.seek(raf.length) 方法则将文件指针移到文件的末尾。

END

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3167 引用 • 8207 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...