我非常支持“先自己动手,然后寻找库解决方案”。幸运的是,这个案例就是这样。
您必须知道文件的“幻数”,即它的签名。
我举个例子来检测InputStream是否代表PNG文件。
PNG 签名是通过在 HEX 中附加以下内容组成的:
1) 错误检查字节
2) ASCII 格式的字符串“PNG”:
P - 0x50
N - 0x4E
G - 0x47
3)CR(回车)-0x0D
4) LF(换行)-0xA
5)SUB(替代)-0x1A
6) LF(换行)-0xA
所以,神奇的数字是
89 50 4E 47 0D 0A 1A 0A
137 80 78 71 13 10 26 10 (decimal)
-119 80 78 71 13 10 26 10 (in Java)
137 -> -119转换说明
N 位数可以用来表示2^N 不同的值。
对于 2^8=256 或 0..255 范围的字节(8 位)。
Java 考虑要签名的字节原语,因此范围是-128..127。
因此,137 被认为是被烧毁的并代表-119 = 137 - 256。
Koltin 中的示例
private fun InputStream.isPng(): Boolean {
val magicNumbers = intArrayOf(-119, 80, 78, 71, 13, 10, 26, 10)
val signatureBytes = ByteArray(magicNumbers.size)
read(signatureBytes, 0, signatureBytes.size)
return signatureBytes.map { it.toInt() }.toIntArray().contentEquals(magicNumbers)
}
当然,为了支持多种 MIME 类型,您必须以某种方式扩展此解决方案,如果您对结果不满意,请考虑使用一些库。