mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-05 10:49:24 +02:00
more optimizations
git-svn-id: https://only.mawhrin.net/repos/FBReaderJ/trunk@899 6a642e6f-84f6-412e-ac94-c4a38d5a04b0
This commit is contained in:
parent
d68eebf52f
commit
a1b19524a4
8 changed files with 145 additions and 112 deletions
|
@ -30,10 +30,6 @@ final class MyBufferedInputStream extends InputStream {
|
|||
return myCurrentPosition;
|
||||
}
|
||||
|
||||
public void reset() throws IOException {
|
||||
setPosition(0);
|
||||
}
|
||||
|
||||
public int read() throws IOException {
|
||||
myCurrentPosition++;
|
||||
if (myBytesReady == 0) {
|
||||
|
@ -77,18 +73,20 @@ final class MyBufferedInputStream extends InputStream {
|
|||
|
||||
public void skip(int n) throws IOException {
|
||||
myCurrentPosition += n;
|
||||
while (n > 0) {
|
||||
if (myBytesReady > n) {
|
||||
if (myBytesReady >= n) {
|
||||
myBytesReady -= n;
|
||||
myPositionInBuffer += n;
|
||||
n = 0;
|
||||
} else {
|
||||
n -= myBytesReady;
|
||||
myPositionInBuffer = 0;
|
||||
myBytesReady = myFileInputStream.read(myBuffer);
|
||||
if (myBytesReady <= 0) {
|
||||
myBytesReady = 0;
|
||||
|
||||
n -= myFileInputStream.skip(n);
|
||||
while (n > 0) {
|
||||
int skipped = myFileInputStream.read(myBuffer, 0, n);
|
||||
if (skipped <= 0) {
|
||||
break;
|
||||
}
|
||||
n -= skipped;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,18 +4,16 @@ import java.io.*;
|
|||
import java.util.Collection;
|
||||
import java.util.Queue;
|
||||
import java.util.LinkedList;
|
||||
import java.util.TreeMap;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public class ZipFile {
|
||||
public final class ZipFile {
|
||||
private final String myFileName;
|
||||
private final TreeMap<String,LocalFileHeader> myFileHeaders = new TreeMap<String,LocalFileHeader>();
|
||||
private final MyBufferedInputStream myBaseStream;
|
||||
private final LinkedHashMap<String,LocalFileHeader> myFileHeaders = new LinkedHashMap<String,LocalFileHeader>();
|
||||
|
||||
private boolean myAllFilesAreRead;
|
||||
|
||||
public ZipFile(String fileName) throws IOException {
|
||||
public ZipFile(String fileName) {
|
||||
myFileName = fileName;
|
||||
myBaseStream = new MyBufferedInputStream(myFileName);
|
||||
}
|
||||
|
||||
public Collection<LocalFileHeader> headers() {
|
||||
|
@ -27,27 +25,27 @@ public class ZipFile {
|
|||
return myFileHeaders.values();
|
||||
}
|
||||
|
||||
private boolean readFileHeader(String fileToFind) throws IOException {
|
||||
int version2extract = myBaseStream.read2Bytes();
|
||||
int generalFlag = myBaseStream.read2Bytes();
|
||||
int compressionMethod = myBaseStream.read2Bytes();
|
||||
myBaseStream.skip(8);
|
||||
private boolean readFileHeader(MyBufferedInputStream baseStream, String fileToFind) throws IOException {
|
||||
int version2extract = baseStream.read2Bytes();
|
||||
int generalFlag = baseStream.read2Bytes();
|
||||
int compressionMethod = baseStream.read2Bytes();
|
||||
baseStream.skip(8);
|
||||
|
||||
int compressedSize = myBaseStream.read4Bytes();
|
||||
int uncompressedSize = myBaseStream.read4Bytes();
|
||||
int fileNameSize = myBaseStream.read2Bytes();
|
||||
int extraField = myBaseStream.read2Bytes();
|
||||
int compressedSize = baseStream.read4Bytes();
|
||||
int uncompressedSize = baseStream.read4Bytes();
|
||||
int fileNameSize = baseStream.read2Bytes();
|
||||
int extraField = baseStream.read2Bytes();
|
||||
|
||||
final String fileName = myBaseStream.readString(fileNameSize);
|
||||
myBaseStream.skip(extraField);
|
||||
final String fileName = baseStream.readString(fileNameSize);
|
||||
baseStream.skip(extraField);
|
||||
LocalFileHeader header = new LocalFileHeader(version2extract, generalFlag,
|
||||
compressionMethod, compressedSize, uncompressedSize,
|
||||
myBaseStream.offset(), fileName);
|
||||
baseStream.offset(), fileName);
|
||||
myFileHeaders.put(fileName, header);
|
||||
if (header.sizeIsKnown()) {
|
||||
myBaseStream.skip(compressedSize);
|
||||
baseStream.skip(compressedSize);
|
||||
} else {
|
||||
findAndReadDescriptor(header);
|
||||
findAndReadDescriptor(baseStream, header);
|
||||
}
|
||||
return fileName.equals(fileToFind);
|
||||
}
|
||||
|
@ -58,47 +56,51 @@ public class ZipFile {
|
|||
}
|
||||
myAllFilesAreRead = true;
|
||||
|
||||
myBaseStream.reset();
|
||||
MyBufferedInputStream baseStream = getBaseStream();
|
||||
baseStream.setPosition(0);
|
||||
myFileHeaders.clear();
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
int header = myBaseStream.read4Bytes();
|
||||
int header = baseStream.read4Bytes();
|
||||
if (header != LocalFileHeader.FILE_HEADER_SIGNATURE) {
|
||||
if (header == LocalFileHeader.FOLDER_HEADER_SIGNATURE) {
|
||||
break; // central directory, no more files
|
||||
} else {
|
||||
throw new WrongZipFormatException(
|
||||
"readHeaders. Wrong signature found = " + header
|
||||
+ " at position " + myBaseStream.offset());
|
||||
+ " at position " + baseStream.offset());
|
||||
}
|
||||
}
|
||||
readFileHeader(null);
|
||||
readFileHeader(baseStream, null);
|
||||
}
|
||||
} finally {
|
||||
storeBaseStream(baseStream);
|
||||
}
|
||||
myBaseStream.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds descriptor of the last header and installs sizes of files
|
||||
*/
|
||||
private void findAndReadDescriptor(LocalFileHeader header) throws IOException {
|
||||
private void findAndReadDescriptor(MyBufferedInputStream baseStream, LocalFileHeader header) throws IOException {
|
||||
while (true) {
|
||||
int signature = 0;
|
||||
do {
|
||||
int nextByte = myBaseStream.read();
|
||||
int nextByte = baseStream.read();
|
||||
if (nextByte < 0) {
|
||||
throw new IOException(
|
||||
"readFileHeaders. Unexpected end of file when looking for DataDescriptor");
|
||||
}
|
||||
signature = ((signature << 8) & (0x0FFFFFFFF)) + (byte) nextByte;
|
||||
} while (signature != LocalFileHeader.DATA_DESCRIPTOR_SIGNATURE);
|
||||
myBaseStream.skip(4);
|
||||
int compressedSize = myBaseStream.read4Bytes();
|
||||
int uncompressedSize = myBaseStream.read4Bytes();
|
||||
if ((myBaseStream.offset() - header.OffsetOfLocalData - 16) == compressedSize) {
|
||||
baseStream.skip(4);
|
||||
int compressedSize = baseStream.read4Bytes();
|
||||
int uncompressedSize = baseStream.read4Bytes();
|
||||
if ((baseStream.offset() - header.OffsetOfLocalData - 16) == compressedSize) {
|
||||
header.setSizes(compressedSize, uncompressedSize);
|
||||
break;
|
||||
} else {
|
||||
myBaseStream.backSkip(12);
|
||||
baseStream.backSkip(12);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -110,12 +112,13 @@ public class ZipFile {
|
|||
myStoredStreams.add(baseStream);
|
||||
}
|
||||
|
||||
synchronized private ZipInputStream createZipInputStream(LocalFileHeader header) throws IOException, WrongZipFormatException {
|
||||
MyBufferedInputStream baseStream =
|
||||
myStoredStreams.isEmpty() ?
|
||||
new MyBufferedInputStream(myFileName) :
|
||||
myStoredStreams.poll();
|
||||
return new ZipInputStream(this, baseStream, header);
|
||||
synchronized MyBufferedInputStream getBaseStream() throws IOException {
|
||||
MyBufferedInputStream baseStream = myStoredStreams.poll();
|
||||
return (baseStream != null) ? baseStream : new MyBufferedInputStream(myFileName);
|
||||
}
|
||||
|
||||
private ZipInputStream createZipInputStream(LocalFileHeader header) throws IOException, WrongZipFormatException {
|
||||
return new ZipInputStream(this, header);
|
||||
}
|
||||
|
||||
public InputStream getInputStream(String entryName) throws IOException {
|
||||
|
@ -133,18 +136,21 @@ public class ZipFile {
|
|||
}
|
||||
}
|
||||
// ready to read fileheader
|
||||
MyBufferedInputStream baseStream = getBaseStream();
|
||||
baseStream.setPosition(0);
|
||||
try {
|
||||
do {
|
||||
int signature = myBaseStream.read4Bytes();
|
||||
int signature = baseStream.read4Bytes();
|
||||
if (signature != LocalFileHeader.FILE_HEADER_SIGNATURE) {
|
||||
if (signature == LocalFileHeader.FOLDER_HEADER_SIGNATURE) {
|
||||
break; // central directory, no more files
|
||||
} else {
|
||||
throw new IOException(
|
||||
"Wrong signature " + signature
|
||||
+ " found at position " + myBaseStream.offset());
|
||||
+ " found at position " + baseStream.offset());
|
||||
}
|
||||
}
|
||||
} while (!readFileHeader(entryName));
|
||||
} while (!readFileHeader(baseStream, entryName));
|
||||
LocalFileHeader header = myFileHeaders.get(entryName);
|
||||
if (header != null) {
|
||||
try {
|
||||
|
@ -152,6 +158,9 @@ public class ZipFile {
|
|||
} catch (WrongZipFormatException e) {
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
storeBaseStream(baseStream);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,15 +8,13 @@ import java.util.Collections;
|
|||
class ZipInputStream extends InputStream {
|
||||
private final ZipFile myParent;
|
||||
private final MyBufferedInputStream myBaseStream;
|
||||
private final LocalFileHeader myHeader;
|
||||
private final Decompressor myDecompressor;
|
||||
private boolean myIsClosed;
|
||||
|
||||
public ZipInputStream(ZipFile parent, MyBufferedInputStream baseStream, LocalFileHeader header) throws IOException, WrongZipFormatException {
|
||||
public ZipInputStream(ZipFile parent, LocalFileHeader header) throws IOException, WrongZipFormatException {
|
||||
myParent = parent;
|
||||
myBaseStream = baseStream;
|
||||
baseStream.setPosition(header.OffsetOfLocalData);
|
||||
myHeader = header;
|
||||
myBaseStream = parent.getBaseStream();
|
||||
myBaseStream.setPosition(header.OffsetOfLocalData);
|
||||
myDecompressor = Decompressor.init(myBaseStream, header);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.geometerplus.zlibrary.core.image.ZLFileImage;
|
|||
|
||||
import org.geometerplus.fbreader.bookmodel.*;
|
||||
import org.geometerplus.fbreader.formats.xhtml.XHTMLReader;
|
||||
import org.geometerplus.fbreader.formats.util.MiscUtil;
|
||||
import org.geometerplus.fbreader.constants.XMLNamespace;
|
||||
|
||||
class Reference {
|
||||
|
@ -54,20 +55,8 @@ class OEBBookReader extends ZLXMLReaderAdapter implements XMLNamespace {
|
|||
myModelReader = new BookReader(model);
|
||||
}
|
||||
|
||||
private static String htmlDirectoryPrefix(String fileName) {
|
||||
ZLFile file = new ZLFile(fileName);
|
||||
String shortName = file.getName(false);
|
||||
String path = file.getPath();
|
||||
int index = -1;
|
||||
if ((path.length() > shortName.length()) &&
|
||||
(path.charAt(path.length() - shortName.length() - 1) == ':')) {
|
||||
index = shortName.lastIndexOf('/');
|
||||
}
|
||||
return path.substring(0, path.length() - shortName.length() + index + 1);
|
||||
}
|
||||
|
||||
boolean readBook(String fileName) {
|
||||
myFilePrefix = htmlDirectoryPrefix(fileName);
|
||||
myFilePrefix = MiscUtil.htmlDirectoryPrefix(fileName);
|
||||
|
||||
myIdToHref.clear();
|
||||
myHtmlFileNames.clear();
|
||||
|
@ -86,8 +75,7 @@ class OEBBookReader extends ZLXMLReaderAdapter implements XMLNamespace {
|
|||
final int len = myHtmlFileNames.size();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
final String name = (String)myHtmlFileNames.get(i);
|
||||
//System.out.println("parsing " + name);
|
||||
new XHTMLReader(myModelReader).readFile(myFilePrefix, name, name);
|
||||
new XHTMLReader(myModelReader).readFile(myFilePrefix + name, name);
|
||||
}
|
||||
|
||||
generateTOC();
|
||||
|
|
36
src/org/geometerplus/fbreader/formats/util/MiscUtil.java
Normal file
36
src/org/geometerplus/fbreader/formats/util/MiscUtil.java
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package org.geometerplus.fbreader.formats.util;
|
||||
|
||||
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
|
||||
|
||||
public class MiscUtil {
|
||||
public static String htmlDirectoryPrefix(String fileName) {
|
||||
ZLFile file = new ZLFile(fileName);
|
||||
String shortName = file.getName(false);
|
||||
String path = file.getPath();
|
||||
int index = -1;
|
||||
if ((path.length() > shortName.length()) &&
|
||||
(path.charAt(path.length() - shortName.length() - 1) == ':')) {
|
||||
index = shortName.lastIndexOf('/');
|
||||
}
|
||||
return path.substring(0, path.length() - shortName.length() + index + 1);
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ import org.geometerplus.zlibrary.core.library.ZLibrary;
|
|||
import org.geometerplus.zlibrary.core.xml.*;
|
||||
|
||||
import org.geometerplus.fbreader.bookmodel.*;
|
||||
import org.geometerplus.fbreader.formats.util.MiscUtil;
|
||||
|
||||
public class XHTMLReader extends ZLXMLReaderAdapter {
|
||||
private static final HashMap ourTagActions = new HashMap();
|
||||
|
@ -132,18 +133,18 @@ public class XHTMLReader extends ZLXMLReaderAdapter {
|
|||
return myPathPrefix;
|
||||
}
|
||||
|
||||
public boolean readFile(String pathPrefix, String fileName, String referenceName) {
|
||||
public boolean readFile(String filePath, String referenceName) {
|
||||
myModelReader.addHyperlinkLabel(referenceName);
|
||||
|
||||
fillTagTable();
|
||||
|
||||
myPathPrefix = pathPrefix;
|
||||
myPathPrefix = MiscUtil.htmlDirectoryPrefix(filePath);
|
||||
myReferenceName = referenceName;
|
||||
|
||||
myPreformatted = false;
|
||||
myInsideBody = false;
|
||||
|
||||
return read(pathPrefix + fileName);
|
||||
return read(filePath);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -47,6 +47,17 @@ public class ZLFile {
|
|||
private static final HashMap ourForcedFiles = new HashMap();
|
||||
private static HashMap<String,ZipFile> ourZipFileMap = new HashMap<String,ZipFile>();
|
||||
|
||||
static ZipFile getZipFile(String fileName) throws IOException {
|
||||
synchronized (ourZipFileMap) {
|
||||
ZipFile zf = ourZipFileMap.get(fileName);
|
||||
if (zf == null) {
|
||||
zf = new ZipFile(fileName);
|
||||
ourZipFileMap.put(fileName, zf);
|
||||
}
|
||||
return zf;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean removeFile(String path) {
|
||||
File file = new File(path);
|
||||
return file.delete();
|
||||
|
@ -211,15 +222,7 @@ public class ZLFile {
|
|||
InputStream base = baseFile.getInputStream();
|
||||
if (base != null) {
|
||||
if (0 != (baseFile.myArchiveType & ArchiveType.ZIP)) {
|
||||
final String baseFileName = myPath.substring(0, index);
|
||||
ZipFile zf;
|
||||
synchronized (ourZipFileMap) {
|
||||
zf = ourZipFileMap.get(baseFileName);
|
||||
if (zf == null) {
|
||||
zf = new ZipFile(baseFileName);
|
||||
ourZipFileMap.put(baseFileName, zf);
|
||||
}
|
||||
}
|
||||
ZipFile zf = getZipFile(myPath.substring(0, index));
|
||||
/*
|
||||
ZipEntry entry = zf.getEntry(myPath.substring(index+1));
|
||||
stream = zf.getInputStream(entry);
|
||||
|
|
|
@ -36,7 +36,7 @@ public class ZLZipDir extends ZLDir {
|
|||
return ":";
|
||||
};
|
||||
|
||||
private static ArrayList EMPTY = new ArrayList();
|
||||
private static final ArrayList EMPTY = new ArrayList();
|
||||
public ArrayList collectSubDirs() {
|
||||
return EMPTY;
|
||||
};
|
||||
|
@ -44,7 +44,7 @@ public class ZLZipDir extends ZLDir {
|
|||
public ArrayList/*<String>*/ collectFiles() {
|
||||
ZipFile zf = null;
|
||||
try {
|
||||
zf = new ZipFile(myFile.getCanonicalPath());
|
||||
zf = ZLFile.getZipFile(myFile.getCanonicalPath());
|
||||
} catch (IOException e) {
|
||||
}
|
||||
if (zf == null) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue