StreamReader的原始文件字节,幻数检测

本文关键字:检测 字节 原始 文件 StreamReader | 更新日期: 2023-09-27 17:58:44

我试图区分"文本文件"answers"二进制"文件,因为我实际上想忽略内容"不可读"的文件。

我有一个文件,我相信是GZIP档案。我正在尝试通过检测幻数/文件签名来忽略这种文件。如果我在Notepad++中使用十六进制编辑器插件打开文件,我可以看到前三个十六进制代码是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从读取文件的结果中获得原始字节?

StreamReader的原始文件字节,幻数检测

您的代码试图将二进制缓冲区更改为字符串。字符串在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....
    }
}

用法(对于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();
}

你不能。StreamReader是用来读取文本的,而不是二进制的。直接使用Stream读取字节。在您的情况下为FileStream

要猜测一个文件是文本文件还是二进制文件,可以将第一个4K读取到byte[]中并进行解释。

顺便说一句,您试图将字符强制转换为字节。这在原则上是无效的。我建议您熟悉Encoding是什么:它是以语义正确的方式在字符和字节之间转换的唯一方法。