Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.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# 访问内存的底层数组<;T>;_C#_Arrays_Sonarqube_Buffer_Filestream - Fatal编程技术网

C# 访问内存的底层数组<;T>;

C# 访问内存的底层数组<;T>;,c#,arrays,sonarqube,buffer,filestream,C#,Arrays,Sonarqube,Buffer,Filestream,在我的应用程序中,我需要迭代文件的内容,以对文件中固定大小的块进行哈希。最终目标是实现Amazon Glacier的树散列算法,我几乎一字不差地从他们的文档中复制了代码 但是,当我通过SonarQube运行以下代码时,就会出现问题: byte[]buff=新字节[Mio]; int字节读取; 而((bytesRead=await inputStream.ReadAsync(buff,0,Mio))>0){ //处理读取的字节 } 我的while循环线路出现Roslyn问题。问题是“将'Read

在我的应用程序中,我需要迭代文件的内容,以对文件中固定大小的块进行哈希。最终目标是实现Amazon Glacier的树散列算法,我几乎一字不差地从他们的文档中复制了代码

但是,当我通过SonarQube运行以下代码时,就会出现问题:

byte[]buff=新字节[Mio];
int字节读取;
而((bytesRead=await inputStream.ReadAsync(buff,0,Mio))>0){
//处理读取的字节
}
我的
while
循环线路出现Roslyn问题。问题是“将'ReadAsync'方法调用更改为使用'Stream.ReadAsync(内存,CancellationToken)'重载”。根据描述,这是因为使用内存类的方法比使用基本数组的方法更有效

当类可以从端到端使用时,这可能是正确的。问题是,我需要将数据提供给
HashAlgorithm
ComputeHash
方法,而它们没有任何接受
内存的覆盖。这意味着我必须使用
内存
ToArray
方法来制作数据的副本。对我来说,这听起来不是很有效

我知道可以通过将现有数组传递给构造函数来创建
内存
实例,如下所示:

byte[]buff=新字节[Mio];
内存=新内存(buff);
int字节读取;
而((bytesRead=await inputStream.ReadAsync(内存))>0){
//使用'buff'访问字节
}
但是,文档不清楚传递给构造函数的数组是否实际用作
内存
实例的底层存储

因此,我的问题如下:

  • 如何将数据从
    内存
    直接馈送到
    哈希算法
    实例?我指的是从
    HashAlgorithm
    派生的类的任何实例,而不是具体的SHA256算法。我的实现不限于SHA256,这与Glacier实现不同
  • 存储在
    内存
    实例中的数据是否也可以在用于创建它的数组中访问
  • 是否有其他方法可以访问存储在
    内存中的数据作为数组而不复制
    实例
  • 否则,如何在SonarQube中消除外部问题(本例中为Roslyn警告)?我没有下拉菜单来改变它的状态,就像正常的声纳问题一样
编辑添加有关代码工作方式的其他信息: 这是第一部分,从文件中计算1Mio块的第一个散列

这些是上面的
while
循环的内容:


//类的构造函数
//该类实现IDisposable以正确处理算法字段
//构造函数是这样调用的
//`using TreeHash TreeHash=new TreeHash(System.Security.Cryptography.SHA512.Create())`
公共树hash(hashalgon算法){
该算法=algo;
}
//块散列生成循环
//树哈希算法的第一部分
字节[][]chunkHashes=新字节[numChunks][];
字节[]buff=新字节[Mio];
int字节读取;
int-idx=0;
而((bytesRead=await inputStream.ReadAsync(buff,0,Mio))>0){
ChunkHash[idx++]=this.ComputeHash(buff,字节读取);
}
//哈希算法的快速包装器
//也用于树哈希计算的第二部分
私有字节[]计算哈希(字节[]数据,整数计数)=>this.Algorithm.ComputeHash(数据,0,计数);

默认情况下,我使用散列算法的非固定版本,但我可能会切换到托管版本。如果需要,该方法可以变为非
异步

以下方法应该有效。它利用
MemoryPool
获取一个
IMemoryOwner
,我们可以用它来检索我们的暂存缓冲区。我们需要一个
内存
来传递给
ReadAsync
调用,因此我们传递
IMemoryOwner
的属性

然后,我们重新构造代码,以使用将
ReadOnlySpan
作为源,将
Span
作为目标的方法。我们会分配一个新的数组(而不是使用
ArrayPool
),因为您正在保存/存储数组

byte[][]chunkHashes=新字节[numChunks][];
使用var memory=MemoryPool.Shared.Rent(Mio);
int字节读取;
int-idx=0;
while((bytesRead=await inputStream.ReadAsync(memory.memory,CancellationToken.None))>0)
{ 
var tempBuff=新字节[(int)Math.天花(this.Algorithm.HashSize/8.0)];
if(this.Algorithm.TryComputeHash(memory.memory.Span[…bytesRead]/*1*/,tempBuff,out var hashwrite))
{
ChunkHash[idx++]=HashWrited==tempBuff.Length?tempBuff:tempBuff[…hashWrited]/*2*/;
} 
其他的
抛出新异常(“缓冲区不够大”);
}
对于源代码,我们传递
Memory
缓冲区的属性,该属性再次从
IMemoryOwner.Memory
属性检索。我们根据读取的字节数将其切片到适当的长度。作为目的地传递的
Span
必须至少是算法属性的大小,即散列所需的位(而不是字节)数。由于一个实现可能(尽管我认为不太可能)使用的大小不是8的倍数,因此,如果需要,我们可以将部门的大小限制为四舍五入。我们不需要调用
AsSpan
,因为有一个来自
t[]
的隐式转换

我相信*最终写入的字节数将始终与
HashSize
的长度相同。如果是,我们只需使用原始数组。否则,我们需要根据写入的哈希字节数将其切片到正确的长度

如果缓冲区不是l