将内存流转换为数组但仅采用指定数量的元素

Posted

技术标签:

【中文标题】将内存流转换为数组但仅采用指定数量的元素【英文标题】:Converting a memory stream to an array but taking only a specified number of elements 【发布时间】:2021-12-13 06:13:00 【问题描述】:

我对实现图像格式验证很感兴趣。 我正在获取一个输入文件(如 IFormFile),我想将其编码为字节,并将这些字节与 jpeg 和 png 等格式的起始字节进行比较。例如,如果文件的前两个字节等于 jpeg 的前两个字节,则该文件是 jpeg 图像。

附加的实现将整个文件转换为字节数组,这似乎是低效的:

        using var stream = new MemoryStream();
        file.CopyTo(stream);
        byte[] checkIfImage = stream.ToArray();

然后,我们将它与 jpeg 或 png 的字节进行比较。

        var png = new byte[]  137, 80 ;
        var jpeg = new byte[]  255, 216 ;

与其创建这个包含文件所有字节的大而低效的数组,我想创建一个只包含前两个字节的数组,这样比较会很有效。 但是,我不能简单地在.ToArray() 之后添加.Take(2) 或类似的东西。

我该怎么办?

谢谢!

【问题讨论】:

***.com/questions/45605748/find-bytes-from-an-offset 【参考方案1】:

只需使用stream.Read method

var firstBytes = new byte[2];
var nrBytesRead = filestream.Read(firstBytes);
if(nrBytesRead == firstBytes.Length)
    // do the comparison

binaryreader 之类的类也可能有用。将整个流读入内存可能很方便,但如果考虑性能或内存使用情况,通常应避免使用。

【讨论】:

【参考方案2】:

不管您在概念上或其他方面遇到的任何其他问题...由于您为MemoryStream分配,您不妨只使用GetBuffer 来访问底层数组。从那里你可以使用任何你喜欢的比较技术。

在此示例中,我使用 Memory<T>ReadOnlyMemory<T> 并使用 SequenceEqual 检查模式 (¯\_(ツ)_/¯)

给定

private static readonly (string Name, ReadOnlyMemory<byte> Pattern)[] _patterns =

   ("png", new byte[] 1, 2),
   ("jpj", new byte[] 1, 216),
;

用法

using var file = new MemoryStream(new byte[] 1, 2, 3, 4, 5);
using var stream = new MemoryStream();
file.CopyTo(stream);

var mem = stream.GetBuffer().AsMemory();

foreach (var (name, pattern) in _patterns) 
   if (pattern.Span.SequenceEqual(mem.Span(0,pattern.Span.Length)))
      Console.WriteLine("Found : " + name + ", " + Convert.ToHexString(pattern.Span));

输出

Found : png, 0102

免责声明 1 :如果您使用的是旧的和破败的 .net 框架,那么所有的赌注都没有了。你需要用数组和蜡笔来做这个

免责声明 2:这并不是世界上最伟大的代码,它只是一种致敬

【讨论】:

我知道如何进行比较。我感兴趣的是创建一个仅包含文件前两个字节的数组,而不是其所有字节。通过应用 GetBuffer(),我只能获取所有字节。我怎样才能只得到前两个字节?我正在尝试处理来自 POST 请求的图像。例如,对 GIF 的所有字节进行编码需要大量时间,这就是为什么我有兴趣只取其前 2 个字节并将其与 GIF 格式进行比较...... @TommyTom 不管你喜欢与否,你拥有的代码已经在分配内存流。 GetBuffer 和剩下的代码基本都是 0 成本和 0 分配 @TommyTom 如果您试图不将任何内容加载到内存中(包括您在代码中拥有的内存流),那么您需要提供将文件流保存在某处的其余代码,因此可以提供低分配变体(不包括原始代码中的内存流)

以上是关于将内存流转换为数组但仅采用指定数量的元素的主要内容,如果未能解决你的问题,请参考以下文章

将内存流拆分为 bytearray

C#字符串字节数组和内存流间的相互转换 - IT浪潮之巅

如何将 NAudio WaveStream 写入内存流?

如何使用内存流、NAudio 和 LameMP3 将音频 aiff 转换为 MP3

内存流中的 InvalidOperationException

下载网络文件,网络流转换为内存流