您的位置:首页 > 其它

检测一个文件是否为文本文件/二进制文件的方法

2007-08-28 15:26 483 查看
判断一个文件是否为文本文件,最简单的方法是使用UE或者editplus之类的文本编辑器打开看看,如果没有明显的乱码且代码页正确,则可以判定是文本文件(多简单阿,有眼睛的都能看出来),但是如果需要程序判断的话怎么办呢?

有几种方法可以考虑

一. 判断不可见字符

我们知道,一般文本文件中是不会带有除空白字符之外的控制符号的,我们可以检测是否存在这些字符来判断是否为文本文件,例如文本中出现值为0的字符,或者值为255的字符,很明显不是文本文件,但是如果是Unicode编码或者中文字符(特别是繁体中文)呢? 还是不太好办。。。

二. 检索字符码表

既然控制字符无法完全解决该问题,那我们把常用编码的码表统计出来,找到码表中的有效区段,这样当文件中出现的所有字符都在这些区段范围时,该文件即可确定为文本文件了。

但是这种方法太猥琐了,还是baidu一下,google一会吧

三. 统计不可见字符

搜了一通后,发现有人说google有篇论文是采用统计不可见字符的方法实现的,不过没找到该文章所说的论文,所以自己随便实现了一下,结果表名有一些效果,统计的比率伐值控制好的话,应该是很实用很简单的一种办法。 在实验了一堆html文件之后信心大增,可是在接下来处理简单Unicode字符时却遇到了麻烦,这种文件中可能有N多的0。。。。。。

怎么对付Unicode文件呢? 继续搜索!

终于找到了识别Unicode的代码,用C#实现如下:

public bool CheckIsUniFile(byte[] header)
{
if (header.Length < 2)
return false;

bool flag = false;
if ((header[0] == 0xfe) && (header[1] == 0xff))
{
// Unicode,bigEndian
flag = true;
}
else if ((header[0] == 0xff) && (header[1] == 0xfe))
{
if (((header.Length >= 4) && (header[2] == 0)) && (header[3] == 0))
{
//UTF32
}
else
{
// UNICODE,littleEndian
}
flag = true;
}
else if (((header.Length >= 3) && (header[0] == 0xef)) && ((header[1] == 0xbb) && (header[2] == 0xbf)))
{
// UTF8
flag = true;
}
else if ((((header.Length >= 4) && (header[0] == 0)) && ((header[1] == 0) && (header[2] == 0xfe))) && (header[3] == 0xff))
{
//UTF32,bigEndian
flag = true;
}

return flag;

//throw new System.NotImplementedException();
}

该函数需要传入2到4个字节的文件头标识,用来识别是否为Unicode文件的标志。

那么判定文件为文本文件的代码也比较好写了,代码为c#的实现:

/// <param name="strFilename">文件名</param>
public bool CheckIsTxtFile(string strFilename)
{
if (!File.Exists(strFilename))
return false;

int[] naCharVisible = new int[2]; // 可见字符统计表,[0] 表示可见个数,[1]表示不可见个数
byte[] header = new byte[4];

FileStream fs = File.OpenRead(strFilename);
byte[] buffer = new byte[1024];

int nReadCount = fs.Read(buffer, 0, 1024);
if (nReadCount >= 4)
{
header[0] = buffer[0];
header[1] = buffer[1];
header[2] = buffer[2];
header[3] = buffer[3];
}

for (int i = 0; i < nReadCount; i++)
{
byte item = buffer[i];
if (item < ' ')
{
naCharVisible[1]++;
//return false;
}
else
{
naCharVisible[0]++;
}
}

if (fs.Length > 1024)
{
fs.Seek(-1024, SeekOrigin.End);
}
nReadCount = fs.Read(buffer, 0, 1024);

for (int i = 0; i < nReadCount; i++)
{
byte item = buffer[i];
if (item < ' ')
{
naCharVisible[1]++;
//return false;
}
else
{
naCharVisible[0]++;
}
}

//throw new System.NotImplementedException();
if (naCharVisible[0] != 0 && naCharVisible[1] != 0)
{
int nRate = naCharVisible[0] * 100 / (naCharVisible[0] + naCharVisible[1]);
if ( nRate >= 93)
{
return true;
}
else if (nRate >= 60)
{
return CheckIsUniFile(header);
}
else
{
return false;
}
}
else if (naCharVisible[0] == 0)
{
return false;
}
else
{
return true;
}
}

文章基本写完了,最后要说的是如果检验结果不够精确,试着修改上面与nRate 比较的几个值,或者使用更有效的统计算法,希望本文对您有用!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: