對於this package,我的下一步驟之一是編寫一系列FileTypeDetector
,以使方法Files.probeContentType()
比默認情況下更智能(默認提供的文件類型檢測器僅依賴於「文件擴展名」)。如何爲zip存檔編寫FileTypeDetector?
由於上述方法的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文件,用於我使用的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
s;因此任何東西File
都不可用。
這不是一個空的zip文件將作爲標題。 – fge
@fge你是對的,我已經更新了我的答案。 – pathfinderelite