Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何直接从流中读取二进制数组?_C#_Arrays - Fatal编程技术网

C# 如何直接从流中读取二进制数组?

C# 如何直接从流中读取二进制数组?,c#,arrays,C#,Arrays,这里的“直接”是指没有临时字节[]数组 问题是,例如,我在磁盘上有一个int或double数组,所以目前我创建了两个数组--字节数组和int数组(在int的情况下)。前者仅用于阅读,后者是实际输出 由于流只能读取字节数组,因此我将其读取到第一个数组,然后将所有数据复制到第二个数组。它是有效的,但它真的伤害了我(我不是在这里谈论性能) 那么,如何在没有临时数组的情况下读取数组呢?使用C#不安全的上下文对我来说很好 到目前为止,我尝试了两种方法:我看是否有可能创建一个重用分配内存的数组,第二种方法看

这里的“直接”是指没有临时
字节[]
数组

问题是,例如,我在磁盘上有一个
int
double
数组,所以目前我创建了两个数组--
字节
数组和
int
数组(在
int
的情况下)。前者仅用于阅读,后者是实际输出

由于
只能读取
字节
数组,因此我将其读取到第一个数组,然后将所有数据复制到第二个数组。它是有效的,但它真的伤害了我(我不是在这里谈论性能)

那么,如何在没有临时数组的情况下读取数组呢?使用C#
不安全的
上下文对我来说很好

到目前为止,我尝试了两种方法:我看是否有可能创建一个重用分配内存的数组,第二种方法看起来更有希望——我可以得到指向结果/秒数组的指针,在不安全的上下文中,我可以将它转换为
字节*
指针。考虑到我的需要,它是100%安全和有效的,但是
byte*
指针在C#world中不是
byte[]
数组,我找不到将指针投射到数组的方法

代码:


据我所知,无法将数据直接从流复制到类型化数组。但是,您可以分块处理数据,将内存开销限制在固定的范围内。记忆将被复制两次,但据我所知,这是不可避免的

例如:

            public static void ReadArrayDataChunked(BinaryReader binaryReader, Array target, Type type, int bufferSize = 4096)
    {
        var buffer = new byte[bufferSize];
        var tSize = Marshal.SizeOf(type) ;

        var remainingBytes = target.Length * tSize;
        var targetPosition = 0;
        while (remainingBytes > 0)
        {
            var toRead = Math.Min(remainingBytes, buffer.Length);
            var bytesRead = binaryReader.Read(buffer, 0, toRead);
            Buffer.BlockCopy(buffer, 0, target, targetPosition, bytesRead);
            targetPosition += bytesRead;
            remainingBytes -= bytesRead;
        }
    }

请注意,由于块复制,这仅适用于基本类型,但这有助于提高复制性能。您需要逐项读取其他类型。

No。使用read()方法读取所需的字节数,并将其放入字节[]。您不需要读取整个流直到结束。在阅读之前,您可以检查流的位置和长度,以确保流中有足够的数据。您的问题不清楚。仅用您请求的字节填充可重用缓冲区。所以不涉及临时数组。如果您有很多并发操作,并且担心即使是这些缓冲区也会损害性能,那么您可以使用一个跨流重用相同的缓冲区。您当然不需要字节指针。如果您不想复制数组,可以使用
Span
@astrowalker,您可能应该发布代码而不是描述it@astrowalker所有语言、所有运行时、所有操作系统都是这样工作的。当您在C中使用
字节*
时,您也会这样工作。有人分配了那个数组。由于每次都使用相同的缓冲区,因此即使是单个流也不会产生浪费或额外的GC。MemoryPool在需要跨数千条流保存内存时使用,例如当您拥有高流量web服务时。那么,真正的问题是什么?为什么要看
字节*
?如果您想避免复制,请使用
Stream.Read(Span)
BinaryReader
可用于从流的一部分读取整数和字节是的,谢谢,看起来我最终遵循了这条路径,因为我没有看到将我的“外部”需求(如双数组)与流API需求(字节数组)连接起来的粘合剂。如果您有一个
double[]
并且想要一个
byte[]
或者反之亦然,您可以直接执行块复制,无需流来执行。我的数据(double)在磁盘上,因此我首先需要流来读取它们。
            public static void ReadArrayDataChunked(BinaryReader binaryReader, Array target, Type type, int bufferSize = 4096)
    {
        var buffer = new byte[bufferSize];
        var tSize = Marshal.SizeOf(type) ;

        var remainingBytes = target.Length * tSize;
        var targetPosition = 0;
        while (remainingBytes > 0)
        {
            var toRead = Math.Min(remainingBytes, buffer.Length);
            var bytesRead = binaryReader.Read(buffer, 0, toRead);
            Buffer.BlockCopy(buffer, 0, target, targetPosition, bytesRead);
            targetPosition += bytesRead;
            remainingBytes -= bytesRead;
        }
    }