【问题标题】:Append to ObjectOutputStream iteratively迭代地附加到 ObjectOutputStream
【发布时间】:2014-09-12 05:07:15
【问题描述】:

我想将大量数据添加到文件中。我定义了 HYB 类,因为我的对象包含不同类型的数据(字符串和字节 [])。我使用 ObjectOutputStream 和 ObjectInputStream 来写入和读取文件。但是我的代码没有打印出预期的结果。为了编写我的代码,我在以下页面中使用了代码: How can I append to an existing java.io.ObjectStream?

ClassCastException when Appending Object OutputStream

我尝试调试我的代码并发现了问题,但我不能。这是我的代码:

import java.io.*;
import java.io.BufferedOutputStream;
import java.util.*;

public class HYB implements Serializable
 {
private static final long serialVersionUID = 1L;
private List<byte[]> data = new ArrayList<>();

public void addRow(String s,byte[] a)
{
    data.add(s.getBytes()); // add encoding if necessary
    data.add(a);
}

@Override public String toString()
{
    StringBuilder sb = new StringBuilder();
    synchronized (data)
    {
        for(int i=0;i<data.size();i+=2)
        {
            sb.append(new String(data.get(i)));
            sb.append(Arrays.toString(data.get(i+1))+"\n");
        }
    }
    return sb.toString();
}

private static void write(File storageFile, HYB hf)
        throws IOException {
               ObjectOutputStream oos = getOOS(storageFile);
               oos.writeObject(hf);
               oos.flush();
               oos.close();
}

public static ObjectOutputStream getOOS(File file) throws IOException
{

    if (file.exists()) {
        return new AppendableObjectOutputStream(new FileOutputStream(file, true));
    } else {
        return new ObjectOutputStream(new FileOutputStream(file));
    }
}



 private static ObjectInputStream getOIS(FileInputStream fis)
        throws IOException {
               long pos = fis.getChannel().position();
               return pos == 0 ? new ObjectInputStream(fis) : 
                         new AppendableObjectInputStream(fis);
}

private static class AppendableObjectOutputStream extends
ObjectOutputStream {

  public AppendableObjectOutputStream(OutputStream out)
    throws IOException {
        super(out);
                        }

  @Override
  protected void writeStreamHeader() throws IOException {

  }
 }

private static class AppendableObjectInputStream extends ObjectInputStream {

    public AppendableObjectInputStream(InputStream in) throws IOException {
        super(in);
    }

    @Override
    protected void readStreamHeader() throws IOException {
        // do not read a header
    }
}



public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException
{

    File x=new File ("test");


    HYB hf1 = new HYB();
    hf1.addRow("fatemeh",new byte[] {11,12,13});
    hf1.addRow("andisheh",new byte[] {14,15,16});

    write(x,hf1);


    HYB hf = new HYB();
    hf.addRow("peter",new byte[] {1,2,3});
    hf.addRow("jaqueline",new byte[] {4,5,6});
    write(x,hf);


    FileInputStream fis = new FileInputStream(x);
    HYB hf2 = (HYB) getOIS(fis).readObject();
    System.out.println(hf2);
  }
}

预期结果:

fatemeh[11, 12, 13]
andisheh[14, 15, 16]
peter[1, 2, 3]
jaqueline[4, 5, 6]

实际结果:

fatemeh[11, 12, 13]
andisheh[14, 15, 16]

【问题讨论】:

    标签: java objectinputstream objectoutputstream


    【解决方案1】:

    将两个HYB 对象写入ObjectOutputStream 不会将它们合并为一个HYB 对象; ObjectOutputStream 仍然包含两个 HYB 对象,您的代码会读取其中一个。如果您对readObject() 进行了第二次调用,则会检索到第二次调用并将其打印到屏幕上。因此,您可以将 readObject()println() 调用包装在一个读取/写入的循环中,直到流中没有其他内容可读取。

    【讨论】:

    • 您可以使用while 循环:ObjectInputStream ois = getOIS(fis); while (ois.available() &gt; 0) { HYB hf2 = (HYB) ois.readObject(); System.out.println(hf2); }。这是有效的,因为您的应用程序知道它在开始读取之前会写入所有内容;如果您不确定(例如,如果您正在从 Socket 读取),那么您可以改用while (true),然后捕获EOFException,一旦您在阅读完最后一个对象(或者如果 Socket 过早关闭)。
    • 你说捕获 EOFException。有没有其他方法可以解决这个问题?
    • 我建议了两种方法:使用ObjectInputStream.available() 测试您是否已到达流的末尾,或读取直到抛出EOFException 并使用它来确定您已到达流的末端。抓住EOFException 本质上并不是一个坏主意,如果你不能保证所有的写作都会在你开始阅读之前发生,那么这是你唯一的选择。但是对于您所描述的,任何一种方法都可以使用。更大的问题是,你为什么反对异常处理?
    • 谢谢。我认为捕获异常是个坏主意。但我发现以下链接解释了为什么我们应该捕获此异常。 link
    • 捕获异常实际上是一个好主意,但只能在您可以有意义地处理它们的地方(即采取行动作为回应)。很多人在处理异常方面做得不好,因为他们在不知道如何处理它们的代码中捕获它们(通常是因为它在调用堆栈中太深了,因为他们害怕抛出异常来自他们自己的代码),所以他们将它们记录到 Log4J,然后继续,就好像没有出错一样。
    【解决方案2】:

    您正在向流中写入两个 HYB 对象,但只读出一个。

    您需要readObject() 两次。

    【讨论】:

      猜你喜欢
      • 2010-11-14
      • 1970-01-01
      相关资源
      最近更新 更多