对于this package,我接下来的步骤之一是编写一系列FileTypeDetector
以使方法Files.probeContentType()
比默认情况下更智能(默认提供的文件类型检测器)依赖于"文件扩展名"仅限)。
正如前面提到的方法的javadoc所提到的,这个方法依赖于在FileTypeDetector
文件中声明META-INF/services
的实例。
我首先使用简单的提供程序进行测试,以使用文件头检测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文件,对于我使用this image的PNG测试。
完整测试:
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();
}
}
...然而
如果我反转services文件中的实现列表,那么现在的文件是:
com.github.fge.filesystem.ftd.ZipFileTypeDetector
com.github.fge.filesystem.ftd.PngFileTypeDetector
然后PNG文件被检测为zip文件!
经过一些调试后,我注意到:
ZipInputStream
并没有失败...... .getNextEntry()
返回null!我预计至少 .getNextEntry()
会抛出ZipException
。
为什么没有?如何可靠地检测文件是否为zip?
进一步说明:这是Path
s;因此任何File
都无法使用。
答案 0 :(得分:0)
为什么没有?
嗯,getNextEntry()
的JavaDoc表示发生了ZipException
或IOException
,
如果发生ZIP文件错误
如果发生I / O错误
分别
根据这些非常有用的信息( cough ),我们无法做出任何假设,即如果遇到无效条目,它会抛出异常。
如何可靠地检测文件是否为zip?
可以找到最初为PKZip的ZIP文件格式规范here。虽然它读得很好:),看看第4节;特别是4.3.16。它指定&#34;中心目录记录的结尾&#34;,所有ZIP文件都有(甚至是空文件)。