I dont know what I'm doing wrong here. my code works as expected on the first pass but on the second pass it wont run and throws an exception that just says "Reading would overrun buffer%"
I gather I'm doing something wrong with buffer and it doesn't like me overwriting it?
I had essentially the same code and changed it to match the msdn example but no joy..
using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[1024];
int bytesRead = 0;
long bytesToRead = stream.Length;
while (bytesToRead > 0)
{
int n = stream.Read (buffer, bytesRead, 1024);
if (n == 0) break;
//do work on buffer...
bytesRead += n;
bytesToRead -= n;
}
}
Working in .Net 2.0 Mono.
Stream.Read - second parameter is offset in the buffer and should be 0 in your case.
Read parameters is for buffer informations, you stock the data in buffer from offset to offset+nLength
To advance in your file set
stream.Position = bytesRead;
Related
I am working on serial port communication. While using BaseStream I am writing and reading the port.
port.BaseStream.Write(dataItems, 0, dataItems.Length);
int receivedBytes = port.BaseStream.Read(buffer, 0, (int)buffer.Length);
Thread.Sleep(100);
var receiveData = BitConverter.ToString(buffer, 0, receivedBytes);
Hereafter write, I am sleeping the thread so that I will get full bytes. Is there any other way around that I can wait that all bytes are available?
Note
The last byte should be 22. Also the above code is running in Task named as public async Task PortHitmethod(Iterations iterations)
This is certainly a wrong way to use Stream.Read. The correct pattern is in the documentation:
Stream s = new MemoryStream();
...
// Now read s into a byte buffer with a little padding.
byte[] bytes = new byte[s.Length + 10];
int numBytesToRead = (int)s.Length;
int numBytesRead = 0;
do
{
// Read may return anything from 0 to 10.
int n = s.Read(bytes, numBytesRead, 10);
numBytesRead += n;
numBytesToRead -= n;
} while (numBytesToRead > 0);
s.Close();
P.S. If you think you should use Thread.Sleep then you can be sure you are certainly doing something wrong.
Im building an application where i need to reed 15 byes from a serial device. (ScaleXtric c7042 powerbase) The bytes need to come in the right order, and the last one is a crc.
Using this code in an backgroundworker, I get the bytes:
byte[] data = new byte[_APB.ReadBufferSize];
_APB.Read(data, 0, data.Length);
The problem is that I don't get the first bytes first, Its like it stores some of the bytes in the buffer, so next time the DataRecieved event fires, I get the last x bytes from the previous message, and only the 15-x byte from the new. I write the bytes to a text box, and its all over the place, so some bytes are missing somewhere.
I have tried to clear the buffer after each read, but no luck.
_APB = new SerialPort(comboBoxCommAPB.SelectedItem.ToString());
_APB.BaudRate = 19200;
_APB.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandlerDataFromAPB);
_APB.Open();
_APB.DiscardInBuffer();
Hope any one can help me here
Use this Method to read fixed amout of bytes from serial port, for your case toread = 15;
public byte[] ReadFromSerialPort(SerialPort serialPort, int toRead)
{
byte[] buffer = new byte[toRead];
int offset = 0;
int read;
while (toRead > 0 && (read = serialPort.Read(buffer, offset, toRead)) > 0)
{
offset += read;
toRead -= read;
}
if (toRead > 0) throw new EndOfStreamException();
return buffer;
}
It says here msdn.microsoft.com/en-us/library/system.io.stream.read.aspx that the Stream.Read and Stream.Write methods both advance the position/offset in the stream automatically so why is the examples here http://msdn.microsoft.com/en-us/library/system.io.stream.read.aspx and http://msdn.microsoft.com/en-us/library/system.io.filestream.read.aspx manually changing the offset?
Do you only set the offset in a loop if you know the size of the stream and set it to 0 if you don't know the size and using a buffer?
// Now read s into a byte buffer.
byte[] bytes = new byte[s.Length];
int numBytesToRead = (int) s.Length;
int numBytesRead = 0;
while (numBytesToRead > 0)
{
// Read may return anything from 0 to 10.
int n = s.Read(bytes, numBytesRead, 10);
// The end of the file is reached.
if (n == 0)
{
break;
}
numBytesRead += n;
numBytesToRead -= n;
}
and
using (GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
{
const int size = 4096;
byte[] buffer = new byte[size];
using (MemoryStream memory = new MemoryStream())
{
int count = 0;
do
{
count = stream.Read(buffer, 0, size);
if (count > 0)
{
memory.Write(buffer, 0, count);
}
}
while (count > 0);
return memory.ToArray();
}
}
The offset is actually the offset of the buffer, not the stream. Streams are advanced automatically as they are read.
Edit (to the edited question):
In none of the code snippets you pasted into the question I see any stream offset being set.
I think you are mistaking the calculation of bytes to read vs. bytes received. This protocol may seem funny (why would you receive fewer bytes than requested?) but it makes sense when you consider that you might be reading from a high-latency packet oriented source (think: network sockets).
You might be receiving 6 characters in one burst (from a TCP packet) and only receive the remaining 4 characters in your next read (when the next packet has arrived).
Edit In response to your linked example from the comment:
using (GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
{
// ... snip
count = stream.Read(buffer, 0, size);
if (count > 0)
{
memory.Write(buffer, 0, count);
}
It appears that the coders use prior knowledge about the underlying stream implementation, that stream.Read will always return 0 OR the size requested. That seems like a risky bet, to me. But if the docs for GZipStream do state that, it could be alright. However, since the MSDN samples use a generic Stream variable, it is (way) more correct to check the exact number of bytes read.
The first linked example uses a MemoryStream in both Write and Read fashion. The position is reset in between, so the data that was written first will be read:
Stream s = new MemoryStream();
for (int i = 0; i < 100; i++)
{
s.WriteByte((byte)i);
}
s.Position = 0;
The second example linked does not set the stream position. You'd typically have seen a call to Seek if it did. You maybe confusing the offsets into the data buffer with the stream position?
I get the following error on the second iteration of my loop:
Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
and this is my loop
FileStream fs = new FileStream("D:\\06.Total Eclipse Of The Moon.mp3", FileMode.Open);
byte[] _FileName = new byte[1024];
long _FileLengh = fs.Length;
int position = 0;
for (int i = 1024; i < fs.Length; i += 1024)
{
fs.Read(_FileName, position, Convert.ToInt32(i));
sck.Client.Send(_FileName);
Thread.Sleep(30);
long unsend = _FileLengh - position;
if (unsend < 1024)
{
position += (int)unsend;
}
else
{
position += i;
}
}
fs.Close();
}
fs.Length = 5505214
On the first iteration, you're calling
fs.Read(_FileName, 0, 1024);
That's fine (although why you're calling Convert.ToInt32 on an int, I don't know.)
On the second iteration, you're going to call
fs.Read(_FileName, position, 2048);
which is trying to read into the _FileName byte array starting at position (which is non-zero) and fetching up to 2048 bytes. The byte array is only 1024 bytes long, so that can't possibly work.
Additional problems:
You haven't used a using statement, so on exceptions you'll leave the stream open
You're ignoring the return value from Read, which means you don't know how much of your buffer has actually been read
You're unconditionally sending the socket the complete buffer, regardless of how much has been read.
Your code should probably look more like this:
using (FileStream fs = File.OpenRead("D:\\06.Total Eclipse Of The Moon.mp3"))
{
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
{
sck.Client.Send(buffer, 0, bytesRead);
// Do you really need this?
Thread.Sleep(30);
}
}
I'm trying to read the response stream from an HttpWebResponse object. I know the length of the stream (_response.ContentLength) however I keep getting the following exception:
Specified argument was out of the range of valid values.
Parameter name: size
While debugging, I noticed that at the time of the error, the values were as such:
length = 15032 //the length of the stream as defined by _response.ContentLength
bytesToRead = 7680 //the number of bytes in the stream that still need to be read
bytesRead = 7680 //the number of bytes that have been read (offset)
body.length = 15032 //the size of the byte[] the stream is being copied to
The peculiar thing is that the bytesToRead and bytesRead variables are ALWAYS 7680, regardless of the size of the stream (contained in the length variable). Any ideas?
Code:
int length = (int)_response.ContentLength;
byte[] body = null;
if (length > 0)
{
int bytesToRead = length;
int bytesRead = 0;
try
{
body = new byte[length];
using (Stream stream = _response.GetResponseStream())
{
while (bytesToRead > 0)
{
// Read may return anything from 0 to length.
int n = stream.Read(body, bytesRead, length);
// The end of the file is reached.
if (n == 0)
break;
bytesRead += n;
bytesToRead -= n;
}
stream.Close();
}
}
catch (Exception exception)
{
throw;
}
}
else
{
body = new byte[0];
}
_responseBody = body;
You want this line:
int n = stream.Read(body, bytesRead, length);
to be this:
int n = stream.Read(body, bytesRead, bytesToRead);
You are saying the maximum number of bytes to read is the stream's length, but it isn't since it is actually only the remaining information in the stream after the offset has been applied.
You also shouldn't need this part:
if (n == 0)
break;
The while should end the reading correctly, and it is possible that you won't read any bytes before you have finished the whole thing (if the stream is filling slower than you are taking the data out of it)