Java经典I/O操作:RandomAccessFile与扁平文件数据库实现
立即解锁
发布时间: 2025-08-19 00:11:30 阅读量: 1 订阅数: 8 


Java编程基础与Android开发入门
### Java经典I/O操作:RandomAccessFile与扁平文件数据库实现
#### 1. File类的杂项方法
File类实现了`java.lang.Comparable`接口的`compareTo()`方法,并重写了`equals()`和`hashCode()`方法。以下是这些方法的详细描述:
| 方法 | 描述 |
| --- | --- |
| `int compareTo(File pathname)` | 按字典顺序比较两个路径名。该方法的排序规则依赖于底层平台。在Unix/Linux平台上,比较路径名时字母大小写敏感;在Windows平台上,字母大小写不敏感。当`pathname`的抽象路径名等于此`File`对象的抽象路径名时返回0;当此`File`对象的抽象路径名小于`pathname`时返回负值;否则返回正值。为了准确比较两个`File`对象,可对每个`File`对象调用`getCanonicalFile()`方法,然后比较返回的`File`对象。 |
| `boolean equals(Object obj)` | 将此`File`对象与`obj`进行相等性比较。抽象路径名的相等性依赖于底层平台。在Unix/Linux平台上,比较路径名时字母大小写敏感;在Windows平台上,字母大小写不敏感。当且仅当`obj`不为空且是一个`File`对象,并且其抽象路径名表示与此`File`对象的抽象路径名相同的文件/目录时,返回`true`。 |
| `int hashCode()` | 计算并返回此路径名的哈希码。此计算依赖于底层平台。在Unix/Linux平台上,路径名的哈希码等于其路径名字符串的哈希码与十进制值1234321的异或。在Windows平台上,哈希码是小写路径名字符串的哈希码与十进制值1234321的异或。在将路径名字符串转换为小写时,不考虑当前的区域设置。 |
#### 2. RandomAccessFile类的使用
Java通过`java.io.RandomAccessFile`类支持文件的随机访问,允许在文件关闭前进行读写混合操作。
##### 2.1 构造函数
`RandomAccessFile`类声明了以下构造函数:
- `RandomAccessFile(File file, String mode)`:如果文件不存在,则创建并打开一个新文件;如果文件已存在,则打开该文件。文件由`file`的抽象路径名标识,并根据`mode`进行创建和/或打开操作。
- `RandomAccessFile(String pathname, String mode)`:如果文件不存在,则创建并打开一个新文件;如果文件已存在,则打开该文件。文件由`pathname`标识,并根据`mode`进行创建和/或打开操作。
`mode`参数必须是`"r"`、`"rw"`、`"rws"`或`"rwd"`之一,否则构造函数将抛出`IllegalArgumentException`。这些字符串字面量的含义如下:
- `"r"`:告知构造函数仅打开现有文件进行读取操作。任何写入文件的尝试都会抛出`IOException`类的实例。
- `"rw"`:告知构造函数在文件不存在时创建并打开一个新文件进行读写操作,或打开现有文件进行读写操作。
- `"rwd"`:告知构造函数在文件不存在时创建并打开一个新文件进行读写操作,或打开现有文件进行读写操作。此外,对文件内容的每次更新都必须同步写入底层存储设备。
- `"rws"`:告知构造函数在文件不存在时创建并打开一个新文件进行读写操作,或打开现有文件进行读写操作。此外,对文件内容或元数据的每次更新都必须同步写入底层存储设备。
文件的元数据是关于文件的数据,而不是实际的文件内容,例如文件的长度和最后修改时间。`"rwd"`和`"rws"`模式确保对本地存储设备上的文件的任何写入操作都能写入设备,从而保证在操作系统崩溃时关键数据不会丢失。但如果文件不在本地设备上,则不提供此保证。需要注意的是,以`"rwd"`或`"rws"`模式打开的随机访问文件的操作比以`"rw"`模式打开的相同操作要慢。
当`mode`为`"r"`且由`pathname`标识的文件无法打开(可能不存在或可能是目录),或者`mode`为`"rw"`且`pathname`是只读的或为目录时,这些构造函数将抛出`FileNotFoundException`。
以下示例演示了使用第二个构造函数通过`"r"`模式字符串尝试打开现有文件进行读取访问:
```java
RandomAccessFile raf = new RandomAccessFile("employee.dat", "r");
```
##### 2.2 文件指针
随机访问文件与一个文件指针相关联,文件指针是一个游标,用于标识下一个要写入或读取的字节的位置。当打开现有文件时,文件指针设置为偏移量为0的第一个字节。创建文件时,文件指针也设置为0。
读写操作从文件指针开始,并将其向前移动写入或读取的字节数。写入超过当前文件末尾的操作会导致文件扩展。这些操作会一直持续到文件关闭。
##### 2.3 RandomAccessFile类的方法
`RandomAccessFile`类声明了多种方法,以下是一些代表性方法的描述:
| 方法 | 描述 |
| --- | --- |
| `void close()` | 关闭文件并释放任何相关的平台资源。后续的读写操作将导致`IOException`。此外,不能使用此`RandomAccessFile`对象重新打开该文件。当发生I/O错误时,此方法将抛出`IOException`。 |
| `FileDescriptor getFD()` | 返回文件的关联文件描述符对象。当发生I/O错误时,此方法将抛出`IOException`。 |
| `long getFilePointer()` | 返回文件指针当前相对于文件开头的基于零的字节偏移量。当发生I/O错误时,此方法将抛出`IOException`。 |
| `long length()` | 返回文件的长度(以字节为单位)。当发生I/O错误时,此方法将抛出`IOException`。 |
| `int read()` | 从文件中读取并返回下一个字节(作为0到255范围内的`int`),或者当到达文件末尾时返回 -1。当没有可用输入时,此方法会阻塞;当发生I/O错误时,将抛出`IOException`。 |
| `int read(byte[] b)` | 从文件中读取最多`b.length`字节的数据到字节数组`b`中。此方法会阻塞,直到至少有1个字节的输入可用。它返回读取到数组中的字节数,或者当到达文件末尾时返回 -1。当`b`为`null`时,抛出`NullPointerException`;当发生I/O错误时,抛出`IOException`。 |
| `char readChar()` | 从文件中读取并返回一个字符。此方法从当前文件指针开始读取2个字节。如果按顺序读取的字节为`b1`和`b2`,其中`0 <= b1, b2 <= 255`,则结果等于`(char) ((b1 << 8) | b2)`。此方法会阻塞,直到读取到2个字节、检测到文件末尾或抛出异常。当在读取两个字节之前到达文件末尾时,抛出`java.io.EOFException`(`IOException`的子类);当发生I/O错误时,抛出`IOException`。 |
| `int readInt()` | 从文件中读取并返回一个32位整数。此方法从当前文件指针开始读取4个字节。如果按顺序读取的字节为`b1`、`b2`、`b3`和`b4`,其中`0 <= b1, b2, b3, b4 <= 255`,则结果等于`(b1 << 24) | (b2 << 16) | (b3 << 8) | b4`。此方法会阻塞,直到读取到4个字节、检测到文件末尾或抛出异常。当在读取4个字节之前到达文件末尾时,抛出`EOFException`;当发生I/O错误时,抛出`IOException`。 |
| `void seek(long pos)` | 将文件指针的当前偏移量设置为`pos`(从文件开头以字节为单位测量)。如果偏移量设置超过文件末尾,文件的长度不会改变。只有在偏移量设置超过文件末尾后进行写入操作,文件长度才会改变。当`pos`的值为负数或发生I/O错误时,此方法将抛出`IOException`。 |
| `void setLength(long newLength)` | 设置文件的长度。如果`length()`返回的当前长度大于`newLength`,则文件将被截断。在这种情况下,如果`getFilePointer()`返回的文件偏移量大于`newLength`,则在`setLength()`返回后,偏移量将等于`newLength`。如果当前长度小于`newLength`,则文件将被扩展。在这种情况下,扩展部分的文件内容未定义。当发生I/O错误时,此方法将抛出`IOException`。 |
| `int skipBytes(int n)` | 尝试跳过`n`个字节。当在跳过`n`个字节之前到达文件末尾时,此方法会跳过较少的字节(可能为零)。在这种情况下,它不会抛出`EOFException`。如果`n`为负数,则不跳过任何字节。返回实际跳过的字节数。当发生I/O错误时,此方法将抛出`IOException`。 |
| `void write(byte[] b)` | 从字节数组`b`中写入`b.length`个字节到文件的当前文件指针位置。当发生I/O错误时,此方法将抛出`IOException`。 |
| `void write(int b)` | 将`b`的低8位写入文件的当前文件指针位置。当发生I/O错误时,此方法将抛出`IOException`。 |
| `void writeChars(String s)` | 将字符串`s`作为字符序列写入文件的当前文件指针位置。当发生I/O错误时,此方法将抛出`IOException`。 |
| `void writeInt(int i)` | 将32位整数`i`写入文件的当前文件指针位置。4个字节以高位字节优先的顺序写入。当发生I/O错误时,此方法将抛出`IOException`。 |
`RandomAccessFile`类的以`read`开头的方法和`skipBytes()`方法源自`java.io.DataInput`接口,该类实现了此接口。此外,以`write`开头的方法源自`java.io.DataOutput`接口,该类也实现了此接口。
##### 2.4 FileDescriptor类
当打开一个文件时,底层平台会创建一个与平台相关的结构来表示该文件。对该结构的句柄存储在`java.io.FileDescriptor`类的实例中,`getFD()`方法会返回该实例。
`FileDescriptor`类是一个小类,声明了三个`FileDescriptor`常量`in`、`out`和`err`。这些常量允许`System.in`、`System.out`和`System.err`访问标准输
0
0
复制全文
相关推荐










