BufferedStream.Read返回字节数组长度是否可变?旧代码判断冗余疑问
BufferedStream.Read返回值差异与字节数组比较的疑问
用户仓库中的旧代码用于比较两个文件内容是否一致,存在两个疑问:
BufferedStream.Read()返回的实际读取字节数是否可能存在差异?- 既然已经通过
if (bytesReadFirst != bytesReadSecond)判断了两次读取的字节数相等,为何CompareByteArrays方法还要判断两个字节数组的长度是否相等?这个判断是否可以省略?
对应的旧代码如下:
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;
问题1:BufferedStream.Read()返回的字节数是否可能存在差异?
在当前代码的逻辑下,几乎不可能出现差异:
- 代码开头已经判断了两个文件的长度完全相等,这意味着两个文件的总字节数一致。
BufferedStream.Read()的返回值表示本次读取到的字节数,当读取到流末尾时返回0。对于长度相同的文件,正常IO流程中每次读取的字节数应该完全匹配——要么同时读到bufferCapacity字节,要么同时读到剩余的不足bufferCapacity的字节,最后同时返回0。- 极端异常场景(比如读取时发生IO错误)不在当前代码的处理范围内,属于未捕获的异常情况。
问题2:CompareByteArrays中的数组长度判断是否可省略?
不仅可以省略,而且这个判断完全是多余的:
- 调用
CompareByteArrays时传入的firstBuffer和secondBuffer是在方法开头创建的、长度均为bufferCapacity的数组,它们的长度从创建到销毁都不会改变,永远相等。这个判断在当前代码的调用场景下永远为true,没有任何实际意义。
额外的代码bug提示
当前代码存在一个严重的逻辑错误:CompareByteArrays调用memcmp(first, second, first.Length)时,传入的是整个数组的长度(bufferCapacity),但实际上最后一次读取时,bytesReadFirst和bytesReadSecond可能小于bufferCapacity,这时候数组中未被覆盖的部分是之前读取的残留数据,会导致错误的比较结果。
正确的做法应该是只比较实际读取到的字节数,修改方式如下:
- 调整
CompareByteArrays方法:
static bool CompareByteArrays(byte[] first, byte[] second, int length) => Interop.memcmp(first, second, length) == 0;
- 在循环中调用时传入实际读取长度:
if (bytesReadFirst != bytesReadSecond || !CompareByteArrays(firstBuffer, secondBuffer, bytesReadFirst)) return false;
内容的提问来源于stack exchange,提问作者notarobot
相关产品推荐
相关产品推荐

