epub Book to EpubBook

pull/921/head
gedoor 4 years ago
parent 6cda4f49af
commit c53784ca37
  1. 38
      app/src/main/java/io/legado/app/model/localBook/EpubFile.kt
  2. 26
      epublib/src/main/java/me/ag2s/epublib/browsersupport/NavigationEvent.java
  3. 8
      epublib/src/main/java/me/ag2s/epublib/browsersupport/NavigationHistory.java
  4. 15
      epublib/src/main/java/me/ag2s/epublib/browsersupport/Navigator.java
  5. 323
      epublib/src/main/java/me/ag2s/epublib/domain/Book.java
  6. 320
      epublib/src/main/java/me/ag2s/epublib/domain/EpubBook.java
  7. 4
      epublib/src/main/java/me/ag2s/epublib/epub/BookProcessor.java
  8. 9
      epublib/src/main/java/me/ag2s/epublib/epub/BookProcessorPipeline.java
  9. 46
      epublib/src/main/java/me/ag2s/epublib/epub/EpubReader.java
  10. 30
      epublib/src/main/java/me/ag2s/epublib/epub/EpubWriter.java
  11. 19
      epublib/src/main/java/me/ag2s/epublib/epub/NCXDocumentV2.java
  12. 14
      epublib/src/main/java/me/ag2s/epublib/epub/NCXDocumentV3.java
  13. 29
      epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentMetadataWriter.java
  14. 63
      epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentReader.java
  15. 36
      epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentWriter.java

@ -62,19 +62,19 @@ class EpubFile(var book: Book) {
}
}
private var epubBook: EpubBook? = null
private var mCharset: Charset = Charset.defaultCharset()
private var epubBook: EpubBook? = null
get() {
if (field != null) {
return field
}
field = readEpub()
return field
}
init {
try {
val inputStream = if (book.bookUrl.isContentScheme()) {
val uri = Uri.parse(book.bookUrl)
appCtx.contentResolver.openInputStream(uri)
} else {
File(book.bookUrl).inputStream()
}
epubBook = readEpub(inputStream)
if (epubBook != null) {
epubBook?.let {
if (book.coverUrl.isNullOrEmpty()) {
book.coverUrl = FileUtils.getPath(
appCtx.externalFilesDir,
@ -84,8 +84,8 @@ class EpubFile(var book: Book) {
}
if (!File(book.coverUrl!!).exists()) {
/*部分书籍DRM处理后,封面获取异常,待优化*/
epubBook!!.coverImage?.inputStream?.use {
val cover = BitmapFactory.decodeStream(it)
it.coverImage?.inputStream?.use { input ->
val cover = BitmapFactory.decodeStream(input)
val out = FileOutputStream(FileUtils.createFileIfNotExist(book.coverUrl!!))
cover.compress(Bitmap.CompressFormat.JPEG, 90, out)
out.flush()
@ -99,9 +99,15 @@ class EpubFile(var book: Book) {
}
/*重写epub文件解析代码,直接读出压缩包文件生成Resources给epublib,这样的好处是可以逐一修改某些文件的格式错误*/
private fun readEpub(input: InputStream?): EpubBook? {
if (input == null) return null
private fun readEpub(): EpubBook? {
try {
val input = if (book.bookUrl.isContentScheme()) {
val uri = Uri.parse(book.bookUrl)
appCtx.contentResolver.openInputStream(uri)
} else {
File(book.bookUrl).inputStream()
}
input ?: return null
val inZip = ZipInputStream(input)
var zipEntry: ZipEntry?
val resources = Resources()
@ -120,7 +126,7 @@ class EpubFile(var book: Book) {
}
resources.add(resource)
} while (zipEntry != null)
if (resources.size() > 0) return EpubReader().readEpubBook(resources)
if (resources.size() > 0) return EpubReader().readEpub(resources)
} catch (e: Exception) {
e.printStackTrace()
}
@ -129,9 +135,7 @@ class EpubFile(var book: Book) {
private fun getContent(chapter: BookChapter): String? {
/*获取当前章节文本*/
val string = getChildChapter(chapter, chapter.url)
return string
return getChildChapter(chapter, chapter.url)
}
private fun getChildChapter(chapter: BookChapter, href: String): String? {

@ -2,7 +2,7 @@ package me.ag2s.epublib.browsersupport;
import java.util.EventObject;
import me.ag2s.epublib.domain.Book;
import me.ag2s.epublib.domain.EpubBook;
import me.ag2s.epublib.domain.Resource;
import me.ag2s.epublib.util.StringUtil;
@ -20,9 +20,9 @@ public class NavigationEvent extends EventObject {
private Resource oldResource;
private int oldSpinePos;
private Navigator navigator;
private Book oldBook;
private int oldSectionPos;
private Navigator navigator;
private EpubBook oldBook;
private int oldSectionPos;
private String oldFragmentId;
public NavigationEvent(Object source) {
@ -61,9 +61,9 @@ public class NavigationEvent extends EventObject {
this.oldFragmentId = oldFragmentId;
}
public Book getOldBook() {
return oldBook;
}
public EpubBook getOldBook() {
return oldBook;
}
// package
void setOldPagePos(int oldPagePos) {
@ -124,13 +124,13 @@ public class NavigationEvent extends EventObject {
}
public void setOldBook(Book oldBook) {
this.oldBook = oldBook;
}
public void setOldBook(EpubBook oldBook) {
this.oldBook = oldBook;
}
public Book getCurrentBook() {
return getNavigator().getBook();
}
public EpubBook getCurrentBook() {
return getNavigator().getBook();
}
public boolean isResourceChanged() {
return oldResource != getCurrentResource();

@ -1,15 +1,15 @@
package me.ag2s.epublib.browsersupport;
import me.ag2s.epublib.domain.Book;
import me.ag2s.epublib.domain.Resource;
import java.util.ArrayList;
import java.util.List;
import me.ag2s.epublib.domain.EpubBook;
import me.ag2s.epublib.domain.Resource;
/**
* A history of the user's locations with the epub.
*
* @author paul.siegmann
*
*/
public class NavigationHistory implements NavigationEventListener {
@ -58,7 +58,7 @@ public class NavigationHistory implements NavigationEventListener {
return currentSize;
}
public void initBook(Book book) {
public void initBook(EpubBook book) {
if (book == null) {
return;
}

@ -1,14 +1,15 @@
package me.ag2s.epublib.browsersupport;
import me.ag2s.epublib.domain.Book;
import me.ag2s.epublib.domain.Resource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import me.ag2s.epublib.domain.EpubBook;
import me.ag2s.epublib.domain.Resource;
/**
* A helper class for epub browser applications.
*
* <p>
* It helps moving from one resource to the other, from one resource
* to the other and keeping other elements of the application up-to-date
* by calling the NavigationEventListeners.
@ -18,7 +19,7 @@ import java.util.List;
public class Navigator implements Serializable {
private static final long serialVersionUID = 1076126986424925474L;
private Book book;
private EpubBook book;
private int currentSpinePos;
private Resource currentResource;
private int currentPagePos;
@ -30,7 +31,7 @@ public class Navigator implements Serializable {
this(null);
}
public Navigator(Book book) {
public Navigator(EpubBook book) {
this.book = book;
this.currentSpinePos = 0;
if (book != null) {
@ -158,7 +159,7 @@ public class Navigator implements Serializable {
return gotoSpineSection(book.getSpine().size() - 1, source);
}
public void gotoBook(Book book, Object source) {
public void gotoBook(EpubBook book, Object source) {
NavigationEvent navigationEvent = new NavigationEvent(source, this);
this.book = book;
this.currentFragmentId = null;
@ -193,7 +194,7 @@ public class Navigator implements Serializable {
this.currentResource = book.getSpine().getResource(currentIndex);
}
public Book getBook() {
public EpubBook getBook() {
return book;
}

@ -1,323 +0,0 @@
package me.ag2s.epublib.domain;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Representation of a Book.
* <p>
* All resources of a Book (html, css, xml, fonts, images) are represented
* as Resources. See getResources() for access to these.<br/>
* A Book as 3 indexes into these Resources, as per the epub specification.<br/>
* <dl>
* <dt>Spine</dt>
* <dd>these are the Resources to be shown when a user reads the book from
* start to finish.</dd>
* <dt>Table of Contents<dt>
* <dd>The table of contents. Table of Contents references may be in a
* different order and contain different Resources than the spine, and often do.
* <dt>Guide</dt>
* <dd>The Guide has references to a set of special Resources like the
* cover page, the Glossary, the copyright page, etc.
* </dl>
* <p/>
* The complication is that these 3 indexes may and usually do point to
* different pages.
* A chapter may be split up in 2 pieces to fit it in to memory. Then the
* spine will contain both pieces, but the Table of Contents only the first.
* <p>
* The Content page may be in the Table of Contents, the Guide, but not
* in the Spine.
* Etc.
* <p/>
* <p>
* Please see the illustration at: doc/schema.svg
*
* @author paul
* @author jake
*/
public class Book implements Serializable {
private static final long serialVersionUID = 2068355170895770100L;
private Resources resources = new Resources();
private Metadata metadata = new Metadata();
private Spine spine = new Spine();
private TableOfContents tableOfContents = new TableOfContents();
private final Guide guide = new Guide();
private Resource opfResource;
private Resource ncxResource;
private Resource coverImage;
private String version="2.0";
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public boolean isEpub3() {
return this.version.startsWith("3.");
}
@SuppressWarnings("UnusedReturnValue")
public TOCReference addSection(
TOCReference parentSection, String sectionTitle, Resource resource) {
return addSection(parentSection, sectionTitle, resource, null);
}
/**
* Adds the resource to the table of contents of the book as a child
* section of the given parentSection
*
* @param parentSection parentSection
* @param sectionTitle sectionTitle
* @param resource resource
* @param fragmentId fragmentId
* @return The table of contents
*/
public TOCReference addSection(
TOCReference parentSection, String sectionTitle, Resource resource,
String fragmentId) {
getResources().add(resource);
if (spine.findFirstResourceById(resource.getId()) < 0) {
spine.addSpineReference(new SpineReference(resource));
}
return parentSection.addChildSection(
new TOCReference(sectionTitle, resource, fragmentId));
}
public TOCReference addSection(String title, Resource resource) {
return addSection(title, resource, null);
}
/**
* Adds a resource to the book's set of resources, table of contents and
* if there is no resource with the id in the spine also adds it to the spine.
*
* @param title title
* @param resource resource
* @param fragmentId fragmentId
* @return The table of contents
*/
public TOCReference addSection(
String title, Resource resource, String fragmentId) {
getResources().add(resource);
TOCReference tocReference = tableOfContents
.addTOCReference(new TOCReference(title, resource, fragmentId));
if (spine.findFirstResourceById(resource.getId()) < 0) {
spine.addSpineReference(new SpineReference(resource));
}
return tocReference;
}
@SuppressWarnings("unused")
public void generateSpineFromTableOfContents() {
Spine spine = new Spine(tableOfContents);
// in case the tocResource was already found and assigned
spine.setTocResource(this.spine.getTocResource());
this.spine = spine;
}
/**
* The Book's metadata (titles, authors, etc)
*
* @return The Book's metadata (titles, authors, etc)
*/
public Metadata getMetadata() {
return metadata;
}
public void setMetadata(Metadata metadata) {
this.metadata = metadata;
}
public void setResources(Resources resources) {
this.resources = resources;
}
@SuppressWarnings("unused")
public Resource addResource(Resource resource) {
return resources.add(resource);
}
/**
* The collection of all images, chapters, sections, xhtml files,
* stylesheets, etc that make up the book.
*
* @return The collection of all images, chapters, sections, xhtml files,
* stylesheets, etc that make up the book.
*/
public Resources getResources() {
return resources;
}
/**
* The sections of the book that should be shown if a user reads the book
* from start to finish.
*
* @return The Spine
*/
public Spine getSpine() {
return spine;
}
public void setSpine(Spine spine) {
this.spine = spine;
}
/**
* The Table of Contents of the book.
*
* @return The Table of Contents of the book.
*/
public TableOfContents getTableOfContents() {
return tableOfContents;
}
public void setTableOfContents(TableOfContents tableOfContents) {
this.tableOfContents = tableOfContents;
}
/**
* The book's cover page as a Resource.
* An XHTML document containing a link to the cover image.
*
* @return The book's cover page as a Resource
*/
public Resource getCoverPage() {
Resource coverPage = guide.getCoverPage();
if (coverPage == null) {
coverPage = spine.getResource(0);
}
return coverPage;
}
public void setCoverPage(Resource coverPage) {
if (coverPage == null) {
return;
}
if (resources.notContainsByHref(coverPage.getHref())) {
resources.add(coverPage);
}
guide.setCoverPage(coverPage);
}
/**
* Gets the first non-blank title from the book's metadata.
*
* @return the first non-blank title from the book's metadata.
*/
public String getTitle() {
return getMetadata().getFirstTitle();
}
/**
* The book's cover image.
*
* @return The book's cover image.
*/
public Resource getCoverImage() {
return coverImage;
}
public void setCoverImage(Resource coverImage) {
if (coverImage == null) {
return;
}
if (resources.notContainsByHref(coverImage.getHref())) {
resources.add(coverImage);
}
this.coverImage = coverImage;
}
/**
* The guide; contains references to special sections of the book like
* colophon, glossary, etc.
*
* @return The guide; contains references to special sections of the book
* like colophon, glossary, etc.
*/
public Guide getGuide() {
return guide;
}
/**
* All Resources of the Book that can be reached via the Spine, the
* TableOfContents or the Guide.
* <p/>
* Consists of a list of "reachable" resources:
* <ul>
* <li>The coverpage</li>
* <li>The resources of the Spine that are not already in the result</li>
* <li>The resources of the Table of Contents that are not already in the
* result</li>
* <li>The resources of the Guide that are not already in the result</li>
* </ul>
* To get all html files that make up the epub file use
* {@link #getResources()}
*
* @return All Resources of the Book that can be reached via the Spine,
* the TableOfContents or the Guide.
*/
public List<Resource> getContents() {
Map<String, Resource> result = new LinkedHashMap<>();
addToContentsResult(getCoverPage(), result);
for (SpineReference spineReference : getSpine().getSpineReferences()) {
addToContentsResult(spineReference.getResource(), result);
}
for (Resource resource : getTableOfContents().getAllUniqueResources()) {
addToContentsResult(resource, result);
}
for (GuideReference guideReference : getGuide().getReferences()) {
addToContentsResult(guideReference.getResource(), result);
}
return new ArrayList<>(result.values());
}
private static void addToContentsResult(Resource resource,
Map<String, Resource> allReachableResources) {
if (resource != null && (!allReachableResources
.containsKey(resource.getHref()))) {
allReachableResources.put(resource.getHref(), resource);
}
}
public Resource getOpfResource() {
return opfResource;
}
public void setOpfResource(Resource opfResource) {
this.opfResource = opfResource;
}
public void setNcxResource(Resource ncxResource) {
this.ncxResource = ncxResource;
}
public Resource getNcxResource() {
return ncxResource;
}
}

@ -1,9 +1,323 @@
package me.ag2s.epublib.domain;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* 这个是用于其它与Book类同名时替换的
* Representation of a Book.
* <p>
* All resources of a Book (html, css, xml, fonts, images) are represented
* as Resources. See getResources() for access to these.<br/>
* A Book as 3 indexes into these Resources, as per the epub specification.<br/>
* <dl>
* <dt>Spine</dt>
* <dd>these are the Resources to be shown when a user reads the book from
* start to finish.</dd>
* <dt>Table of Contents<dt>
* <dd>The table of contents. Table of Contents references may be in a
* different order and contain different Resources than the spine, and often do.
* <dt>Guide</dt>
* <dd>The Guide has references to a set of special Resources like the
* cover page, the Glossary, the copyright page, etc.
* </dl>
* <p/>
* The complication is that these 3 indexes may and usually do point to
* different pages.
* A chapter may be split up in 2 pieces to fit it in to memory. Then the
* spine will contain both pieces, but the Table of Contents only the first.
* <p>
* The Content page may be in the Table of Contents, the Guide, but not
* in the Spine.
* Etc.
* <p/>
* <p>
* Please see the illustration at: doc/schema.svg
*
* @author paul
* @author jake
*/
@SuppressWarnings("unused declaration")
public class EpubBook extends Book {
public class EpubBook implements Serializable {
private static final long serialVersionUID = 2068355170895770100L;
private Resources resources = new Resources();
private Metadata metadata = new Metadata();
private Spine spine = new Spine();
private TableOfContents tableOfContents = new TableOfContents();
private final Guide guide = new Guide();
private Resource opfResource;
private Resource ncxResource;
private Resource coverImage;
private String version = "2.0";
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public boolean isEpub3() {
return this.version.startsWith("3.");
}
@SuppressWarnings("UnusedReturnValue")
public TOCReference addSection(
TOCReference parentSection, String sectionTitle, Resource resource) {
return addSection(parentSection, sectionTitle, resource, null);
}
/**
* Adds the resource to the table of contents of the book as a child
* section of the given parentSection
*
* @param parentSection parentSection
* @param sectionTitle sectionTitle
* @param resource resource
* @param fragmentId fragmentId
* @return The table of contents
*/
public TOCReference addSection(
TOCReference parentSection, String sectionTitle, Resource resource,
String fragmentId) {
getResources().add(resource);
if (spine.findFirstResourceById(resource.getId()) < 0) {
spine.addSpineReference(new SpineReference(resource));
}
return parentSection.addChildSection(
new TOCReference(sectionTitle, resource, fragmentId));
}
public TOCReference addSection(String title, Resource resource) {
return addSection(title, resource, null);
}
/**
* Adds a resource to the book's set of resources, table of contents and
* if there is no resource with the id in the spine also adds it to the spine.
*
* @param title title
* @param resource resource
* @param fragmentId fragmentId
* @return The table of contents
*/
public TOCReference addSection(
String title, Resource resource, String fragmentId) {
getResources().add(resource);
TOCReference tocReference = tableOfContents
.addTOCReference(new TOCReference(title, resource, fragmentId));
if (spine.findFirstResourceById(resource.getId()) < 0) {
spine.addSpineReference(new SpineReference(resource));
}
return tocReference;
}
@SuppressWarnings("unused")
public void generateSpineFromTableOfContents() {
Spine spine = new Spine(tableOfContents);
// in case the tocResource was already found and assigned
spine.setTocResource(this.spine.getTocResource());
this.spine = spine;
}
/**
* The Book's metadata (titles, authors, etc)
*
* @return The Book's metadata (titles, authors, etc)
*/
public Metadata getMetadata() {
return metadata;
}
public void setMetadata(Metadata metadata) {
this.metadata = metadata;
}
public void setResources(Resources resources) {
this.resources = resources;
}
@SuppressWarnings("unused")
public Resource addResource(Resource resource) {
return resources.add(resource);
}
/**
* The collection of all images, chapters, sections, xhtml files,
* stylesheets, etc that make up the book.
*
* @return The collection of all images, chapters, sections, xhtml files,
* stylesheets, etc that make up the book.
*/
public Resources getResources() {
return resources;
}
/**
* The sections of the book that should be shown if a user reads the book
* from start to finish.
*
* @return The Spine
*/
public Spine getSpine() {
return spine;
}
public void setSpine(Spine spine) {
this.spine = spine;
}
/**
* The Table of Contents of the book.
*
* @return The Table of Contents of the book.
*/
public TableOfContents getTableOfContents() {
return tableOfContents;
}
public void setTableOfContents(TableOfContents tableOfContents) {
this.tableOfContents = tableOfContents;
}
/**
* The book's cover page as a Resource.
* An XHTML document containing a link to the cover image.
*
* @return The book's cover page as a Resource
*/
public Resource getCoverPage() {
Resource coverPage = guide.getCoverPage();
if (coverPage == null) {
coverPage = spine.getResource(0);
}
return coverPage;
}
public void setCoverPage(Resource coverPage) {
if (coverPage == null) {
return;
}
if (resources.notContainsByHref(coverPage.getHref())) {
resources.add(coverPage);
}
guide.setCoverPage(coverPage);
}
/**
* Gets the first non-blank title from the book's metadata.
*
* @return the first non-blank title from the book's metadata.
*/
public String getTitle() {
return getMetadata().getFirstTitle();
}
/**
* The book's cover image.
*
* @return The book's cover image.
*/
public Resource getCoverImage() {
return coverImage;
}
public void setCoverImage(Resource coverImage) {
if (coverImage == null) {
return;
}
if (resources.notContainsByHref(coverImage.getHref())) {
resources.add(coverImage);
}
this.coverImage = coverImage;
}
/**
* The guide; contains references to special sections of the book like
* colophon, glossary, etc.
*
* @return The guide; contains references to special sections of the book
* like colophon, glossary, etc.
*/
public Guide getGuide() {
return guide;
}
/**
* All Resources of the Book that can be reached via the Spine, the
* TableOfContents or the Guide.
* <p/>
* Consists of a list of "reachable" resources:
* <ul>
* <li>The coverpage</li>
* <li>The resources of the Spine that are not already in the result</li>
* <li>The resources of the Table of Contents that are not already in the
* result</li>
* <li>The resources of the Guide that are not already in the result</li>
* </ul>
* To get all html files that make up the epub file use
* {@link #getResources()}
*
* @return All Resources of the Book that can be reached via the Spine,
* the TableOfContents or the Guide.
*/
public List<Resource> getContents() {
Map<String, Resource> result = new LinkedHashMap<>();
addToContentsResult(getCoverPage(), result);
for (SpineReference spineReference : getSpine().getSpineReferences()) {
addToContentsResult(spineReference.getResource(), result);
}
for (Resource resource : getTableOfContents().getAllUniqueResources()) {
addToContentsResult(resource, result);
}
for (GuideReference guideReference : getGuide().getReferences()) {
addToContentsResult(guideReference.getResource(), result);
}
return new ArrayList<>(result.values());
}
private static void addToContentsResult(Resource resource,
Map<String, Resource> allReachableResources) {
if (resource != null && (!allReachableResources
.containsKey(resource.getHref()))) {
allReachableResources.put(resource.getHref(), resource);
}
}
public Resource getOpfResource() {
return opfResource;
}
public void setOpfResource(Resource opfResource) {
this.opfResource = opfResource;
}
public void setNcxResource(Resource ncxResource) {
this.ncxResource = ncxResource;
}
public Resource getNcxResource() {
return ncxResource;
}
}

@ -1,6 +1,6 @@
package me.ag2s.epublib.epub;
import me.ag2s.epublib.domain.Book;
import me.ag2s.epublib.domain.EpubBook;
/**
* Post-processes a book.
@ -16,5 +16,5 @@ public interface BookProcessor {
*/
BookProcessor IDENTITY_BOOKPROCESSOR = book -> book;
Book processBook(Book book);
EpubBook processBook(EpubBook book);
}

@ -2,14 +2,15 @@ package me.ag2s.epublib.epub;
import android.util.Log;
import me.ag2s.epublib.domain.Book;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import me.ag2s.epublib.domain.EpubBook;
/**
* A book processor that combines several other bookprocessors
*
* <p>
* Fixes coverpage/coverimage.
* Cleans up the XHTML.
*
@ -30,7 +31,7 @@ public class BookProcessorPipeline implements BookProcessor {
}
@Override
public Book processBook(Book book) {
public EpubBook processBook(EpubBook book) {
if (bookProcessors == null) {
return book;
}
@ -38,7 +39,7 @@ public class BookProcessorPipeline implements BookProcessor {
try {
book = bookProcessor.processBook(book);
} catch (Exception e) {
Log.e(TAG,e.getMessage(), e);
Log.e(TAG, e.getMessage(), e);
}
}
return book;

@ -13,7 +13,6 @@ import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import me.ag2s.epublib.Constants;
import me.ag2s.epublib.domain.Book;
import me.ag2s.epublib.domain.EpubBook;
import me.ag2s.epublib.domain.MediaType;
import me.ag2s.epublib.domain.MediaTypes;
@ -27,22 +26,21 @@ import me.ag2s.epublib.util.StringUtil;
*
* @author paul
*/
@SuppressWarnings("ALL")
public class EpubReader {
private static final String TAG = EpubReader.class.getName();
private final BookProcessor bookProcessor = BookProcessor.IDENTITY_BOOKPROCESSOR;
@SuppressWarnings("unused")
public Book readEpub(InputStream in) throws IOException {
public EpubBook readEpub(InputStream in) throws IOException {
return readEpub(in, Constants.CHARACTER_ENCODING);
}
@SuppressWarnings("unused")
public Book readEpub(ZipInputStream in) throws IOException {
public EpubBook readEpub(ZipInputStream in) throws IOException {
return readEpub(in, Constants.CHARACTER_ENCODING);
}
@SuppressWarnings("unused")
public Book readEpub(ZipFile zipfile) throws IOException {
public EpubBook readEpub(ZipFile zipfile) throws IOException {
return readEpub(zipfile, Constants.CHARACTER_ENCODING);
}
@ -54,7 +52,7 @@ public class EpubReader {
* @return the Book as read from the inputstream
* @throws IOException IOException
*/
public Book readEpub(InputStream in, String encoding) throws IOException {
public EpubBook readEpub(InputStream in, String encoding) throws IOException {
return readEpub(new ZipInputStream(in), encoding);
}
@ -67,18 +65,17 @@ public class EpubReader {
* @return this Book without loading all resources into memory.
* @throws IOException IOException
*/
@SuppressWarnings("unused")
public Book readEpubLazy(ZipFile zipFile, String encoding)
public EpubBook readEpubLazy(ZipFile zipFile, String encoding)
throws IOException {
return readEpubLazy(zipFile, encoding,
Arrays.asList(MediaTypes.mediaTypes));
}
public Book readEpub(ZipInputStream in, String encoding) throws IOException {
public EpubBook readEpub(ZipInputStream in, String encoding) throws IOException {
return readEpub(ResourcesLoader.loadResources(in, encoding));
}
public Book readEpub(ZipFile in, String encoding) throws IOException {
public EpubBook readEpub(ZipFile in, String encoding) throws IOException {
return readEpub(ResourcesLoader.loadResources(in, encoding));
}
@ -91,24 +88,20 @@ public class EpubReader {
* @return this Book without loading all resources into memory.
* @throws IOException IOException
*/
public Book readEpubLazy(ZipFile zipFile, String encoding,
List<MediaType> lazyLoadedTypes) throws IOException {
public EpubBook readEpubLazy(ZipFile zipFile, String encoding,
List<MediaType> lazyLoadedTypes) throws IOException {
Resources resources = ResourcesLoader
.loadResources(zipFile, encoding, lazyLoadedTypes);
return readEpub(resources);
}
@SuppressWarnings("unused")
public Book readEpub(Resources resources) {
return readEpub(resources, new Book());
}
public EpubBook readEpubBook(Resources resources) {
return (EpubBook) readEpub(resources, new Book());
public EpubBook readEpub(Resources resources) {
return readEpub(resources, new EpubBook());
}
public Book readEpub(Resources resources, Book result) {
public EpubBook readEpub(Resources resources, EpubBook result) {
if (result == null) {
result = new Book();
result = new EpubBook();
}
handleMimeType(result, resources);
String packageResourceHref = getPackageResourceHref(resources);
@ -122,14 +115,14 @@ public class EpubReader {
}
private Book postProcessBook(Book book) {
private EpubBook postProcessBook(EpubBook book) {
if (bookProcessor != null) {
book = bookProcessor.processBook(book);
}
return book;
}
private Resource processNcxResource(Resource packageResource, Book book) {
private Resource processNcxResource(Resource packageResource, EpubBook book) {
Log.d(TAG, "OPF:getHref()" + packageResource.getHref());
if (book.isEpub3()) {
return NCXDocumentV3.read(book, this);
@ -139,7 +132,7 @@ public class EpubReader {
}
private Resource processPackageResource(String packageResourceHref, Book book,
private Resource processPackageResource(String packageResourceHref, EpubBook book,
Resources resources) {
Resource packageResource = resources.remove(packageResourceHref);
try {
@ -173,8 +166,7 @@ public class EpubReader {
return result;
}
@SuppressWarnings("unused")
private void handleMimeType(Book result, Resources resources) {
private void handleMimeType(EpubBook result, Resources resources) {
resources.remove("mimetype");
//result.setResources(resources);
}

@ -2,10 +2,8 @@ package me.ag2s.epublib.epub;
import android.util.Log;
import me.ag2s.epublib.domain.Book;
import me.ag2s.epublib.domain.MediaTypes;
import me.ag2s.epublib.domain.Resource;
import me.ag2s.epublib.util.IOUtil;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -14,7 +12,11 @@ import java.io.Writer;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.xmlpull.v1.XmlSerializer;
import me.ag2s.epublib.domain.EpubBook;
import me.ag2s.epublib.domain.MediaTypes;
import me.ag2s.epublib.domain.Resource;
import me.ag2s.epublib.util.IOUtil;
/**
* Generates an epub file. Not thread-safe, single use object.
@ -40,7 +42,7 @@ public class EpubWriter {
}
public void write(Book book, OutputStream out) throws IOException {
public void write(EpubBook book, OutputStream out) throws IOException {
book = processBook(book);
ZipOutputStream resultStream = new ZipOutputStream(out);
writeMimeType(resultStream);
@ -51,19 +53,19 @@ public class EpubWriter {
resultStream.close();
}
private Book processBook(Book book) {
private EpubBook processBook(EpubBook book) {
if (bookProcessor != null) {
book = bookProcessor.processBook(book);
}
return book;
}
private void initTOCResource(Book book) {
private void initTOCResource(EpubBook book) {
Resource tocResource;
try {
if(book.isEpub3()){
if (book.isEpub3()) {
tocResource = NCXDocumentV3.createNCXResource(book);
}else {
} else {
tocResource = NCXDocumentV2.createNCXResource(book);
}
@ -81,7 +83,7 @@ public class EpubWriter {
}
private void writeResources(Book book, ZipOutputStream resultStream) {
private void writeResources(EpubBook book, ZipOutputStream resultStream) {
for (Resource resource : book.getResources().getAll()) {
writeResource(resource, resultStream);
}
@ -108,11 +110,11 @@ public class EpubWriter {
}
private void writePackageDocument(Book book, ZipOutputStream resultStream)
throws IOException {
private void writePackageDocument(EpubBook book, ZipOutputStream resultStream)
throws IOException {
resultStream.putNextEntry(new ZipEntry("OEBPS/content.opf"));
XmlSerializer xmlSerializer = EpubProcessorSupport
.createXmlSerializer(resultStream);
.createXmlSerializer(resultStream);
PackageDocumentWriter.write(this, xmlSerializer, book);
xmlSerializer.flush();
// String resultAsString = result.toString();

@ -19,7 +19,7 @@ import java.util.zip.ZipOutputStream;
import me.ag2s.epublib.Constants;
import me.ag2s.epublib.domain.Author;
import me.ag2s.epublib.domain.Book;
import me.ag2s.epublib.domain.EpubBook;
import me.ag2s.epublib.domain.Identifier;
import me.ag2s.epublib.domain.MediaTypes;
import me.ag2s.epublib.domain.Resource;
@ -77,7 +77,7 @@ public class NCXDocumentV2 {
}
@SuppressWarnings("unused")
public static Resource read(Book book, EpubReader epubReader) {
public static Resource read(EpubBook book, EpubReader epubReader) {
Resource ncxResource = null;
if (book.getSpine().getTocResource() == null) {
Log.e(TAG, "Book does not contain a table of contents file");
@ -107,7 +107,7 @@ public class NCXDocumentV2 {
}
static List<TOCReference> readTOCReferences(NodeList navpoints,
Book book) {
EpubBook book) {
if (navpoints == null) {
return new ArrayList<>();
}
@ -127,7 +127,7 @@ public class NCXDocumentV2 {
return result;
}
static TOCReference readTOCReference(Element navpointElement, Book book) {
static TOCReference readTOCReference(Element navpointElement, EpubBook book) {
String label = readNavLabel(navpointElement);
//Log.d(TAG,"label:"+label);
String tocResourceRoot = StringUtil
@ -184,8 +184,9 @@ public class NCXDocumentV2 {
return DOMUtil.getTextChildrenContent(DOMUtil
.getFirstElementByTagNameNS(navLabel, NAMESPACE_NCX, NCXTags.text));
}
@SuppressWarnings("unused")
public static void write(EpubWriter epubWriter, Book book,
public static void write(EpubWriter epubWriter, EpubBook book,
ZipOutputStream resultStream) throws IOException {
resultStream
.putNextEntry(new ZipEntry(book.getSpine().getTocResource().getHref()));
@ -200,17 +201,17 @@ public class NCXDocumentV2 {
*
* @param xmlSerializer the serializer used
* @param book the book to serialize
* @throws IOException IOException
* @throws IllegalStateException IllegalStateException
* @throws IOException IOException
* @throws IllegalStateException IllegalStateException
* @throws IllegalArgumentException IllegalArgumentException
*/
public static void write(XmlSerializer xmlSerializer, Book book)
public static void write(XmlSerializer xmlSerializer, EpubBook book)
throws IllegalArgumentException, IllegalStateException, IOException {
write(xmlSerializer, book.getMetadata().getIdentifiers(), book.getTitle(),
book.getMetadata().getAuthors(), book.getTableOfContents());
}
public static Resource createNCXResource(Book book)
public static Resource createNCXResource(EpubBook book)
throws IllegalArgumentException, IllegalStateException, IOException {
return createNCXResource(book.getMetadata().getIdentifiers(),
book.getTitle(), book.getMetadata().getAuthors(),

@ -17,7 +17,7 @@ import java.util.List;
import me.ag2s.epublib.Constants;
import me.ag2s.epublib.domain.Author;
import me.ag2s.epublib.domain.Book;
import me.ag2s.epublib.domain.EpubBook;
import me.ag2s.epublib.domain.Identifier;
import me.ag2s.epublib.domain.MediaType;
import me.ag2s.epublib.domain.MediaTypes;
@ -96,7 +96,7 @@ public class NCXDocumentV3 {
* @return Resource
*/
@SuppressWarnings("unused")
public static Resource read(Book book, EpubReader epubReader) {
public static Resource read(EpubBook book, EpubReader epubReader) {
Resource ncxResource = null;
if (book.getSpine().getTocResource() == null) {
Log.e(TAG, "Book does not contain a table of contents file");
@ -126,7 +126,7 @@ public class NCXDocumentV3 {
return ncxResource;
}
private static List<TOCReference> doToc(Node n, Book book) {
private static List<TOCReference> doToc(Node n, EpubBook book) {
List<TOCReference> result = new ArrayList<>();
if (n == null || n.getNodeType() != Document.ELEMENT_NODE) {
@ -143,7 +143,7 @@ public class NCXDocumentV3 {
static List<TOCReference> readTOCReferences(NodeList navpoints,
Book book) {
EpubBook book) {
if (navpoints == null) {
return new ArrayList<>();
}
@ -169,7 +169,7 @@ public class NCXDocumentV3 {
}
static TOCReference readTOCReference(Element navpointElement, Book book) {
static TOCReference readTOCReference(Element navpointElement, EpubBook book) {
//章节的名称
String label = readNavLabel(navpointElement);
//Log.d(TAG, "label:" + label);
@ -260,7 +260,7 @@ public class NCXDocumentV3 {
}
public static Resource createNCXResource(Book book)
public static Resource createNCXResource(EpubBook book)
throws IllegalArgumentException, IllegalStateException, IOException {
return createNCXResource(book.getMetadata().getIdentifiers(),
book.getTitle(), book.getMetadata().getAuthors(),
@ -289,7 +289,7 @@ public class NCXDocumentV3 {
* @throws IllegalStateException IllegalStateException
* @throws IllegalArgumentException IllegalArgumentException
*/
public static void write(XmlSerializer xmlSerializer, Book book)
public static void write(XmlSerializer xmlSerializer, EpubBook book)
throws IllegalArgumentException, IllegalStateException, IOException {
write(xmlSerializer, book.getMetadata().getIdentifiers(), book.getTitle(),
book.getMetadata().getAuthors(), book.getTableOfContents());

@ -1,39 +1,42 @@
package me.ag2s.epublib.epub;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import me.ag2s.epublib.Constants;
import me.ag2s.epublib.domain.Author;
import me.ag2s.epublib.domain.Book;
import me.ag2s.epublib.domain.Date;
import me.ag2s.epublib.domain.EpubBook;
import me.ag2s.epublib.domain.Identifier;
import me.ag2s.epublib.util.StringUtil;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import org.xmlpull.v1.XmlSerializer;
public class PackageDocumentMetadataWriter extends PackageDocumentBase {
/**
* Writes the book's metadata.
*
* @param book book
* @param book book
* @param serializer serializer
* @throws IOException IOException
* @throws IllegalStateException IllegalStateException
* @throws IOException IOException
* @throws IllegalStateException IllegalStateException
* @throws IllegalArgumentException IllegalArgumentException
*/
public static void writeMetaData(Book book, XmlSerializer serializer)
throws IllegalArgumentException, IllegalStateException, IOException {
public static void writeMetaData(EpubBook book, XmlSerializer serializer)
throws IllegalArgumentException, IllegalStateException, IOException {
serializer.startTag(NAMESPACE_OPF, OPFTags.metadata);
serializer.setPrefix(PREFIX_DUBLIN_CORE, NAMESPACE_DUBLIN_CORE);
serializer.setPrefix(PREFIX_OPF, NAMESPACE_OPF);
writeIdentifiers(book.getMetadata().getIdentifiers(), serializer);
writeSimpleMetdataElements(DCTags.title, book.getMetadata().getTitles(),
serializer);
serializer);
writeSimpleMetdataElements(DCTags.subject, book.getMetadata().getSubjects(),
serializer);
serializer);
writeSimpleMetdataElements(DCTags.description,
book.getMetadata().getDescriptions(), serializer);
writeSimpleMetdataElements(DCTags.publisher,

@ -20,7 +20,7 @@ import java.util.Map;
import java.util.Set;
import me.ag2s.epublib.Constants;
import me.ag2s.epublib.domain.Book;
import me.ag2s.epublib.domain.EpubBook;
import me.ag2s.epublib.domain.Guide;
import me.ag2s.epublib.domain.GuideReference;
import me.ag2s.epublib.domain.MediaType;
@ -46,8 +46,8 @@ public class PackageDocumentReader extends PackageDocumentBase {
public static void read(
Resource packageResource, EpubReader epubReader, Book book,
Resources resources)
Resource packageResource, EpubReader epubReader, EpubBook book,
Resources resources)
throws SAXException, IOException {
Document packageDocument = ResourceUtil.getAsDocument(packageResource);
String packageHref = packageResource.getHref();
@ -155,17 +155,17 @@ public class PackageDocumentReader extends PackageDocumentBase {
*/
@SuppressWarnings("unused")
private static void readGuide(Document packageDocument,
EpubReader epubReader, Book book, Resources resources) {
Element guideElement = DOMUtil
.getFirstElementByTagNameNS(packageDocument.getDocumentElement(),
NAMESPACE_OPF, OPFTags.guide);
if (guideElement == null) {
return;
}
Guide guide = book.getGuide();
NodeList guideReferences = guideElement
.getElementsByTagNameNS(NAMESPACE_OPF, OPFTags.reference);
for (int i = 0; i < guideReferences.getLength(); i++) {
EpubReader epubReader, EpubBook book, Resources resources) {
Element guideElement = DOMUtil
.getFirstElementByTagNameNS(packageDocument.getDocumentElement(),
NAMESPACE_OPF, OPFTags.guide);
if (guideElement == null) {
return;
}
Guide guide = book.getGuide();
NodeList guideReferences = guideElement
.getElementsByTagNameNS(NAMESPACE_OPF, OPFTags.reference);
for (int i = 0; i < guideReferences.getLength(); i++) {
Element referenceElement = (Element) guideReferences.item(i);
String resourceHref = DOMUtil
.getAttribute(referenceElement, NAMESPACE_OPF, OPFAttributes.href);
@ -400,23 +400,24 @@ public class PackageDocumentReader extends PackageDocumentBase {
return result;
}
/**
* Finds the cover resource in the packageDocument and adds it to the book if found.
* Keeps the cover resource in the resources map
* @param packageDocument s
* @param book x
*/
private static void readCover(Document packageDocument, Book book) {
Collection<String> coverHrefs = findCoverHrefs(packageDocument);
for (String coverHref : coverHrefs) {
Resource resource = book.getResources().getByHref(coverHref);
if (resource == null) {
Log.e(TAG,"Cover resource " + coverHref + " not found");
continue;
}
if (resource.getMediaType() == MediaTypes.XHTML) {
book.setCoverPage(resource);
/**
* Finds the cover resource in the packageDocument and adds it to the book if found.
* Keeps the cover resource in the resources map
*
* @param packageDocument s
* @param book x
*/
private static void readCover(Document packageDocument, EpubBook book) {
Collection<String> coverHrefs = findCoverHrefs(packageDocument);
for (String coverHref : coverHrefs) {
Resource resource = book.getResources().getByHref(coverHref);
if (resource == null) {
Log.e(TAG, "Cover resource " + coverHref + " not found");
continue;
}
if (resource.getMediaType() == MediaTypes.XHTML) {
book.setCoverPage(resource);
} else if (MediaTypes.isBitmapImage(resource.getMediaType())) {
book.setCoverImage(resource);
}

@ -2,8 +2,15 @@ package me.ag2s.epublib.epub;
import android.util.Log;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import me.ag2s.epublib.Constants;
import me.ag2s.epublib.domain.Book;
import me.ag2s.epublib.domain.EpubBook;
import me.ag2s.epublib.domain.Guide;
import me.ag2s.epublib.domain.GuideReference;
import me.ag2s.epublib.domain.MediaTypes;
@ -12,13 +19,6 @@ import me.ag2s.epublib.domain.Spine;
import me.ag2s.epublib.domain.SpineReference;
import me.ag2s.epublib.util.StringUtil;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.xmlpull.v1.XmlSerializer;
/**
* Writes the opf package document as defined by namespace http://www.idpf.org/2007/opf
*
@ -29,7 +29,7 @@ public class PackageDocumentWriter extends PackageDocumentBase {
private static final String TAG = PackageDocumentWriter.class.getName();
public static void write(EpubWriter epubWriter, XmlSerializer serializer,
Book book) {
EpubBook book) {
try {
serializer.startDocument(Constants.CHARACTER_ENCODING, false);
serializer.setPrefix(PREFIX_OPF, NAMESPACE_OPF);
@ -66,7 +66,7 @@ public class PackageDocumentWriter extends PackageDocumentBase {
* @throws IllegalArgumentException 1@throws XMLStreamException
*/
@SuppressWarnings("unused")
private static void writeSpine(Book book, EpubWriter epubWriter,
private static void writeSpine(EpubBook book, EpubWriter epubWriter,
XmlSerializer serializer)
throws IllegalArgumentException, IllegalStateException, IOException {
serializer.startTag(NAMESPACE_OPF, OPFTags.spine);
@ -93,7 +93,7 @@ public class PackageDocumentWriter extends PackageDocumentBase {
}
private static void writeManifest(Book book, EpubWriter epubWriter,
private static void writeManifest(EpubBook book, EpubWriter epubWriter,
XmlSerializer serializer)
throws IllegalArgumentException, IllegalStateException, IOException {
serializer.startTag(NAMESPACE_OPF, OPFTags.manifest);
@ -102,7 +102,7 @@ public class PackageDocumentWriter extends PackageDocumentBase {
//For EPUB3
if (book.isEpub3()) {
serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.properties,NCXDocumentV3.V3_NCX_PROPERTIES);
serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.properties, NCXDocumentV3.V3_NCX_PROPERTIES);
serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.id, NCXDocumentV3.NCX_ITEM_ID);
serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.href, NCXDocumentV3.DEFAULT_NCX_HREF);
serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.media_type, NCXDocumentV3.V3_NCX_MEDIATYPE.getName());
@ -124,7 +124,7 @@ public class PackageDocumentWriter extends PackageDocumentBase {
serializer.endTag(NAMESPACE_OPF, OPFTags.manifest);
}
private static List<Resource> getAllResourcesSortById(Book book) {
private static List<Resource> getAllResourcesSortById(EpubBook book) {
List<Resource> allResources = new ArrayList<>(
book.getResources().getAll());
Collections.sort(allResources, (resource1, resource2) -> resource1.getId().compareToIgnoreCase(resource2.getId()));
@ -134,13 +134,13 @@ public class PackageDocumentWriter extends PackageDocumentBase {
/**
* Writes a resources as an item element
*
* @param resource g
* @param resource g
* @param serializer g
* @throws IOException g
* @throws IllegalStateException g
* @throws IOException g
* @throws IllegalStateException g
* @throws IllegalArgumentException 1@throws XMLStreamException
*/
private static void writeItem(Book book, Resource resource,
private static void writeItem(EpubBook book, Resource resource,
XmlSerializer serializer)
throws IllegalArgumentException, IllegalStateException, IOException {
if (resource == null ||
@ -204,7 +204,7 @@ public class PackageDocumentWriter extends PackageDocumentBase {
}
}
private static void writeGuide(Book book, EpubWriter epubWriter,
private static void writeGuide(EpubBook book, EpubWriter epubWriter,
XmlSerializer serializer)
throws IllegalArgumentException, IllegalStateException, IOException {
serializer.startTag(NAMESPACE_OPF, OPFTags.guide);

Loading…
Cancel
Save