覆盖了readObject()方法,正确地读取了对象,然后将所有成员变量设置为null/默认值。

10 浏览
0 Comments

覆盖了readObject()方法,正确地读取了对象,然后将所有成员变量设置为null/默认值。

我有一个类,我将其序列化到文件中,然后在需要时从文件中反序列化。我在同一个类的构造函数中的一个函数中进行反序列化:\n

try (ObjectInputStream objectInputStream = 
     new ObjectInputStream(new FileInputStream(comdict_file));)
{
  objectInputStream.readObject();
}
catch (ClassNotFoundException e)
{
  // TODO Auto-generated catch block
  System.out.println(e.getMessage());
  e.printStackTrace();
}

\n使用的readObject如下所示:\n

private void readObject(ObjectInputStream in)
  throws IOException, ClassNotFoundException
{
  //读取默认属性
  in.defaultReadObject();
  String file = path + "meanings_info.bin";
  readBuffer(file);
}

\n当运行调试器时,我意识到它正确地读取和加载了所有实例,但一旦退出readObject(而不是defaultReadObject)函数,我就回到了构造函数,所有成员变量都是null或它们的默认值。\n我的问题是,我如何“保留”序列化的值?\n这是该类和测试,虽然我不认为这是问题:\n

public class CompactDictionary implements Serializable
{
  private static final int BUFFER_SIZE_STEP = 10 * 1024 * 1024;
  private TObjectIntHashMap meanings_index = new TObjectIntHashMap<>( 1000 );
  transient private ByteBuffer meanings_info = ByteBuffer.allocate(BUFFER_SIZE_STEP);
  //private int meanings_position = 0;
  private final static long serialVersionUID = 1L;
  //private final static Logger log = LogManager.getLogger();
  private transient Charset charset;
  //private boolean truncate;
  private String path;
  public CompactDictionary(String path, Charset cs, boolean trun)
    throws IOException
  {
    charset = cs;
    this.path = Objects.requireNonNull(path, "path must not be null");
    fileInitiation(trun);
  }
  private void fileInitiation(boolean trun) throws IOException
  {
    String meanings_file = path + "meanings_info.bin";
    String comdict_file = path + "comdict.bin";
    if (!trun) {
      File f = new File(meanings_file);
      File f2 = new File(comdict_file);
      if (!f.exists() || !f.isFile() || !f2.exists() || !f2.isFile()) {
        throw new FileNotFoundException("You chose to not truncate but the saved files are not in the specified directory or they don't have permissions.");
      }
      try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(comdict_file));){
        objectInputStream.readObject();
      } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        System.out.println(e.getMessage());
        e.printStackTrace();
      }
    } else {
      try (FileWriter fwOb = new FileWriter(meanings_file, false);
           PrintWriter pwOb = new PrintWriter(fwOb, false);
           FileWriter fwOb2 = new FileWriter(comdict_file, false);
           PrintWriter pwOb2 = new PrintWriter(fwOb, false);)
      {
        pwOb.flush();
        pwOb2.flush();
      }
    }
  }
  public void setCharset(Charset c) {
    charset = c;
  }
  public int size() {
    return meanings_index.size();
  }
  //TODO
  public boolean contains(String form, char pos)
  {
    return false;
  }
  public boolean contains(String meaning)
  {
    assert StringUtils.isNotBlank(meaning);
    return meanings_index.containsKey(meaning);
  }
  public List getMeanings(String key)
  {
    assert StringUtils.isNotBlank(key);
    int position = getMeaningPosition(key);
    if (position == -1)
     return new ArrayList<>();
    final int old_pos = meanings_info.position();
    meanings_info.position(position);
    final int num_meanings = meanings_info.getShort();
    final List meanings = IntStream.range(0, num_meanings)
        .mapToObj(i ->
    {
       final int num_bytes = meanings_info.getShort();
       byte[] bytes = new byte[num_bytes];
       meanings_info.get(bytes);
       return new String(bytes, charset);
    }).collect(toList());
      meanings_info.position(old_pos);
      return meanings;
  }
  @SuppressWarnings("UnusedReturnValue")
  public boolean addEntry(final String key, List values)
  {
      //assert StringUtils.isNotBlank(meaning) && StringUtils.isNotBlank(label) && glosses != null;
      values.removeIf(String::isEmpty);
      if (contains(key))
            return false;
      final List bytes_list = new ArrayList<>(values.size());
      values.forEach(m ->
      { 
        final byte[] bytes_string = m.getBytes(charset);
        ByteBuffer buffer = ByteBuffer.allocate(2);
        buffer.putShort((short) bytes_string.length);
        final byte[] bytes_count = buffer.array();
        byte[] bytes = ArrayUtils.addAll(bytes_count, bytes_string);
        bytes_list.add(bytes);
      });
      //increase buffer size if necessary
      int num_bytes = Short.BYTES + bytes_list.stream()
        .mapToInt(a -> a.length)
        .sum();
      if (meanings_info.remaining() < num_bytes)
      {
        final ByteBuffer newBuf = ByteBuffer.allocate(meanings_info.capacity() + BUFFER_SIZE_STEP);
        meanings_info.flip();
        newBuf.put(meanings_info);
        meanings_info = newBuf;
      }
      final int position = meanings_info.position();
      meanings_info.putShort((short) values.size()); // a short with max value 32767 should suffice
      // store the bytes for each gloss
      for (final byte[] bytes : bytes_list)
      {
        meanings_info.put(bytes);
      }
      updateMeaningsIndex(key, position);
      return true;
  }
  private int getMeaningPosition(String m)
  {
    if (meanings_index.containsKey(m))
        return meanings_index.get(m);
    return -1;
  }
  private void updateMeaningsIndex(String meaning, int position)
  {
    meanings_index.put(meaning, position);
  }
  private void readBuffer(String filename)
    throws IOException
  {
    FileInputStream fileIn = new FileInputStream(filename);
    ObjectInputStream in = new ObjectInputStream(fileIn);
    int bufferSize = in.readInt();
    byte[] buffer = new byte[bufferSize];
    in.readFully(buffer, 0, bufferSize);
    meanings_info = ByteBuffer.wrap(buffer, 0, bufferSize);
    //meanings_info.position(meanings_position);
    in.close();
    //pasar a try
  }
  private void readObject(ObjectInputStream in)
    throws IOException, ClassNotFoundException
  {
    //final StopWatch timer = new StopWatch(); timer.start();
    //读取默认属性
    in.defaultReadObject();
    String file = path + "meanings_info.bin"; //pasar luego a join Path
    readBuffer(file);
  }
  public void save()
  {
    String comdict_file = path + "comdict.bin";
    try(FileOutputStream fos = new FileOutputStream(comdict_file);
        ObjectOutputStream oos = new ObjectOutputStream(fos);)
    {
      oos.writeObject(this);
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
    String meanings_file = path + "meanings_info.bin";
    try(FileOutputStream fos = new FileOutputStream(meanings_file);
        ObjectOutputStream oos = new ObjectOutputStream(fos);)
    {
        oos.writeInt(meanings_info.position());
        oos.write(meanings_info.array());
    }
    catch (Exception e) {
      System.out.println(e.getMessage());
    }
  }
}
@Test
public void testSave() throws Exception
{
  List value2 = new ArrayList<>();
  List value3 = Arrays.asList(new String[]{"first", "second"});
  index.addEntry("testKey2", value2);
  index.addEntry("testKey3", value3);
  index.save();
  index = new CompactDictionary("src/test/resources/indexes/", StandardCharsets.UTF_8, false);
  List actual;
  actual = index.getMeanings("testKey2");
  assertEquals("Seems that your index is messed up...", value2, actual);
  actual = index.getMeanings("testKey3");
  assertEquals("Seems that your index is messed up...", value3, actual);
}

0
0 Comments

问题出现的原因是在构造函数中调用了`readObject()`方法,但是没有保存返回值,导致读取的对象被丢弃了。解决方法是将读取对象的操作移至其他类的方法中,并且只序列化值而不是整个对象,可以使用除Java序列化之外的其他方式进行序列化。

0