我目前正在实现一个电子阅读器库(skyepub http://skyepub.net/)这要求我实现一个方法来检查 zipEntry 是否存在。在他们的演示版本中,解决方案很简单:
public boolean isExists(String baseDirectory,String contentPath) {
setupZipFile(baseDirectory,contentPath);
if (this.isCustomFont(contentPath)) {
String path = baseDirectory +"/"+ contentPath;
File file = new File(path);
return file.exists();
}
ZipEntry entry = this.getZipEntry(contentPath);
if (entry==null) return false;
else return true;
}
// Entry name should start without / like META-INF/container.xml
private ZipEntry getZipEntry(String contentPath) {
if (zipFile==null) return null;
String[] subDirs = contentPath.split(Pattern.quote(File.separator));
String corePath = contentPath.replace(subDirs[1], "");
corePath=corePath.replace("//", "");
ZipEntry entry = zipFile.getEntry(corePath.replace(File.separatorChar, '/'));
return entry;
}
正如您所看到的,您可以使用 O(1) 时间访问有问题的 ZipEntrygetZipEntry(contentPath);
但是,就我而言,我无法直接从文件系统读取 zip 文件(出于安全原因,必须从内存中读取)。ifExists
实现实际上是通过 zip 文件进行的一次一个条目,直到找到有问题的 zipEntry,以下是相关部分:
try {
final InputStream stream = dbUtil.getBookStream(bookEditionID);
if( stream == null) return null;
final ZipInputStream zip = new ZipInputStream(stream);
ZipEntry entry;
do {
entry = zip.getNextEntry();
if( entry == null) {
zip.close();
return null;
}
} while( !entry.getName().equals(zipEntryName));
} catch( IOException e) {
Log.e("demo", "Can't get content data for "+contentPath);
return null;
}
return data;
所以如果数据存在,ifExists
返回 true,如果为 null,则返回 false。
Question
有没有办法可以在 O(1) 时间内而不是 O(n) 时间内从整个 ZipInputStream 中找到有问题的 zip 条目?
Related
See this https://stackoverflow.com/questions/36768080/reading-a-decrypted-file-into-a-zipinputstream-truncates-first-file-sometimes问题
和this https://stackoverflow.com/a/36797263/766570 answer.