提问人:notarobot 提问时间:2/25/2023 最后编辑:notarobot 更新时间:2/25/2023 访问量:130
从 BufferedStream.Read() 返回的字节数组是否有可能具有不同的长度?
Is it possible for byte arrays, returned from BufferedStream.Read(), to have different lengths?
问:
我们的 repo 中有这个旧代码:
bool BufferByteCompareFiles(string filePath1, string filePath2)
{
int bufferCapacity = 0x400000;
var firstFile = File.OpenRead(filePath1);
var secondFile = File.OpenRead(filePath2);
using var firstStream = new BufferedStream(firstFile);
using var secondStream = new BufferedStream(secondFile);
if (firstFile.Length != secondFile.Length)
return false;
var firstBuffer = new byte[bufferCapacity];
var secondBuffer = new byte[bufferCapacity];
int bytesReadFirst;
int bytesReadSecond;
do
{
bytesReadFirst = firstStream.Read(firstBuffer, 0, firstBuffer.Length);
bytesReadSecond = secondStream.Read(secondBuffer, 0, secondBuffer.Length);
if (bytesReadFirst != bytesReadSecond || !CompareByteArrays(firstBuffer, secondBuffer))
return false;
} while (bytesReadFirst > 0 && bytesReadSecond > 0);
return true;
}
static bool CompareByteArrays(byte[] first, byte[] second)
=> first.Length == second.Length && Interop.memcmp(first, second, first.Length) == 0;
我不明白的部分是,当已经有一个语句检查 if 和那些 int 是 读取的字节数时,为什么要检查字节数组长度。CompareByteArrays
if
bytesReadFirst != bytesReadSecond
BufferedStream.Read()
我是否遗漏了什么,或者可以省略整个内容?first.Length == second.Length
答:
1赞
Marc Gravell
2/25/2023
#1
坦率地说,该代码完全是错误的。这是两个不同的测试:
- 第一个测试检查每次调用中读取的量是否相同; 没有定义它将返回的内容 - 给定一个带有 和 的缓冲区,并且可以返回
Read
Read
Read
offset
count
- 0,对于 EOF 方案
- 如果某些数据可用,则为 1 和(含)之间的任何数字(不需要填充字节;任何方便都可以)
count
count
- 或抛出异常
- 第二个测试检查数组的大小是否相同;这是一个非常不同的问题
然而,由于 ,测试本身是注定要失败的;我们这里有一个巨大的缓冲区(太大了,IMO);返回 3 和返回 42 是完全有效的,这绝对不会告诉您有效负载是否相同 - 您必须继续读取两个流并比较两个流中可用的交叉字节数。最简单的方法是每次都填充两个缓冲区,即1
firstStream.Read
secondStream.Read
static ReadOnlySpan<byte> ReadAsMuchAsPossible(Stream stream, byte[] buffer)
{
int read, totalRead = 0;
while (totalRead < buffer.Length && (read = stream.Read(buffer, totalRead, buffer.Length - totalRead)) > 0)
{
totalRead += read;
}
return new ReadOnlySpan<byte>(buffer, 0, totalRead);
}
// ... loop over the streams, with, per iteration
Debug.Assert(firstBuffer.Length == secondBuffer.Length);
var firstChunk = ReadAsMuchAsPossible(firstStream, firstBuffer);
var secondChunk = ReadAsMuchAsPossible(secondStream, secondBuffer);
bool chunkSame = firstChunk.SequenceEqual(secondChunk);
让运行时担心优化跨度比较
评论
0赞
notarobot
2/26/2023
等。。。我刚刚意识到比较数组大小。那么,这不会总是正确的,因为两个数组都是以相同的大小创建的?返回不同的数字怎么不能告诉我任何事情?我正在测试文件是否相同,逐字节。因此,如果返回两个不同的数字,则一个字节流较短,因此不相等。此外,呼叫已经推进了导引头,或者无论它被调用什么,第二次调用它,偏移量为 0 将从第一次调用中断的地方开始读取。first.Length == second.Length
bufferCapacity
Read
Read
Read
评论