我需要解析epub文件的内容,我正在尝试什么是最有效的方法。epub文件可能包含图像、大量文本,偶尔还会包含视频。我应该选择FileInputStream还是FileReader?
由于epub使用ZIP归档结构,我建议按此方式处理它。在下面找到一个小片段,列出epub文件的内容。
Map<String, String> env = new HashMap<>();
env.put("create", "true");
Path path = Paths.get("foobar.epub");
URI uri = URI.create("jar:" + path.toUri());
FileSystem zipFs = FileSystems.newFileSystem(uri, env);
Path root = zipFs.getPath("/");
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs) throws IOException {
print(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs) throws IOException {
print(dir);
return FileVisitResult.CONTINUE;
}
private void print(Path file) throws IOException {
Date lastModifiedTime = new Date(Files.getLastModifiedTime(file).toMillis());
System.out.printf("%td.%<tm.%<tY %<tH:%<tM:%<tS %9d %sn",
lastModifiedTime, Files.size(file), file);
}
});
样本输出
01.01.1970 00:59:59 0 /META-INF/
11.02.2015 16:33:44 244 /META-INF/container.xml
11.02.2015 16:33:44 3437 /logo.jpg
...
edit如果您只想根据文件的名称提取文件,您可以按照本代码段中visitFile(...)
方法所示的方式进行提取。
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs) throws IOException {
// if the filename inside the epub end with "*logo.jpg"
if (file.endsWith("logo.jpg")) {
// extract the file in directory /tmp/
Files.copy(file, Paths.get("/tmp/",
file.getFileName().toString()));
}
return FileVisitResult.CONTINUE;
}
根据您希望如何处理epub中的文件,您还可以查看ZipInputStream
。
try (ZipInputStream in = new ZipInputStream(new FileInputStream("foobar.epub"))) {
for (ZipEntry entry = in.getNextEntry(); entry != null;
entry = in.getNextEntry()) {
System.out.printf("%td.%<tm.%<tY %<tH:%<tM:%<tS %9d %sn",
new Date(entry.getTime()), entry.getSize(), entry.getName());
if (entry.getName().endsWith("logo.jpg")) {
try (FileOutputStream out = new FileOutputStream(entry.getName())) {
// process the file
}
}
}
}
样本输出
11.02.2013 16:33:44 244 META-INF/container.xml
11.02.2013 16:33:44 3437 logo.jpg
以字节形式读取整个文件的最简单方法(如果不是纯文本,那就是您想要的)是使用java.nio.file.Files
类:
byte[] content = Files.readAllBytes(Paths.get("example.epub"));
这种方法的优点:
- 更少的代码=代码可读性更强,出错的可能性更小
- java关心打开和关闭文件
编辑:
为了快速读取文件,您还可以使用java.nio
。这次java.nio.channels.FileChannel
:
import java.io.FileInputStream;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
// Load the file
FileChannel c = new FileInputStream("example.epub").getChannel();
MappedByteBuffer byteBuffer = c.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
// Process the data
buffer.get(myByte, 1120, 50);
// when finished
c.close();
这不会将整个文件读取到内存中,而是创建一个指向文件的链接,并只读取(缓冲)您试图访问的部分。它还将识别文件上的更改,并始终返回最新的内容。