代码之家  ›  专栏  ›  技术社区  ›  ipingu

在序列化和存储在Jarfile中时,什么可以修改SerialVersionUID?

  •  3
  • ipingu  · 技术社区  · 17 年前

    IOException during package import : java.util.ArrayList; local class incompatible: stream classdesc serialVersionUID = 8664875232659988799, local class serialVersionUID = 8683452581122892189
    

    因此,我认为问题在于当我将序列化对象保存到Jarfile条目中时。我认为我做得对,因为可以正确读取以相同方式保存在Jarfile中的其他文件。 在使用“cmp”和“hexdump”后,我发现将其保存为jar会导致一个八位字节的变化,如果uuid是,否则内容是相同的。

    我真的很失望,无法说明问题可能在哪里。


    添加源代码:

    /**
     * Writes content provided from a reader into a file contained in a jar.
     * 
     * @param output the output stream to write on
     * @param entryName the name of the file that will contain reader data
     * @param contentReader 
     * 
     * @return the zip entry that has been created into the jar
     */
    ZipEntry writeEntry(JarOutputStream output, String entryName, ByteArrayInputStream input) {
        if (output == null || entryName == null || entryName.trim().length() == 0 || input == null) {
            throw new NullPointerException("Null argument passed");
        }
    
        ZipEntry entry = new ZipEntry(entryName);
        byte[] buffer = new byte[BUFFER_LENGTH];
    
        try {
            output.putNextEntry(entry);
            int nRead;
    
            while ((nRead = input.read(buffer, 0, BUFFER_LENGTH)) > 0) {
                output.write(buffer, 0, nRead);
            }
    
            output.closeEntry();
        } catch (IOException e) {
            e.printStackTrace();
        }
    
        return entry;
    }
    
    /**
     * Export rules files to a serialized object (ArrayList<KnowledgePackage>) into 
     * an output stream, then write the output content as an entry of a jar.
     * 
     * @param os the output jar to write in
     */
    void writeRulesPackageEntry(JarOutputStream os) {
        // serialize objects and write them to the output stream
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        RulesPackaging rulesPackaging = new RulesPackaging();
        rulesPackaging.exportResources(this.rules, output);
    
        // create a new input stream to read written objects from
        ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
        this.writeEntry(os, Product.ENTRY_RULES_PACKAGE, input);
    }
    
    /**
     * Creates a JarFile containing resources. 
     * 
     * @param filename the exported jar filename
     * @return the jar as an object, null if an error occured
     */
    public JarFile exportToJar(String filename) {
        FileOutputStream fOs;
        JarOutputStream jOs;
        JarFile jar = null;
    
        try {
            fOs = new FileOutputStream(filename);
            jOs = new JarOutputStream(fOs);
    
            this.writeRulesPackageEntry(jOs);
    
            jOs.close();
    
            // construct a jar from the output jar
            jar = new JarFile(new File(filename));
        } catch (IOException e) {
            e.printStackTrace();
        }
    
        return jar;
    }
    
    3 回复  |  直到 17 年前
        1
  •  3
  •   Nick Holt    17 年前

    serialVersionUID 不会改变。它是一个 static final 在编译时分配(我认为是基于源代码的哈希值),除非在源代码中明确分配了值。

    这里有更多关于它的信息 http://mindprod.com/jgloss/serialization.html .

    除了你看到的是正确的 序列版本唯一标识符 对于java.util。ArrayList是8683452581122892189L,它在源代码中显式分配,自1.2中引入该类以来一直保持不变。

    正如您所说,错误最有可能发生在字节流到JarFile时——请发布您用于执行此操作的代码。

    源代码发布后继续

    我怀疑问题在于使用 java.io.InputStreamReader .

    来自JavaDoc:

    InputStreamReader是从 字节流到字符流:它 读取字节并将其解码为 使用指定字符集的字符。 它使用的字符集可能是 按名称指定或可以给出 明确地,或平台的默认设置

    一旦我看到非文本流中涉及的字符集,我总是会怀疑,因为在解码过程中,流可能会被修改,因为字节序列与字符集中的字符不对应(看到编码问题发生时出现的小方块字符)。我会尝试直接读取字节 java.io.ByteArrayInputStream 你正在用 java.io.InputStreamReader writeRulesPackageEntry(JarOutputStream) .转换为a char[] 没有必要。

        2
  •  0
  •   Laurence Vanhelsuwe    17 年前

    正如Nick所提出的,问题很可能是你没有将流视为字节(永远不会改变),而是将其视为字符(可以改变)。

    话虽如此,关于序列化的另一个不错的资源是我在一百万年前(1997年)写的一本书《精通JavaBeans》中的一章。幸运的是,第11章“序列化”在今天和当时一样重要。从以下网址下载免费PDF http://ccd.uab.es/~srobles/manuals/JavaBeans

        3
  •  0
  •   DreadPirateShawn    17 年前

    是否有可能早期版本被序列化到JarFile中,而后续的序列化尝试未能覆盖它?然后,您将检索该类早期版本的序列化数据,这将(正确地)抛出“不兼容”错误。