二进制文件比较工具:Beyond Compare,这是一款收费软件,免费试用30天。也可以找其它的二进制文件比较工具,这里主要是讲解二进制文件比较的作用。
今天在做一个文件分割的功能的时候,没什么思路,感觉用传统的IO类写起来还是比较麻烦的,后来看到NIO中的一些写法,用来分割文件还是挺不错的,而且NIO的效率还更高呢,示例代码如下:
fun main() {
val fullFile = File("C:\\Users\\Even\\Music\\222\\zfy667_2021_11_24_19_37_14.wav")
splitFile(fullFile)
}
fun splitFile(fullFile: File) {
val fileLength = fullFile.length()
val partCount = 3
var partIndex = 0
val avgSize = fileLength / partCount
val lastPartSize = fileLength - avgSize * (partCount - 1)
val wavChannel = FileInputStream(fullFile).channel
val part_01_file = File("${fullFile.absolutePath}.${partIndex++}")
val part_02_file = File("${fullFile.absolutePath}.${partIndex++}")
val part_03_file = File("${fullFile.absolutePath}.${partIndex}")
val part_01_channel = FileOutputStream(part_01_file).channel
val part_02_channel = FileOutputStream(part_02_file).channel
val part_03_channel = FileOutputStream(part_03_file).channel
wavChannel.transferTo(0, avgSize, part_01_channel)
wavChannel.transferTo(avgSize, avgSize, part_02_channel)
wavChannel.transferTo(avgSize * 2, lastPartSize, part_03_channel)
part_01_channel.close()
part_02_channel.close()
part_03_channel.close()
wavChannel.close()
}
如上代码,我把一个音频文件分成了3份,在IntelliJ IDEA中运行是没有问题的,分割后的文件再合并回一个音频文件的时候也是可以正常播放的。奇怪的是,在Android中,我是先录音,得到wav音频文件,然后调用上面的分割函数来分割文件,但是分割后的文件再合并时播放不了,我就奇怪了,一模一样的函数,为什么在Widnows中正常,在Android中就不正常了,真是百思不得其解。
解决方案就是:把Android中录制的音频和分割的音频保存到电脑中,然后用在电脑上把那个完整的音频以同样的方式分割一次,因为在电脑上分割的文件是正常的,所以就可以和在Android中分割的文件进行比较了,因为是音频文件,所以需要找二进制对比的工具,这里我就用到了Beyond Compare,运行界面如下:
如上图,点击16进制比较,点击后界面如下:
如上图,界面分成了左右两边,我们把需要比较的两个文件分别拖动到左右窗口,效果如下:
如上图,蓝色是光标所在的位置,红色显示的就是不同的数据,这样我们很容易就发现不同了,我发现就上面的3个字节有不同,其它都是一样的,我就很奇怪,为什么会出现这个情况,难道是NIO的类有Bug吗?而且分割出来的第二个子文件和第三个子文件进行二进制比较后发现是没问题的,所以锁定了范围,为什么那几个数据和正确答案不一样,我数了一下位置,那几个数据是保存wav数据大小的位置,然后才想起来,我在Android中,录音结束前会把文件头再写一次,因为在录音结束的时候才能知道数据有多长,想到这里再看相关的代码,问题就浮出水面了,如下:
EventBus.getDefault().post(Message.obtain(null, Whats.UPLOAD_WAV_FILE, wavFilePath));
mWavWriter.close();
mWavWriter = null;
这里,在调用close()函数的时候会把文件头再写一次,但是在之前有一行代码,它是发消息给另一个子线程去分割文件,在分割文件的时候,最后的文件头还没开始写,我们就开始分割了,所以导致出现了不一致的问题。