gpt4 book ai didi

java - 如何为 zip 存档编写 FileTypeDetector?

转载 作者:搜寻专家 更新时间:2023-10-30 23:02:48 24 4
gpt4 key购买 nike

对于 this package ,我接下来的步骤之一是编写一系列 FileTypeDetector有方法 Files.probeContentType()比默认情况下更智能(默认提供的文件类型检测器仅依赖于“文件扩展名”)。

正如上述方法的 javadoc 提到的,此方法依赖于 META-INF/services 文件中声明的 FileTypeDetector 实例。

我首先使用一个简单的提供程序进行测试,以使用文件头检测 PNG 文件:

public final class PngFileTypeDetector
extends FileTypeDetector
{
private static final byte[] PNG_HEADER = {
(byte) 0x89,
(byte) 0x50, (byte) 0x4E, (byte) 0x47,
(byte) 0x0D, (byte) 0x0A,
(byte) 0x1A,
(byte) 0x0A
};

private static final int PNG_HEADER_SIZE = PNG_HEADER.length;

@Override
public String probeContentType(final Path path)
throws IOException
{
final byte[] buf = new byte[PNG_HEADER_SIZE];

try (
final InputStream in = Files.newInputStream(path);
) {
if (in.read(buf) != PNG_HEADER_SIZE)
return null;
}

return Arrays.equals(buf, PNG_HEADER) ? "image/png" : null;
}
}

它有效。现在,在快速浏览了 API 之后,我认为这是检测文件是否为 zip 的好方法:

public final class ZipFileTypeDetector
extends FileTypeDetector
{
@Override
public String probeContentType(final Path path)
throws IOException
{
// Rely on what the JDK has to offer...
try (
final InputStream in = Files.newInputStream(path);
final ZipInputStream z = new ZipInputStream(in);
) {
z.getNextEntry();
return "application/zip";
} catch (ZipException ignored) {
return null;
}
}
}

META-INF/services/java.nio.file.spi.FileTypeDetector 的内容是这样的:

com.github.fge.filesystem.ftd.PngFileTypeDetector
com.github.fge.filesystem.ftd.ZipFileTypeDetector

在当前的测试中,它起作用了;对于 zip,我创建了一个空的 zip 文件,对于我使用的 PNG 测试 this image .

完整测试:

public final class FileTypeDetectorTest
{
private FileSystem fs;
private Path path;

@BeforeMethod
public void initfs()
throws IOException
{
fs = MemoryFileSystemBuilder.newLinux().build("testfs");
path = fs.getPath("/foo");
}

@DataProvider
public Iterator<Object[]> samples()
{
final List<Object[]> list = new ArrayList<>();

String resourcePath;
String mimeType;

resourcePath = "/ftd/sample.png";
mimeType = "image/png";
list.add(new Object[] { resourcePath, mimeType });

resourcePath = "/ftd/sample.zip";
mimeType = "application/zip";
list.add(new Object[] { resourcePath, mimeType });

return list.iterator();
}

@Test(dataProvider = "samples")
public void fileTypeDetectionTest(final String resourcePath,
final String mimeType)
throws IOException
{
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
final InputStream in
= FileTypeDetectorTest.class.getResourceAsStream(resourcePath);

if (in == null)
throw new IOException(resourcePath + " not found in classpath");

try (
final InputStream inref = in;
) {
Files.copy(inref, path);
}

assertThat(Files.probeContentType(path)).isEqualTo(mimeType);
}

@AfterMethod
public void closefs()
throws IOException
{
fs.close();
}
}

然而...

如果我反转服务文件中的实现列表,那么现在的文件是:

com.github.fge.filesystem.ftd.ZipFileTypeDetector
com.github.fge.filesystem.ftd.PngFileTypeDetector

然后 PNG 文件被检测为一个 zip 文件!

经过一些调试我注意到:

  • 将 PNG 作为 ZipInputStream 打开没有失败...
  • ... 和 .getNextEntry() 返回 null!

我本以为至少 .getNextEntry() 会抛出ZipException

为什么没有呢?如何可靠地检测文件是否为 zip?

进一步注意:这是针对 Path 的;因此任何 File 都不可用。

最佳答案

Why didn't it?

嗯,getNextEntry() 的 JavaDoc 说发生了 ZipExceptionIOException

if a ZIP file error has occurred

if an I/O error has occurred

分别。

基于这些非常有用的信息(咳咳),我们不能假设它会在遇到无效条目时抛出异常。

How can I detect reliably whether a file is a zip?

ZIP 文件格式规范,原来是PKZip,可以找到here .虽然这都是一本好书 :),请看一下第 4 节;特别是 4.3.16。它指定了所有 ZIP 文件(甚至是空文件)都有的“中央目录记录结束”。

关于java - 如何为 zip 存档编写 FileTypeDetector?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29880198/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com