用于构建epub的Java代码不起作用

时间:2011-11-15 04:09:23

标签: java zip epub

我创建了一个java类来读取一个txt文件并转换成EPUB格式,我的代码能够生成必要的文件到ZipOutputStream(java.util.zip)对象中。 生成的zio文件包含以下文件:

  1. index.html
  2. mimetype
  3. content.opf
  4. toc.ncx
  5. META-INF / container.xml中
  6. 但是当我尝试加载epub文件时,它是不可行的。在线epub验证(http://threepress.org/document/epub-validate/)抛出错误,找不到“META-INF / container.xml”文件,但是有点奇怪的是我可以正确地提取zip存档和所有内容如果我使用windows winzip实用程序重新创建提取到zip文件,epub正在工作! 以下是用于创建container.xml文件的代码片段

    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.util.Enumeration;
    import java.util.Iterator;
    import java.util.zip.Deflater;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipFile;
    import java.util.zip.ZipOutputStream;
    
    import javax.swing.JPopupMenu.Separator;
    
    public class ToEPub {
    
    private String rootDir;
    
    private static String metaFolder = "META-INF";
    private static String oebpsFolder = "";// "OEBPS";
    private static String containerFile = "container.xml";
    private static String contentPpfFile = "content.opf";
    private static String tocFile = "toc.ncx";
    private static String baseFileName;
    private static String baseFilePathHTML;
    private static String baseFileNameHTML;
    private String baseFilePath;
    private ZipOutputStream zip;
    private String baseFileZipPath;
    
    public ToEPub(String fileName) throws IOException {
        File file = new File(fileName);
        rootDir = file.getParent();
        baseFileName = file.getName();
        baseFilePath = file.getPath();
        baseFilePathHTML = baseFilePath + ".html";
        baseFileNameHTML = baseFileName.substring(0, baseFileName
                .lastIndexOf("."))
                + ".html";
        baseFileZipPath = baseFilePath.substring(0, baseFilePath
                .lastIndexOf("."))
                + ".epub";
        zip = new ZipOutputStream(new FileOutputStream(baseFileZipPath));
    
    }
    
    public void start() throws IOException {
    
        createMimeFile();
        createMeta();
        readConnent();
        createContentList();
        createTocFile();
    
        //zip.flush();
        zip.close();
        /*
         * Reading Creating Zip again
         */
        ZipFile zfile = new ZipFile(new File(baseFileZipPath));
        System.out.println(zfile.size() + " Files");
        Enumeration<? extends ZipEntry> itr = zfile.entries();
        while(itr.hasMoreElements()){
            ZipEntry entry = itr.nextElement();
            System.out.println(entry.getName()+" Size: "+entry.getCompressedSize()+"/"+entry.getSize() +" CRC: "+ entry.getCrc());
    
        }
    }
    
    public void createMimeFile() throws IOException {
        byte[] content = "application/epub+zip".getBytes("UTF-8");
        ZipEntry entry = new ZipEntry("mimetype");
        entry.setMethod(ZipEntry.STORED);
        entry.setSize(20);
        entry.setCompressedSize(20);
        entry.setCrc(0x2CAB616F); // pre-computed
        zip.putNextEntry(entry);
    
        zip.write(content);
        zip.closeEntry();
    
    }
    
    public void readConnent() throws IOException {
        String thisLine;
        FileReader fr = new FileReader(baseFilePath);
        BufferedReader bReader = new BufferedReader(fr);
        String outFile = oebpsFolder + File.separator + baseFileNameHTML;
        ZipEntry entry = new ZipEntry(baseFileNameHTML);
        zip.putNextEntry(entry);
        zip.write("<?xml version='1.0' encoding='utf-8'?>\r\n".getBytes("UTF-8"));
        zip.write("<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n"
                .getBytes("UTF-8"));
        while ((thisLine = bReader.readLine()) != null) { // while loop
            // begins here
            zip.write(("<p>" + thisLine + "</p>\r\n").getBytes("UTF-8"));
        } // end while
        zip.write("</html>".getBytes("UTF-8"));
        zip.closeEntry();
    }
    
    public void createContentList() throws IOException{
        ZipEntry entry = new ZipEntry(contentPpfFile);
        zip.putNextEntry(entry);
         zip.write("<?xml version='1.0' encoding='utf-8'?>\r\n".getBytes("UTF-8"));
         zip.write("<package xmlns=\"http://www.idpf.org/2007/opf\" version=\"2.0\" unique-identifier=\"uuid_id\">".getBytes("UTF-8"));
         zip.write("<metadata xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:opf=\"http://www.idpf.org/2007/opf\" xmlns:dcterms=\"http://purl.org/dc/terms/\" xmlns:calibre=\"http://calibre.kovidgoyal.net/2009/metadata\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\r\n".getBytes("UTF-8")); 
         zip.write("<dc:language>en</dc:language>\r\n".getBytes("UTF-8"));
         zip.write("<dc:creator opf:role=\"aut\">Open Mobile Alliance</dc:creator>\r\n".getBytes("UTF-8"));
    
         zip.write("<meta name=\"calibre:timestamp\" content=\"2011-11-11T15:02:14.075083+00:00\"/>\r\n".getBytes("UTF-8")); 
         zip.write("<dc:title>OMA Specification</dc:title>\r\n".getBytes("UTF-8"));
         zip.write("<dc:contributor opf:role=\"bkp\">calibre (0.8.22) [http://calibre-ebook.com]</dc:contributor>\r\n".getBytes("UTF-8"));
         zip.write("<dc:identifier id=\"uuid_id\" opf:scheme=\"uuid\">22fb9171-78bd-4bd1-89f8-7cae3a497c7c</dc:identifier>\r\n".getBytes("UTF-8")); 
         zip.write("<dc:subject>Template</dc:subject>\r\n".getBytes("UTF-8"));
         zip.write("</metadata>\r\n".getBytes("UTF-8")); 
         zip.write("<manifest>\r\n".getBytes("UTF-8"));
         zip.write(("<item href=\""+baseFileNameHTML+"\" id=\"id1\" media-type=\"application/xhtml+xml\"/>\r\n").getBytes("UTF-8"));
         zip.write("<item href=\"toc.ncx\" media-type=\"application/x-dtbncx+xml\" id=\"ncx\"/>\r\n".getBytes("UTF-8")); 
         zip.write("</manifest>\r\n".getBytes("UTF-8")); 
         zip.write("<spine toc=\"ncx\">\r\n".getBytes("UTF-8"));
         zip.write("<itemref idref=\"id1\"/>\r\n".getBytes("UTF-8")); 
         zip.write("</spine>\r\n".getBytes("UTF-8"));
         zip.write("<guide/>\r\n".getBytes("UTF-8")); 
         zip.write("</package>\r\n".getBytes("UTF-8")); 
         zip.closeEntry();
    }
    public void createTocFile() throws IOException{
        ZipEntry entry = new ZipEntry(tocFile);
        zip.putNextEntry(entry);
        zip.write("<?xml version=\"1.0\"?>\r\n".getBytes("UTF-8"));
        zip.write("<container version=\"1.0\" xmlns=\"urn:oasis:names:tc:opendocument:xmlns:container\">\r\n".getBytes("UTF-8")); 
        zip.write("<rootfiles>".getBytes("UTF-8"));
    
        zip.write(("<rootfile full-path=\""+contentPpfFile
                  +"\" media-type=\"application/oebps-package+xml\"/>\r\n").getBytes("UTF-8"));
    
        zip.write("</rootfiles>\r\n".getBytes("UTF-8")); 
        zip.write("</container>".getBytes("UTF-8"));
        zip.closeEntry();
    }
    public void createMeta() throws IOException{
    
        ZipEntry entry = new ZipEntry(metaFolder+File.separator+containerFile);
    
        zip.putNextEntry(entry);
        zip.write("<?xml version=\"1.0\"?>\r\n".getBytes("UTF-8"));
        zip.write("<container version=\"1.0\" xmlns=\"urn:oasis:names:tc:opendocument:xmlns:container\">\r\n".getBytes("UTF-8"));
        zip.write("<rootfiles>\r\n".getBytes("UTF-8"));
        zip.write("<rootfile full-path=\"content.opf\" media-type=\"application/oebps-package+xml\"/>\r\n".getBytes("UTF-8"));
        zip.write("</rootfiles>\r\n".getBytes("UTF-8"));
        zip.write("</container>\r\n".getBytes("UTF-8"));
        zip.closeEntry();
    }
    public void createMetaInfo() throws IOException{
        ZipEntry entry = new ZipEntry(metaFolder+File.separator);
        zip.putNextEntry(entry);
        zip.closeEntry();
    }
    
    }
    

    我尝试将UTF-8更改为默认值但无效

    提前致谢

2 个答案:

答案 0 :(得分:1)

如果我改变

ZipEntry entry = new ZipEntry(metaFolder+File.separator+containerFile);

final ZipEntry entry = new ZipEntry(metaFolder + "/" + containerFile);

它对我有用(在Windows上)。 EpubCheck仍会显示一些(新的)错误,您也应该检查它们。


确保按以下顺序将条目放入zip / epub

  • mimetype
  • META-INF/*
  • 其他一切

我可以在您的原始epub和重新包装的版本之间找到一些差异:

# unzip -l android.epub
Archive:  android.epub
  Length      Date    Time    Name
---------  ---------- -----   ----
       20  11-17-2011 14:48   mimetype
      227  11-17-2011 14:48   META-INF\container.xml
     1589  11-17-2011 14:48   android.html
     1076  11-17-2011 14:48   content.opf
      223  11-17-2011 14:48   toc.ncx
---------                     -------
     3135                     5 files

# unzip -l my.epub
Archive:  my.epub
  Length      Date    Time    Name
---------  ---------- -----   ----
       20  11-17-2011 14:48   mimetype
        0  11-17-2011 11:05   META-INF/
      227  11-17-2011 14:48   META-INF/container.xml
     1076  11-17-2011 14:48   content.opf
      223  11-17-2011 14:48   toc.ncx
     1589  11-17-2011 14:48   android.html
---------                     -------
     3135                     6 files

我尝试在zip文件中添加META-INF文件夹条目。

EpubCheck也会报告错误:

ERROR: android.epub: Required META-INF/container.xml resource is missing

如果META-INF条目没有帮助,请检查EpubCheck的来源,也许它可以提供帮助。

答案 1 :(得分:0)

我知道这是很久以前的事了,但是如果有人再遇到这个问题,我认为问题可能出在createMeta()方法的源代码中。

    zip.write("<rootfile full-path=\"content.opf\" media-type=\"application/oebps-package+xml\"/>\r\n".getBytes("UTF-8"));

不应该如下吗?

    zip.write("<rootfile full-path=\"OEBPS/content.opf\" media-type=\"application/oebps-package+xml\"/>\r\n".getBytes("UTF-8"));