-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BinaryReader.Read(byte[], int, int) is a leaky abstraction #68139
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Tagging subscribers to this area: @dotnet/area-system-io Issue DetailsDescription
Unfortunately, the two methods have wildly different semantics. While Reproduction Steps
Expected behaviorThe test should run successfully. Actual behaviorThe test throws an exception, because Regression?No response Known WorkaroundsAt first glance, it looks like this should be able to be worked around trivially with a
ConfigurationCompletely standard install of .NET 6, Visual Studio 2022, Windows 10. Other informationNo response
|
By documentation, the Read method Improvement of stream to fulfill the buffer is tracked in #58216. |
Unfortunately, #16598 isn't going to solve this issue. From looking at BinaryReader, it is a bit confusing at which APIs treat Actual Count APIs:
These are either Count is a "maximum" APIs:
These are just thin wrappers over @huoyaoyuan is correct above that the documentation doesn't say the bottom APIs need to read exactly
https://docs.microsoft.com/en-us/dotnet/api/system.io.binaryreader.read?view=net-6.0#system-io-binaryreader-read(system-byte()-system-int32-system-int32) With #16598, you will be able to accomplish what you want above by saying One potential here is to add @adamsitnik @jozkee @stephentoub - thoughts here? Do you think it would be worth it to add |
It's not a bad idea, but I would prefer to wait until the issue receives feedback from more customers. |
Description
System.IO.BinaryReader
provides an abstraction layer overStream
that takes several common reading tasks and makes them Just Work without having to deal with all the fiddly details of working with the limitedStream
API. Among these operations are two ways to read from the stream into an array:ReadBytes
will read a specified number of bytes and allocate a new array, while theRead(byte[], int, int)
overload will read a specified number of bytes into a pre-existing array.Unfortunately, the two methods have wildly different semantics. While
ReadBytes
works exactly as expected, always returning the specified number of bytes, (unless the underlying stream reaches its end or some error occurs in the stream,) theRead
overload is basically just a pass-through to the underlying stream's similarly-named method. This means that if the underlying stream's implementation is such thatRead
has a limit on the number of bytes it will process at one time,BinaryReader
will shove this same limitation right in your face, rather than taking care of it for you under the hood which is the entire point ofBinaryReader
existing in the first place.Reproduction Steps
Expected behavior
The test should run successfully.
Actual behavior
The test throws an exception, because
BrotliStream.Read
does not return the full requested number of bytes, andBinaryReader
fails to compensate for this.Regression?
No response
Known Workarounds
At first glance, it looks like this should be able to be worked around trivially with a
while
loop and a running total, but in my testing I'm finding cases where this does not produce correct results. It's difficult to say exactly why, as it works most of the time, and I'm dealing with large (1 MB+) blocks of binary data. All I know is, with the data I have,ReadBytes()
always works correctly but generates massive amounts of garbage, and attempting to refactor it to improve memory performance by reusing the buffer occasionally corrupts data.Configuration
Completely standard install of .NET 6, Visual Studio 2022, Windows 10.
Other information
No response
The text was updated successfully, but these errors were encountered: