分享我的解决方案,希望它可以帮助其他人,因为它可以从这些帖子和论坛中帮助我。
背景
我一直在研究和探索相同的解决方案。但是,我希望它是简单的或稍微扭曲的。
但是,大多数尝试在这里以及其他来源提供了复杂的解决方案,并深入研究了 Unicode、UTF-series、BOM、编码、字节顺序。在这个过程中,我也走上了越野路,也进入了Ascii Tables and Code pages。
无论如何,我已经想出了一个基于流阅读器和自定义控制字符检查的想法的解决方案。
它的构建考虑了论坛和其他地方提供的各种提示和技巧,例如:
- 检查大量控制字符,例如查找多个连续的空字符。
- 检查 UTF、Unicode、编码、BOM、字节顺序和类似方面。
我的目标是:
- 不应依赖字节顺序、编码和其他更多涉及深奥的工作。
- 应该相对容易实现和理解。
- 它应该适用于所有类型的文件。
我提出的解决方案适用于测试数据,包括 mp3、eml、txt、info、flv、mp4、pdf、gif、png、jpg。到目前为止,它给出了预期的结果。
解决方案的工作原理
我依靠StreamReader default constructor 来做它在确定默认使用UTF8Encoding 的文件编码相关特征方面做得最好的事情。
我创建了自己的自定义控件字符条件检查版本,因为Char.IsControl 似乎没有用。它说:
控制字符是格式化和其他非打印字符,
如 ACK、BEL、CR、FF、LF 和 VT。 Unicode 标准分配代码
从 \U0000 到 \U001F、\U007F 以及从 \U0080 到 \U009F 到
控制字符。这些值将被解释为控制
字符,除非它们的使用由应用程序另行定义。它
除其他外,将 LF 和 CR 视为控制字符
因为文本文件至少包含 CR 和 LF,所以它没有用处。
解决方案
static void testBinaryFile(string folderPath)
{
List<string> output = new List<string>();
foreach (string filePath in getFiles(folderPath, true))
{
output.Add(isBinary(filePath).ToString() + " ---- " + filePath);
}
Clipboard.SetText(string.Join("\n", output), TextDataFormat.Text);
}
public static List<string> getFiles(string path, bool recursive = false)
{
return Directory.Exists(path) ?
Directory.GetFiles(path, "*.*",
recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly).ToList() :
new List<string>();
}
public static bool isBinary(string path)
{
long length = getSize(path);
if (length == 0) return false;
using (StreamReader stream = new StreamReader(path))
{
int ch;
while ((ch = stream.Read()) != -1)
{
if (isControlChar(ch))
{
return true;
}
}
}
return false;
}
public static bool isControlChar(int ch)
{
return (ch > Chars.NUL && ch < Chars.BS)
|| (ch > Chars.CR && ch < Chars.SUB);
}
public static class Chars
{
public static char NUL = (char)0; // Null char
public static char BS = (char)8; // Back Space
public static char CR = (char)13; // Carriage Return
public static char SUB = (char)26; // Substitute
}
如果您尝试上述解决方案,请告诉我它是否适合您。
其他有趣的相关链接: