1
0
Fork 0
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:
Nikolay Pultsin 2009-03-27 08:19:19 +00:00
parent d68eebf52f
commit a1b19524a4
8 changed files with 145 additions and 112 deletions

View file

@ -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;
}
}
}

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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();

View 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);
}
}

View file

@ -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);
}
/*

View file

@ -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);

View file

@ -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) {