- go version go1.15.14 linux/amd64
- 相关项目地址为:点我跳转
最近在写一个golang实现的字符串搜索与替换程序练手,其中一个很大的问题就是程序不能识别二进制文件与文本文件,导致搜索出来的内容会乱码,非常的不雅观。如果再不小心替换一下的话,就会造成很大的影响,所以这个问题必须解决。
我简单看了一下相关的标准库函数,发现golang标准库内并没有提供相关的函数来实现分辨二进制文件的功能。于是学习了一下编码相关的知识来自己实现一个二进制文件判断的功能。
二、思路文本文件其实本质也是二进制文件,只不过可以被计算机内置的编码方式来解读为可阅读的文本。所以本文中需要解决的问题实质为如何识别出无法被正常编码的文件。
总所周知,ASCII为最初的编码方式,故基础字母数字和操作符都可以按照ASCII标准被编码。但是查看ASCII编码中的内容,可以发现其中一些内容是不可读的,比如编码为0-6的一些状态符。假如文件中出现了这类编码,那么肯定此文件不是正常的可读文本文件,即二进制文件。
32~127\\r(13)\\n(10)\\t(9)
128~25532~2550~31
故,主要的思路即为判定字节的内容,若存在非常规内容,即可进行判定。
三、实现32~255\\r(13)\\n(10)\\t(9)\\a
然后今天我抽空上网冲浪了一会,找到了一种更全面的算法(zlib的算法),本文中的最终版本识别二进制文件也是使用的这种算法,算法内容如下:
32~255\\r(13)\\n(10)\\t(9)\\a(7)\\b(8)\\v(11)\\f(12)sub(26)esc(27)0~614~31
算法主要就是上面那个,很简单,但是判定了空文件等若干情况。在此次的完善中,我规定的读取范围为前1024个字节,因为之前实现中100个字节有些少,但是全文读取又会影响效率,所以读取1024个字节。核心的判定算法更改为上文中的那个。代码如下:(github地址:点我跳转)
package detect
import (
"os"
"log"
"bufio"
)
func DetectBinary(path string) bool {
file, err := os.Open(path)
if err != nil {
┊ log.Printf("\\033[31merror : IO error - \\033[0m%s", err)
┊ return false
}
defer file.Close()
r := bufio.NewReader(file)
buf := make([]byte, 1024)
n, err := r.Read(buf)
var white_byte int = 0
for i := 0; i < n; i++ {
┊ if (buf[i] >= 0x20 && buf[i] <= 0xff) ||
┊ ┊ buf[i] == 9 ||
┊ ┊ buf[i] == 10 ||
┊ ┊ buf[i] == 13 {
┊ ┊ white_byte++
┊ } else if buf[i] <= 6 || (buf[i] >= 14 && buf[i] <= 31) {
┊ ┊ return true
┊ }
}
if white_byte >= 1 {
┊ return false
}
return true
}
如上即为实现,返回值为true即为二进制文件。就我进行的测试来看,可以很好的判定二进制文件。