Kotlin获取webm等格式文件魔数异常问题及解决方案
我尝试在Kotlin中实现文件魔数读取功能,但webm格式文件的读取结果始终不符合预期。
webm的标准魔数应为1A 45 DF A3,但我读取得到的结果是1A 45 7E3 FFFD,显然实现逻辑存在错误。使用HxD十六进制编辑器查看同一份文件可得到正确的1A 45 DF A3,可排除文件本身的问题。
测试用webm文件来自公开webm演示文件站点。
最初错误实现代码
#!/usr/bin/env kscript import java.io.File val files = arrayListOf<File>() files.add(File("big-buck-bunny_trailer.webm")) files.add(File("elephants-dream.webm")) for (file in files){ val buffered_reader = file.bufferedReader() var first_bytes: String = "" println("-".repeat(20)) println(file.name) println("-".repeat(20)) for (i in 1..5) { try { // readbyte val a = buffered_reader.read() println(a.toString() + "\t" + String.format("%02X ", a) + "\t" + String.format("%02X ", a and 0xFF) + "\t" + a.toChar()) first_bytes = first_bytes.plus(a) } catch (e:java.io.IOException) { println("Exception: "+e.localizedMessage) } } buffered_reader.close() }
执行kscript main.kts错误输出:
-------------------- big-buck-bunny_trailer.webm -------------------- 26 1A 1A 69 45 45 E 2019 7E3 E3 ߣ 65533 FFFD FD � 66 42 42 B -------------------- elephants-dream.webm -------------------- 26 1A 1A 69 45 45 E 2019 7E3 E3 ߣ 65533 FFFD FD � 66 42 42 B
改用InputStream的修正版脚本
#!/usr/bin/env kscript import java.io.File val files = arrayListOf<File>() files.add(File("big-buck-bunny_trailer.webm")) files.add(File("elephants-dream.webm")) for (file in files){ val input_stream = file.inputStream() var bytes_read = ByteArray(10) var first_bytes: String = "" input_stream.read(bytes_read) println("-".repeat(20)) println(file.name) println("-".repeat(20)) for (byte in bytes_read) { try { println(byte.toString() + "\t" + String.format("%02X", byte) + "\t" + byte.toChar()) } catch (e:java.io.IOException) { println("Exception: "+e.localizedMessage) } } input_stream.close() }
执行kscript main.kts的正确输出:
-------------------- big-buck-bunny_trailer.webm -------------------- 26 1A 69 45 E -33 DF -93 A3 ᆪ -93 A3 ᆪ 66 42 B -122 86 ニ -127 81 チ 1 01 66 42 B -------------------- elephants-dream.webm -------------------- 26 1A 69 45 E -33 DF -93 A3 ᆪ -93 A3 ᆪ 66 42 B -122 86 ニ -127 81 チ 1 01 66 42 B
优化十六进制值打印的版本(适配音视频、图片格式校验场景)
#!/usr/bin/env kscript import java.io.File val files = arrayListOf<File>() files.add(File("big-buck-bunny_trailer.webm")) files.add(File("elephants-dream.webm")) for (file in files){ val input_stream = file.inputStream() var bytes_read = ByteArray(10) var first_bytes: String = "" input_stream.read(bytes_read) println("-".repeat(20)) println(file.name) println("-".repeat(20)) first_bytes = bytes_read.joinToString(separator=" ", transform = { byte: Byte -> String.format("%02X",byte) }) println(first_bytes) input_stream.close() }
输出结果:
-------------------- big-buck-bunny_trailer.webm -------------------- 1A 45 DF A3 A3 42 86 81 01 42 -------------------- elephants-dream.webm -------------------- 1A 45 DF A3 A3 42 86 81 01 42
最终实现的多格式魔数判断逻辑:
if (first_bytes.contains("66 74 79 70 69 73") || first_bytes.contains("66 74 79 70 6D 70")) { type = "mp4" } else if (first_bytes.contains("66 74 79 70 4D 34")) { type = "m4v" } else if (first_bytes.contains("66 74 79 70 71 74")) { type = "mov" } else if (first_bytes.startsWith("89 50 4E 47 0D 0A 1A 0A")) { type = "png" } else if (first_bytes.startsWith("47 49 46 38 3")) { type = "gif" } else if (first_bytes.startsWith("FF D8 FF")) { type = "jpg" } else if (first_bytes.startsWith("52 49 46 46") && first_bytes.endsWith("57 45 42 50")) { type = "webp" } else if (first_bytes.startsWith("1A 45 DF A3")) { type = "webm" } else { type = "unknown" }
内容的提问来源于stack exchange,提问作者Daviid
相关产品推荐
相关产品推荐

