我可以使用FileReader读取包含图像、视频(比如epub文件)和文本的文件吗?建议这样做是否符合性能要求



我需要解析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();

这不会将整个文件读取到内存中,而是创建一个指向文件的链接,并只读取(缓冲)您试图访问的部分。它还将识别文件上的更改,并始终返回最新的内容。

相关内容