我试图区分"文本文件"和"二进制"文件,因为我有效地想忽略文件"不可读"内容。
我有一个我认为是GZIP档案的文件。我通过检测魔术数字/文件签名来忽略这种文件。如果我在Notepad ++中使用Hex编辑器插件打开文件,我可以看到前三个十六进制代码是1f 8b 08
。
但是如果我使用StreamReader
读取文件,我不知道如何获取原始字节..
using (var streamReader = new StreamReader(@"C:\file"))
{
char[] buffer = new char[10];
streamReader.Read(buffer, 0, 10);
var s = new String(buffer);
byte[] bytes = new byte[6];
System.Buffer.BlockCopy(s.ToCharArray(), 0, bytes, 0, 6);
var hex = BitConverter.ToString(bytes);
var otherhex = BitConverter.ToString(System.Text.Encoding.UTF8.GetBytes(s.ToCharArray()));
}
在using语句结束时,我有以下变量值:
hex: "1F-00-FD-FF-08-00"
otherhex: "1F-EF-BF-BD-08-00-EF-BF-BD-EF-BF-BD-0A-51-02-03"
两者都不以Notepad ++中显示的十六进制值开头。
是否可以通过StreamReader
来获取文件的原始字节?
答案 0 :(得分:7)
您的代码尝试将二进制缓冲区更改为字符串。字符串在NET中是Unicode,因此需要两个字节。你可以看到结果有点不可预测。
只需使用BinaryReader及其ReadBytes方法
即可using(FileStream fs = new FileStream(@"C:\file", FileMode.Open, FileAccess.Read))
{
using (var reader = new BinaryReader(fs, new ASCIIEncoding()))
{
byte[] buffer = new byte[10];
buffer = reader.ReadBytes(10);
if(buffer[0] == 31 && buffer[1] == 139 && buffer[2] == 8)
// you have a signature match....
}
}
答案 1 :(得分:4)
用法(对于pdf文件):
Assert.AreEqual("25504446", GetMagicNumbers(filePath, 4));
方法GetMagicNumbers:
private static string GetMagicNumbers(string filepath, int bytesCount)
{
// https://en.wikipedia.org/wiki/List_of_file_signatures
byte[] buffer;
using (var fs = new FileStream(filepath, FileMode.Open, FileAccess.Read))
using (var reader = new BinaryReader(fs))
buffer = reader.ReadBytes(bytesCount);
var hex = BitConverter.ToString(buffer);
return hex.Replace("-", String.Empty).ToLower();
}
答案 2 :(得分:2)
你做不到。 StreamReader
用于读取文本,而不是二进制文件。直接使用Stream
读取字节。在您的情况下FileStream
。
要猜测文件是文本还是二进制文件,您可以将第一个4K读入byte[]
并解释它。
顺便说一下,你试图将字符强制为字节。原则上这是无效的。我建议你熟悉Encoding
是什么:它是唯一的方式,以语义正确的方式在字符和字节之间进行转换。