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; return myCurrentPosition;
} }
public void reset() throws IOException {
setPosition(0);
}
public int read() throws IOException { public int read() throws IOException {
myCurrentPosition++; myCurrentPosition++;
if (myBytesReady == 0) { if (myBytesReady == 0) {
@ -77,19 +73,21 @@ final class MyBufferedInputStream extends InputStream {
public void skip(int n) throws IOException { public void skip(int n) throws IOException {
myCurrentPosition += n; myCurrentPosition += n;
while (n > 0) { if (myBytesReady >= n) {
if (myBytesReady > n) { myBytesReady -= n;
myBytesReady -= n; myPositionInBuffer += n;
myPositionInBuffer += n; } else {
n = 0; n -= myBytesReady;
} else { myBytesReady = 0;
n -= myBytesReady;
myPositionInBuffer = 0; n -= myFileInputStream.skip(n);
myBytesReady = myFileInputStream.read(myBuffer); while (n > 0) {
if (myBytesReady <= 0) { int skipped = myFileInputStream.read(myBuffer, 0, n);
if (skipped <= 0) {
break; break;
} }
} n -= skipped;
}
} }
} }

View file

@ -4,18 +4,16 @@ import java.io.*;
import java.util.Collection; import java.util.Collection;
import java.util.Queue; import java.util.Queue;
import java.util.LinkedList; 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 String myFileName;
private final TreeMap<String,LocalFileHeader> myFileHeaders = new TreeMap<String,LocalFileHeader>(); private final LinkedHashMap<String,LocalFileHeader> myFileHeaders = new LinkedHashMap<String,LocalFileHeader>();
private final MyBufferedInputStream myBaseStream;
private boolean myAllFilesAreRead; private boolean myAllFilesAreRead;
public ZipFile(String fileName) throws IOException { public ZipFile(String fileName) {
myFileName = fileName; myFileName = fileName;
myBaseStream = new MyBufferedInputStream(myFileName);
} }
public Collection<LocalFileHeader> headers() { public Collection<LocalFileHeader> headers() {
@ -27,27 +25,27 @@ public class ZipFile {
return myFileHeaders.values(); return myFileHeaders.values();
} }
private boolean readFileHeader(String fileToFind) throws IOException { private boolean readFileHeader(MyBufferedInputStream baseStream, String fileToFind) throws IOException {
int version2extract = myBaseStream.read2Bytes(); int version2extract = baseStream.read2Bytes();
int generalFlag = myBaseStream.read2Bytes(); int generalFlag = baseStream.read2Bytes();
int compressionMethod = myBaseStream.read2Bytes(); int compressionMethod = baseStream.read2Bytes();
myBaseStream.skip(8); baseStream.skip(8);
int compressedSize = myBaseStream.read4Bytes(); int compressedSize = baseStream.read4Bytes();
int uncompressedSize = myBaseStream.read4Bytes(); int uncompressedSize = baseStream.read4Bytes();
int fileNameSize = myBaseStream.read2Bytes(); int fileNameSize = baseStream.read2Bytes();
int extraField = myBaseStream.read2Bytes(); int extraField = baseStream.read2Bytes();
final String fileName = myBaseStream.readString(fileNameSize); final String fileName = baseStream.readString(fileNameSize);
myBaseStream.skip(extraField); baseStream.skip(extraField);
LocalFileHeader header = new LocalFileHeader(version2extract, generalFlag, LocalFileHeader header = new LocalFileHeader(version2extract, generalFlag,
compressionMethod, compressedSize, uncompressedSize, compressionMethod, compressedSize, uncompressedSize,
myBaseStream.offset(), fileName); baseStream.offset(), fileName);
myFileHeaders.put(fileName, header); myFileHeaders.put(fileName, header);
if (header.sizeIsKnown()) { if (header.sizeIsKnown()) {
myBaseStream.skip(compressedSize); baseStream.skip(compressedSize);
} else { } else {
findAndReadDescriptor(header); findAndReadDescriptor(baseStream, header);
} }
return fileName.equals(fileToFind); return fileName.equals(fileToFind);
} }
@ -58,47 +56,51 @@ public class ZipFile {
} }
myAllFilesAreRead = true; myAllFilesAreRead = true;
myBaseStream.reset(); MyBufferedInputStream baseStream = getBaseStream();
baseStream.setPosition(0);
myFileHeaders.clear(); myFileHeaders.clear();
while (true) { try {
int header = myBaseStream.read4Bytes(); while (true) {
if (header != LocalFileHeader.FILE_HEADER_SIGNATURE) { int header = baseStream.read4Bytes();
if (header == LocalFileHeader.FOLDER_HEADER_SIGNATURE) { if (header != LocalFileHeader.FILE_HEADER_SIGNATURE) {
break; // central directory, no more files if (header == LocalFileHeader.FOLDER_HEADER_SIGNATURE) {
} else { break; // central directory, no more files
throw new WrongZipFormatException( } else {
"readHeaders. Wrong signature found = " + header throw new WrongZipFormatException(
+ " at position " + myBaseStream.offset()); "readHeaders. Wrong signature found = " + header
+ " at position " + baseStream.offset());
}
} }
readFileHeader(baseStream, null);
} }
readFileHeader(null); } finally {
} storeBaseStream(baseStream);
myBaseStream.reset(); }
} }
/** /**
* Finds descriptor of the last header and installs sizes of files * 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) { while (true) {
int signature = 0; int signature = 0;
do { do {
int nextByte = myBaseStream.read(); int nextByte = baseStream.read();
if (nextByte < 0) { if (nextByte < 0) {
throw new IOException( throw new IOException(
"readFileHeaders. Unexpected end of file when looking for DataDescriptor"); "readFileHeaders. Unexpected end of file when looking for DataDescriptor");
} }
signature = ((signature << 8) & (0x0FFFFFFFF)) + (byte) nextByte; signature = ((signature << 8) & (0x0FFFFFFFF)) + (byte) nextByte;
} while (signature != LocalFileHeader.DATA_DESCRIPTOR_SIGNATURE); } while (signature != LocalFileHeader.DATA_DESCRIPTOR_SIGNATURE);
myBaseStream.skip(4); baseStream.skip(4);
int compressedSize = myBaseStream.read4Bytes(); int compressedSize = baseStream.read4Bytes();
int uncompressedSize = myBaseStream.read4Bytes(); int uncompressedSize = baseStream.read4Bytes();
if ((myBaseStream.offset() - header.OffsetOfLocalData - 16) == compressedSize) { if ((baseStream.offset() - header.OffsetOfLocalData - 16) == compressedSize) {
header.setSizes(compressedSize, uncompressedSize); header.setSizes(compressedSize, uncompressedSize);
break; break;
} else { } else {
myBaseStream.backSkip(12); baseStream.backSkip(12);
continue; continue;
} }
} }
@ -110,12 +112,13 @@ public class ZipFile {
myStoredStreams.add(baseStream); myStoredStreams.add(baseStream);
} }
synchronized private ZipInputStream createZipInputStream(LocalFileHeader header) throws IOException, WrongZipFormatException { synchronized MyBufferedInputStream getBaseStream() throws IOException {
MyBufferedInputStream baseStream = MyBufferedInputStream baseStream = myStoredStreams.poll();
myStoredStreams.isEmpty() ? return (baseStream != null) ? baseStream : new MyBufferedInputStream(myFileName);
new MyBufferedInputStream(myFileName) : }
myStoredStreams.poll();
return new ZipInputStream(this, baseStream, header); private ZipInputStream createZipInputStream(LocalFileHeader header) throws IOException, WrongZipFormatException {
return new ZipInputStream(this, header);
} }
public InputStream getInputStream(String entryName) throws IOException { public InputStream getInputStream(String entryName) throws IOException {
@ -133,25 +136,31 @@ public class ZipFile {
} }
} }
// ready to read fileheader // ready to read fileheader
do { MyBufferedInputStream baseStream = getBaseStream();
int signature = myBaseStream.read4Bytes(); baseStream.setPosition(0);
if (signature != LocalFileHeader.FILE_HEADER_SIGNATURE) { try {
if (signature == LocalFileHeader.FOLDER_HEADER_SIGNATURE) { do {
break; // central directory, no more files int signature = baseStream.read4Bytes();
} else { if (signature != LocalFileHeader.FILE_HEADER_SIGNATURE) {
throw new IOException( if (signature == LocalFileHeader.FOLDER_HEADER_SIGNATURE) {
"Wrong signature " + signature break; // central directory, no more files
+ " found at position " + myBaseStream.offset()); } else {
throw new IOException(
"Wrong signature " + signature
+ " found at position " + baseStream.offset());
}
}
} while (!readFileHeader(baseStream, entryName));
LocalFileHeader header = myFileHeaders.get(entryName);
if (header != null) {
try {
return createZipInputStream(header);
} catch (WrongZipFormatException e) {
} }
} }
} while (!readFileHeader(entryName)); } finally {
LocalFileHeader header = myFileHeaders.get(entryName); storeBaseStream(baseStream);
if (header != null) { }
try {
return createZipInputStream(header);
} catch (WrongZipFormatException e) {
}
}
return null; return null;
} }
} }

View file

@ -8,15 +8,13 @@ import java.util.Collections;
class ZipInputStream extends InputStream { class ZipInputStream extends InputStream {
private final ZipFile myParent; private final ZipFile myParent;
private final MyBufferedInputStream myBaseStream; private final MyBufferedInputStream myBaseStream;
private final LocalFileHeader myHeader;
private final Decompressor myDecompressor; private final Decompressor myDecompressor;
private boolean myIsClosed; 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; myParent = parent;
myBaseStream = baseStream; myBaseStream = parent.getBaseStream();
baseStream.setPosition(header.OffsetOfLocalData); myBaseStream.setPosition(header.OffsetOfLocalData);
myHeader = header;
myDecompressor = Decompressor.init(myBaseStream, header); 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.bookmodel.*;
import org.geometerplus.fbreader.formats.xhtml.XHTMLReader; import org.geometerplus.fbreader.formats.xhtml.XHTMLReader;
import org.geometerplus.fbreader.formats.util.MiscUtil;
import org.geometerplus.fbreader.constants.XMLNamespace; import org.geometerplus.fbreader.constants.XMLNamespace;
class Reference { class Reference {
@ -54,20 +55,8 @@ class OEBBookReader extends ZLXMLReaderAdapter implements XMLNamespace {
myModelReader = new BookReader(model); 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) { boolean readBook(String fileName) {
myFilePrefix = htmlDirectoryPrefix(fileName); myFilePrefix = MiscUtil.htmlDirectoryPrefix(fileName);
myIdToHref.clear(); myIdToHref.clear();
myHtmlFileNames.clear(); myHtmlFileNames.clear();
@ -86,8 +75,7 @@ class OEBBookReader extends ZLXMLReaderAdapter implements XMLNamespace {
final int len = myHtmlFileNames.size(); final int len = myHtmlFileNames.size();
for (int i = 0; i < len; ++i) { for (int i = 0; i < len; ++i) {
final String name = (String)myHtmlFileNames.get(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(); 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.zlibrary.core.xml.*;
import org.geometerplus.fbreader.bookmodel.*; import org.geometerplus.fbreader.bookmodel.*;
import org.geometerplus.fbreader.formats.util.MiscUtil;
public class XHTMLReader extends ZLXMLReaderAdapter { public class XHTMLReader extends ZLXMLReaderAdapter {
private static final HashMap ourTagActions = new HashMap(); private static final HashMap ourTagActions = new HashMap();
@ -132,18 +133,18 @@ public class XHTMLReader extends ZLXMLReaderAdapter {
return myPathPrefix; return myPathPrefix;
} }
public boolean readFile(String pathPrefix, String fileName, String referenceName) { public boolean readFile(String filePath, String referenceName) {
myModelReader.addHyperlinkLabel(referenceName); myModelReader.addHyperlinkLabel(referenceName);
fillTagTable(); fillTagTable();
myPathPrefix = pathPrefix; myPathPrefix = MiscUtil.htmlDirectoryPrefix(filePath);
myReferenceName = referenceName; myReferenceName = referenceName;
myPreformatted = false; myPreformatted = false;
myInsideBody = false; myInsideBody = false;
return read(pathPrefix + fileName); return read(filePath);
} }
/* /*

View file

@ -46,6 +46,17 @@ public class ZLFile {
private static final HashMap ourForcedFiles = new HashMap(); private static final HashMap ourForcedFiles = new HashMap();
private static HashMap<String,ZipFile> ourZipFileMap = new HashMap<String,ZipFile>(); 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) { public boolean removeFile(String path) {
File file = new File(path); File file = new File(path);
@ -211,15 +222,7 @@ public class ZLFile {
InputStream base = baseFile.getInputStream(); InputStream base = baseFile.getInputStream();
if (base != null) { if (base != null) {
if (0 != (baseFile.myArchiveType & ArchiveType.ZIP)) { if (0 != (baseFile.myArchiveType & ArchiveType.ZIP)) {
final String baseFileName = myPath.substring(0, index); ZipFile zf = getZipFile(myPath.substring(0, index));
ZipFile zf;
synchronized (ourZipFileMap) {
zf = ourZipFileMap.get(baseFileName);
if (zf == null) {
zf = new ZipFile(baseFileName);
ourZipFileMap.put(baseFileName, zf);
}
}
/* /*
ZipEntry entry = zf.getEntry(myPath.substring(index+1)); ZipEntry entry = zf.getEntry(myPath.substring(index+1));
stream = zf.getInputStream(entry); stream = zf.getInputStream(entry);

View file

@ -36,7 +36,7 @@ public class ZLZipDir extends ZLDir {
return ":"; return ":";
}; };
private static ArrayList EMPTY = new ArrayList(); private static final ArrayList EMPTY = new ArrayList();
public ArrayList collectSubDirs() { public ArrayList collectSubDirs() {
return EMPTY; return EMPTY;
}; };
@ -44,7 +44,7 @@ public class ZLZipDir extends ZLDir {
public ArrayList/*<String>*/ collectFiles() { public ArrayList/*<String>*/ collectFiles() {
ZipFile zf = null; ZipFile zf = null;
try { try {
zf = new ZipFile(myFile.getCanonicalPath()); zf = ZLFile.getZipFile(myFile.getCanonicalPath());
} catch (IOException e) { } catch (IOException e) {
} }
if (zf == null) { if (zf == null) {