在 java 中是不是有 RandomAccessFile 的 readObject() 替代方法

Posted

技术标签:

【中文标题】在 java 中是不是有 RandomAccessFile 的 readObject() 替代方法【英文标题】:In java is there a readObject() alternative for RandomAccessFile在 java 中是否有 RandomAccessFile 的 readObject() 替代方法 【发布时间】:2011-11-22 20:47:57 【问题描述】:

我正在尝试保存几个字符串,但我目前正在使用 ObjectInputStream,它显然不会以永久方式保存我的数据。这是我在项目中评论的代码。它以临时方式保存字符串。每当我退出程序时,数据都会消失:

ObjectInputStream FileIn= new ObjectInputStream(new FileInputStream("cars.txt"));

//AND HERE IS THE CODE FOR THE RandomAccessFile VERSION:
RandomAccessFile FileIn = new RandomAccessFile("cars.txt", "rw");

  au=(Cars)FileIn.readObject(); //THIS readObject(), is giving me errors
  //Cars is a Class

我可以使用其他替代方法来阅读RandomAccessFile...请帮助并感谢。

【问题讨论】:

您是否记得在关闭应用程序之前刷新并关闭 OutputStream?如果不是,那么这就是没有保存数据的原因——而不是因为您选择了写入数据的类。 代码无法编译。 ObjectInputStream 根本不存储对象,它 存储中检索它们。您所说的“永久方式”和“暂时方式”以及“给我带来错误”到底是什么意思?目前的问题是无法回答的。 对我的回答@Cesar 的任何评论。您是否尝试从序列化输出流文件中的随机点读取? 【参考方案1】:

就像 FileInputStream 一样,您需要将 RandomAccessFile 包装在 ObjectInputStream 中。即 RandomAccessFile 不会给你买任何东西。

final RandomAccessFile raf = new RandomAccessFile("file.dat", "r");
ObjectInputStream ois = new ObjectInputStream(new InputStream() 
    @Override
    public int read(byte[] b, int off, int len) throws IOException 
        return raf.read(b, off, len);
    

    @Override
    public int read() throws IOException 
        return raf.read();
    
);

【讨论】:

你能把它放在代码中吗?这对我有很大帮助..我会给你更多的声誉 你不能做一个new FileInputStream(randomAccessFile.getFD())吗? @TomHawtin-tackline,我认为这会从一开始就读取文件。如果他想要随机访问,他将需要采取不同的方式。 @Peter Lawrey 文件描述符包含偏移量(显然,套接字和管道略有不同)。刚刚检查过。无论使用哪种方法,使用ObjectInputStream 应该缓冲超出对象流数据,因此使用后的RandomAccessFile 将是“错误的”。【参考方案2】:

对于简单的 String 对象,使用普通的 DataInputStream / DataOutputStream 会容易得多:

package test;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;

public class TestFile 

    static final String FILE = "/tmp/cars.txt";

    public static void main(String[] args) 
    try 
        List<String> strs = new ArrayList<String>();
        strs.add("Audi");
        strs.add("Seat");
        strs.add("Renault");

        saveStrings(strs);

        strs = loadStrings();

        System.out.println("Read strings: " + strs);

     catch (Exception e) 

    
    

    static List<String> loadStrings() throws Exception 
    DataInputStream dis = null;
    List<String> list = new ArrayList<String>();
    try 
        dis = new DataInputStream(new FileInputStream(FILE));
        while (dis.available() > 0) 
        list.add(dis.readUTF());
        
     finally 
        if (dis != null)
        dis.close();
    

    return list;
    

    static void saveStrings(List<String> list) throws Exception 
    DataOutputStream dos = null;

    try 
        dos = new DataOutputStream(new FileOutputStream(FILE));
        for (String str : list) 
        dos.writeUTF(str);
        
     finally 
        if (dos != null)
        dos.close();
    
    


【讨论】:

可能要容易得多,但可能效率较低(如果您可能存储重复的字符串)。【参考方案3】:

如果您问是否可以使用RandomAccessFile 在对象流中四处寻找并读取对象,那么简短的回答是“否”。序列化的对象流使用指向先前使用的对象的反向指针进行大量编码,包括先前转储的类定义等。

Serialization stream specification 提供一些格式细节。 这里有一些more details on the serialization format。 关于random writing from Java docs的讨论。

我们有类似的需求,编写了一些代码,偶尔关闭和重新打开序列化流,并记录这些断点的位置。这并没有使我们能够读取特定对象,但它确实使我们能够追加到序列化流并跳过文件的特定部分——跳到下一个中​​断。

【讨论】:

【参考方案4】:

你必须调用writeObject() 而不是readObject(),后者实际上是从磁盘读取到内存,当然当程序结束时,该程序使用的内存也会结束。

【讨论】:

不知道,点赞。我觉得还可以!

以上是关于在 java 中是不是有 RandomAccessFile 的 readObject() 替代方法的主要内容,如果未能解决你的问题,请参考以下文章

AbstractList.java中RandomAccess的操作

分析轮子- RandomAccess.java

小白学Java:奇怪的RandomAccess

Java集合类:"随机访问" 的RandomAccess接口

Java RandomAccess

标记接口: RandomAccess