Scenario
I have a Binary file which is a output from a certain system. The vendor has provided us with the description of the file encoding. Its very complicated because the encoding follows a certain methodology. For eg. the first Byte is ISO coded, we need to decode it first, if the value matches the provided list then it has some meaning. Then the next 15 Bytes also ISO encoded, we need to decode it and compare. Similarly after certain position, few Bytes are Binary encoded.. so on and so forth.
Action so far
I will be using C# WinForm Application. So far I have looked at various documents and all point to FileStream/ BinaryReader combination, since my file size are in the range of 1G to 1.8G. I cannot put the whole file in a Byte[] either.
Problem
I am facing issue in reading the file Byte by Byte. According to the above scenario, first I need to read only 1 Byte then 15 Bytes then 10 Bytes and so on and so forth. How to accomplish this. Thanks in advance for your help.
BinaryReader is the way to go, as it uses a stream the memory usage will be low.
Now you can do something like below :
internal struct MyHeader
{
public byte FirstByte;
// etc
}
internal class MyFormat
{
private readonly string _fileName;
private MyFormat(string fileName)
{
_fileName = fileName;
}
public MyHeader Header { get; private set; }
public string FileName
{
get { return _fileName; }
}
public static MyFormat FromFileName(string fileName)
{
if (fileName == null) throw new ArgumentNullException("fileName");
// read the header of your file
var header = new MyHeader();
using (var reader = new BinaryReader(File.OpenRead(fileName)))
{
byte b1 = reader.ReadByte();
if (b1 != 0xAA)
{
// return null or throw an exception
}
header.FirstByte = b1;
// you can also read block of bytes with a BinaryReader
var readBytes = reader.ReadBytes(10);
// etc ... whenever something's wrong return null or throw an exception
}
// when you're done reading your header create and return the object
var myFormat = new MyFormat(fileName);
myFormat.Header = header;
// the rest of the object is delivered only when needed, see method below
return myFormat;
}
public object GetBigContent()
{
var content = new object();
// use FileName and Header property to get your big content and return it
// again, use a BinaryReader with 'using' statement here
return content;
}
}
Explanations
Call MyFormat.FromFileName to create one of these object, inside it :
you parse the header, whenever an error occurs return null or throw an exception
once your header is parsed you create the object and return it and that's it
Since you just read the header, provide a way for reading the bigger parts in the file.
Pseudo-example:
Use GetBigContent or whatever you want to call it whenever you need to read a large part of it.
Using Header and FileName inside that method you will have everything you need to return a content from this file on-demand.
By using this approach,
you quickly return a valid object by only parsing its header
you do not consume 1.8Gb at first call
you return only what the user needs, on-demand
For your encoding-related stuff the Encoding class will probably be helpful to you :
http://msdn.microsoft.com/en-us/library/system.text.encoding.aspx
BinaryReader.ReadBytes Method
Reads the specified number of bytes from the current stream into a byte array and advances the current position by that number of bytes.
public virtual byte[] ReadBytes(int count)
http://msdn.microsoft.com/en-us/library/system.io.binaryreader.readbytes(v=vs.110).aspx
Related
I have a simple procedure to write a list of library books (of type TBook) to a binary file as follows:
static void SaveToFile(List<TBook> lib)
{
FileStream currentFile;
BinaryWriter writerToFile;
currentFile = new FileStream("MyLibrary.bin", FileMode.Create);
writerToFile = new BinaryWriter(currentFile);
foreach (TBook book in lib)
{
writerToFile.Write(book.Title);
writerToFile.Write(book.Author);
writerToFile.Write(book.Genre);
writerToFile.Write(book.BookID);
}
writerToFile.Close();
currentFile.Close();
}
However, when trying to read the binary file and load contents into a list, i get an error:
An unhandled exception of type 'System.IO.EndOfStreamException' occurred in mscorlib.dll
Additional information: Unable to read beyond the end of the stream.
Here is my subroutine that attempts to read the Binary File back into a Struct again:
static List<TBook> LoadDataFromFile (List<TBook>library)
{
FileStream currentFile;
BinaryReader readerFromFile;
currentFile = new FileStream("MyLibrary.bin", FileMode.Open);
readerFromFile= new BinaryReader(currentFile);
while (currentFile.Position < currentFile.Length)
{
TBook CurrentRecord = new TBook();
CurrentRecord.Title = readerFromFile.ReadString();
CurrentRecord.Author = readerFromFile.ReadString();
CurrentRecord.Genre = readerFromFile.ReadString();
CurrentRecord.BookID = readerFromFile.ReadInt16();
library.Add(CurrentRecord);
}
readerFromFile.Close();
currentFile.Close();
return library;
}
I assume the issue is with the line:
while (currentFile.Position < currentFile.Length)
Note: The Struct is setup as follows:
struct TBook
{
public string Title;
public string Author;
public string Genre;
public int BookID;
}
When you are serializing data as binary, your deserialization code must follow serialization code exactly; otherwise your deserializer starts reading junk from adjacent positions, eventually causing an exception or silently populating your structures with wrong data.
This pair of calls is mismatched:
writerToFile.Write(book.BookID);
....
CurrentRecord.BookID = readerFromFile.ReadInt16();
It is hard to see this problem, because BinaryWriter overloads the Write method. Since book.BookID is of type int, an alias for Int32, the call to Write is resolved to Write(Int32). Therefore, the corresponding read must also read Int32, not Int16:
CurrentRecord.BookID = readerFromFile.ReadInt32();
I am trying to convert byte[] to base64 string format so that i can send that information to third party. My code as below:
byte[] ByteArray = System.IO.File.ReadAllBytes(path);
string base64Encoded = System.Convert.ToBase64String(ByteArray);
I am getting below error:
Exception of type 'System.OutOfMemoryException' was thrown. Can you
help me please ?
Update
I just spotted #PanagiotisKanavos' comment pointing to Is there a Base64Stream for .NET?. This does essentially the same thing as my code below attempts to achieve (i.e. allows you to process the file without having to hold the whole thing in memory in one go), but without the overhead/risk of self-rolled code / rather using a standard .Net library method for the job.
Original
The below code will create a new temporary file containing the Base64 encoded version of your input file.
This should have a lower memory footprint, since rather than doing all data at once, we handle it several bytes at a time.
To avoid holding the output in memory, I've pushed that back to a temp file, which is returned. When you later need to use that data for some other process, you'd need to stream it (i.e. so that again you're not consuming all of this data at once).
You'll also notice that I've used WriteLine instead of Write; which will introduce non base64 encoded characters (i.e. the line breaks). That's deliberate, so that if you consume the temp file with a text reader you can easily process it line by line.
However, you can amend per your needs.
void Main()
{
var inputFilePath = #"c:\temp\bigfile.zip";
var convertedDataPath = ConvertToBase64TempFile(inputFilePath);
Console.WriteLine($"Take a look in {convertedDataPath} for your converted data");
}
//inputFilePath = where your source file can be found. This is not impacted by the below code
//bufferSizeInBytesDiv3 = how many bytes to read at a time (divided by 3); the larger this value the more memory is required, but the better you'll find performance. The Div3 part is because we later multiple this by 3 / this ensures we never have to deal with remainders (i.e. since 3 bytes = 4 base64 chars)
public string ConvertToBase64TempFile(string inputFilePath, int bufferSizeInBytesDiv3 = 1024)
{
var tempFilePath = System.IO.Path.GetTempFileName();
using (var fileStream = File.Open(inputFilePath,FileMode.Open))
{
using (var reader = new BinaryReader(fileStream))
{
using (var writer = new StreamWriter(tempFilePath))
{
byte[] data;
while ((data = reader.ReadBytes(bufferSizeInBytesDiv3 * 3)).Length > 0)
{
writer.WriteLine(System.Convert.ToBase64String(data)); //NB: using WriteLine rather than Write; so when consuming this content consider removing line breaks (I've used this instead of write so you can easily stream the data in chunks later)
}
}
}
}
return tempFilePath;
}
I have a problem with my school project, i use Protobuf library but i have the following error:
Google.Protobuf.InvalidProtocolBufferException" Protocol message contained an invalid tag (zero).
My protocol message wrapper is:
syntax = "proto3";
package CardGameGUI.Network.Protocol.Message;
message WrapperMessage {
enum MessageType {
HELLO_MESSAGE = 0;
JOIN_ROOM_MESSAGE = 1;
JOIN_ROOM_RESPONSE_MESSAGE = 2;
}
MessageType type = 1;
bytes payload = 2;
}
I use this to send a message:
public void SendObject<T>(Protocol.Message.WrapperMessage.Types.MessageType type, T messageObject)
{
byte[] message;
// Serialize message
using (var stream = new MemoryStream())
{
((IMessage)messageObject).WriteTo(stream);
message = stream.GetBuffer();
}
byte[] wrapper = new Protocol.Message.WrapperMessage{Type = type, Payload = Google.Protobuf.ByteString.CopyFrom(message)}.ToByteArray();
Connection.SendObject<byte[]>("ByteMessage", wrapper);
}
And my server handler:
private void IncommingMessageHandler(PacketHeader header, Connection connection, byte[] message)
{
Protocol.Message.WrapperMessage wrapper = Protocol.Message.WrapperMessage.Parser.ParseFrom(message);
switch (wrapper.Type)
{
case Protocol.Message.WrapperMessage.Types.MessageType.HelloMessage:
GetClient(connection.ConnectionInfo.NetworkIdentifier).MessageHandler(Protocol.Message.HelloMessage.Parser.ParseFrom(wrapper.Payload.ToByteArray()));
break;
}
}
The wrapper message is perfectly unserialized, and type is correctly matched, but at the treatment of my Payload, the exception pops.
Do i do something bad?
Edit: a small screen of the message Payload
The problem is probably that you used GetBuffer without making use of the known length. GetBuffer returns the oversized backing array. The data after the stream's .Length is garbage and should not be consumed - it will typically (but not always) be zeros, which is what you are seeing.
Either use ToArray() instead of GetBuffer(), or track the .Length of the stream and only consume that much of the oversized buffer.
Another possibility is "framing" - it looks like you're handling packets, but if this is TCP there is no guarantee that the chunks you receive are the same sizes as the chunks you send. If you are sending multiple messages over TCP you need to implement your own framing (typically via a length prefix, since you're talking binary data).
Incidentally, this isn't protobuf-net.
If neither of those is the problem: check the data you receive is exactly (byte for byte) the data you send (including lengths). It is easy for data to get corrupted or mis-chunked by IO code.
i encounter this problem in this case
because my serialize bytestream loss the varint lenth
such as if i serialize a "Person.proto" message which have 672 bytes
if i deserialize the 672 bytes will encounter the error
the solve strategy is that add the varint len in the 672bytes so youcan get a 674bytes stream
the extra amount data is the "varint" code for 672, which is 160,5
you can get the varint bytes by the function
public static byte[] VarInt(int value)
{
//data len
List<byte> varIntBuffer = new List<byte>();
int index = 0;
while (true)
{
if ((value & ~0x7f) == 0)
{
varIntBuffer.Add((byte)(value & 0x7f));
break;
}
else
{
varIntBuffer.Add((byte)((value & 0x7f) | 0x80));
value = value >> 7;
}
index++;
}
return varIntBuffer.ToArray();
}
I had this same issue when attempting to deserialize a byte array which had been initialized to a fixed size but there was a bug which meant I was not populating the array with proto bytes (so the byte array was populated with zeros when I was attempting to deserialize).
It turns out that I was reading bytes from a JMS BytesMessage twice in a test case but was not calling BytesMessage.reset() before the second read.
I'm guessing you could get a similar bug if attempting to read from an InputStream twice without calling reset()
im trying to send an image via network stream, i have a sendData and Getdata functions
and i always get an invalid parameter when using the Image.FromStream function
this is my code :
I am Getting the pic from the screen, then converting it to a byte[]
Inserting it to a Memory stream that i send via a networkStream.
private void SendData()
{
StreamWriter swWriter = new StreamWriter(this._nsClient);
// BinaryFormatter bfFormater = new BinaryFormatter();
// this method
lock (this._secLocker)
{
while (this._bShareScreen)
{
// Check if you need to send the screen
if (this._bShareScreen)
{
MemoryStream msStream = new MemoryStream();
this._imgScreenSend = new Bitmap(this._imgScreenSend.Width, this._imgScreenSend.Height);
// Send an image code
swWriter.WriteLine(General.IMAGE);
swWriter.Flush();
// Copy image from screen
this._grGraphics.CopyFromScreen(0, 0, 0, 0, this._sizScreenSize);
this._imgScreenSend.Save(msStream, System.Drawing.Imaging.ImageFormat.Jpeg);
msStream.Seek(0, SeekOrigin.Begin);
// Create the pakage
byte[] btPackage = msStream.ToArray();
// Send its langth
swWriter.WriteLine(btPackage.Length.ToString());
swWriter.Flush();
// Send the package
_nsClient.Write(btPackage, 0, btPackage.Length);
_nsClient.Flush();
}
}
}
}
private void ReciveData()
{
StreamReader srReader = new StreamReader(this._nsClient);
string strMsgCode = String.Empty;
bool bContinue = true;
//BinaryFormatter bfFormater = new BinaryFormatter();
DataContractSerializer x = new DataContractSerializer(typeof(Image));
// Lock this method
lock (this._objLocker)
{
while (bContinue)
{
// Get the next msg
strMsgCode = srReader.ReadLine();
// Check code
switch (strMsgCode)
{
case (General.IMAGE):
{
// Read bytearray
int nSize = int.Parse(srReader.ReadLine().ToString());
byte[] btImageStream = new byte[nSize];
this._nsClient.Read(btImageStream, 0, nSize);
// Get the Stream
MemoryStream msImageStream = new MemoryStream(btImageStream, 0, btImageStream.Length);
// Set seek, so we read the image from the begining of the stream
msImageStream.Position = 0;
// Build the image from the stream
this._imgScreenImg = Image.FromStream(msImageStream); // Error Here
Part of the problem is that you're using WriteLine() which adds Environment.NewLine at the end of the write. When you just call Read() on the other end, you're not dealing with that newline properly.
What you want to do is just Write() to the stream and then read it back on the other end.
The conversion to a string is strange.
What you're doing, when transferring an image, is sending an array of bytes. All you need to do is send the length of the expected stream and then the image itself, and then read the length and the byte array on the other side.
The most basic and naive way of transferring a byte array over the wire is to first send an integer that represents the length of the array, and read that length on the receiving end.
Once you now know how much data to send/receive, you then send the array as a raw array of bytes on the wire and read the length that you previously determined on the other side.
Now that you have the raw bytes and a size, you can reconstruct the array from your buffer into a valid image object (or whatever other binary format you've just sent).
Also, I'm not sure why that DataContractSerializer is there. It's raw binary data, and you're already manually serializing it to bytes anyway, so that thing isn't useful.
One of the fundamental problems of network programming using sockets and streams is defining your protocol, because the receiving end can't otherwise know what to expect or when the stream will end. That's why every common protocol out there either has a very strictly defined packet size and layout or else does something like sending length/data pairs, so that the receiving end knows what to do.
If you implement a very simple protocol such as sending an integer which represents array length and reading an integer on the receiving end, you've accomplished half the goal. Then, both sender and receiver are in agreement as to what happens next. Then, the sender sends exactly that number of bytes on the wire and the receiver reads exactly that number of bytes on the wire and considers the read to be finished. What you now have is an exact copy of the original byte array on the receiving side and you can then do with it as you please, since you know what that data was in the first place.
If you need a code example, I can provide a simple one or else there are numerous examples available on the net.
Trying to keep it short:
the Stream.Read function (which you use) returns an int that states how many bytes were read, this is return to you so you could verify that all the bytes you need are received.
something like:
int byteCount=0;
while(byteCount < nSize)
{
int read = this._nsClient.Read(btImageStream, byteCount, nSize-byteCount);
byteCount += read;
}
this is not the best code for the job
My app reads bytes from a TCP socket and needs to buffer them up, so that I can extract messages from them later. Due to the nature of TCP I may get partial or multiple messages in one read, so after each read I would like to inspect the buffer and extract as many full messages as are available.
Therefore I want a class that allows me to do the following:
append arbitrary byte[] data to it
inspect the content without consuming it, in particular checking the amount of content and also searching for the existence of a certain byte or bytes
extract and consume part of the data as a byte[], while leaving the rest in there for a future read
I expect that what I want can be done with 1 or more existing classes in the .NET library, but I'm not sure which ones. System.IO.MemoryStream looks close to what I want, but (a) it isn't clear whether it's suited to being used as a buffer (does the read data get removed from the capacity?) and (b) reads and writes seem to happen at the same place - "The current position of a stream is the position at which the next read or write operation could take place." - which is not what I want. I need to be writing to the end and reading from the front.
I suggest you use MemoryStream under the hood, but encapsulate it in another class which stores:
The MemoryStream
The current "read" position
The current "consumed" position
It will then expose:
Write: set the stream's position to the end, write data, set the stream's position back to the read position
Read: read data, set the read position to the stream's position
Consume: update the consumed position (details based on how you're trying to consume); if the consume position is above a certain threshold, copy the existing buffered data into a new MemoryStream and update all the variables. (You probably don't want to copy the buffer on every consume request.)
Note that none of this will be thread-safe without extra synchronization.
Just use a big byte-array and Array.Copy - it should do the trick.
If not, use List<byte>.
If you use the array you have to implement an index to it (where you copy additional data) yourself (same for checking the content-size), but it's straightforward.
If you are interested: here is a simple implementation of a "cyclic buffer". The test should run (I threw a couple unit test at it, but it didn't check all critical path):
public class ReadWriteBuffer
{
private readonly byte[] _buffer;
private int _startIndex, _endIndex;
public ReadWriteBuffer(int capacity)
{
_buffer = new byte[capacity];
}
public int Count
{
get
{
if (_endIndex > _startIndex)
return _endIndex - _startIndex;
if (_endIndex < _startIndex)
return (_buffer.Length - _startIndex) + _endIndex;
return 0;
}
}
public void Write(byte[] data)
{
if (Count + data.Length > _buffer.Length)
throw new Exception("buffer overflow");
if (_endIndex + data.Length >= _buffer.Length)
{
var endLen = _buffer.Length - _endIndex;
var remainingLen = data.Length - endLen;
Array.Copy(data, 0, _buffer, _endIndex, endLen);
Array.Copy(data, endLen, _buffer, 0, remainingLen);
_endIndex = remainingLen;
}
else
{
Array.Copy(data, 0, _buffer, _endIndex, data.Length);
_endIndex += data.Length;
}
}
public byte[] Read(int len, bool keepData = false)
{
if (len > Count)
throw new Exception("not enough data in buffer");
var result = new byte[len];
if (_startIndex + len < _buffer.Length)
{
Array.Copy(_buffer, _startIndex, result, 0, len);
if (!keepData)
_startIndex += len;
return result;
}
else
{
var endLen = _buffer.Length - _startIndex;
var remainingLen = len - endLen;
Array.Copy(_buffer, _startIndex, result, 0, endLen);
Array.Copy(_buffer, 0, result, endLen, remainingLen);
if (!keepData)
_startIndex = remainingLen;
return result;
}
}
public byte this[int index]
{
get
{
if (index >= Count)
throw new ArgumentOutOfRangeException();
return _buffer[(_startIndex + index) % _buffer.Length];
}
}
public IEnumerable<byte> Bytes
{
get
{
for (var i = 0; i < Count; i++)
yield return _buffer[(_startIndex + i) % _buffer.Length];
}
}
}
Please note: the code "consumes" on read - if you don't want that just remove the "_startIndex = ..." parts (or make a overload optional parameter and check or whatever).
I think BufferedStream is the solution to the problem. Also it is possible to go unread len byte of data by calling Seek.
BufferdStream buffer = new BufferedStream(tcpStream, size); // we have a buffer of size
...
...
while(...)
{
buffer.Read(...);
// do my staff
// I read too much, I want to put back len bytes
buffer.Seek(-len, SeekOrigin.End);
// I shall come back and read later
}
Growing memory
Contrary to BufferedStream where the size is specified initially, MemoryStream can grow.
Remembering streaming data
MemoryStream holds all the dara-read all the time, while BufferedStream only holds a segment of stream data.
Source stream vs byte array
MemoryStream allows to add input-bytes in Write() method which can be Read() in future. While BufferedSteam takes input-bytes from another source-stream specified in the constructor.
Here's another implementation of a buffer I wrote a while ago:
Resizeable: allowing to queue up data and not throw buffer overflow exception;
Efficient: uses a single buffer and Buffer.Copy operations to enqueue/dequeue data
Coming to this late, but for posterity:
When I've done this in the past I've take a slight different approach. If your messages have a fixed header size (that tells you how many bytes in the body), and bearing in mind the network stream is already buffering, I perform the operation in two phases:
a read on the stream for the bytes for the header
a subsequent read on the stream for the bytes for the body, based on the header
repeat
This leverages the fact that - for a stream - when you ask for 'n' bytes you'll never get more back, so you can ignore many of the 'opps I read too many, let me put these aside till next time' issues.
Now this isn't the whole story, to be fair. I had an underlying wrapper class over the stream to handle fragmentation issues (ie if asked for 4 bytes, don't return until 4 bytes received, or stream closed). But that bit is fairly easy.
In my mind the key is to decouple the message handling with the stream mechanics, and if you stop attempting to consume the message as a single ReadBytes() from a stream, life becomes much simpler.
[all of this is true whether your reads are blocking, or async (APM/await)]
It sounds like you want to read from the socket into a MemoryStream buffer, and then 'pop' data out of the buffer and reset it each time a certain byte is encountered. It would look something like this:
void ReceiveAllMessages(Action<byte[]> messageReceived, Socket socket)
{
var currentMessage = new MemoryStream();
var buffer = new byte[128];
while (true)
{
var read = socket.Receive(buffer, 0, buffer.Length);
if (read == 0)
break; // Connection closed
for (var i = 0; i < read; i++)
{
var currentByte = buffer[i];
if (currentByte == END_OF_MESSAGE)
{
var message = currentMessage.ToByteArray();
messageReceived(message);
currentMessage = new MemoryStream();
}
else
{
currentMessage.Write(currentByte);
}
}
}
}
You could do this with a Stream wrapping a ConcurrentQueue<ArraySegment<byte>> (keep in mind this makes it forward only). However I really dislike the idea of keeping data in memory before doing something with it; it opens you up to a bunch of attacks (intentional or not) regarding the size of the message. You might also want to Google "circular buffer".
You should actually be writing code that does something meaningful with the data as soon as it is received: 'Push Parsing' (this is what, for example, SAX supports). As an example of how you would do this with text:
private Encoding _encoding;
private Decoder _decoder;
private char[] _charData = new char[4];
public PushTextReader(Encoding encoding)
{
_encoding = encoding;
_decoder = _encoding.GetDecoder();
}
// A single connection requires its own decoder
// and charData. That connection should never
// call this method from multiple threads
// simultaneously.
// If you are using the ReadAsyncLoop you
// don't need to worry about it.
public void ReceiveData(ArraySegment<byte> data)
{
// The two false parameters cause the decoder
// to accept 'partial' characters.
var charCount = _decoder.GetCharCount(data.Array, data.Offset, data.Count, false);
charCount = _decoder.GetChars(data.Array, data.Offset, data.Count, _charData, 0, false);
OnCharacterData(new ArraySegment<char>(_charData, 0, charCount));
}
If you must be able to accept complete messages before deserializing them, you can use a MemoryMappedFile, which has the advantage that the sending entity won't be able to out-of-memory your server. What gets tricky is resetting the file back to zero; because that can bunch of issues. One way to tackle this is by:
TCP Receiver End
Write to the current stream.
If the stream exceeds a certain length move to a new one.
Deserialization End
Read from the current stream.
Once you have emptied the stream destroy it.
The TCP receiver end is very simple. The deserializer end will need some elementary buffer stitching logic (remember to use Buffer.BlockCopy and not Array.Copy).
Side note: Sounds like a fun project, if I have the time and remember I might go ahead and implement this system.
There are only three answers here which provide code.
One of them is clumsy and the others do not answer the question.
Here a class that you can just copy and paste:
/// <summary>
/// This class is a very fast and threadsafe FIFO buffer
/// </summary>
public class FastFifo
{
private List<Byte> mi_FifoData = new List<Byte>();
/// <summary>
/// Get the count of bytes in the Fifo buffer
/// </summary>
public int Count
{
get
{
lock (mi_FifoData)
{
return mi_FifoData.Count;
}
}
}
/// <summary>
/// Clears the Fifo buffer
/// </summary>
public void Clear()
{
lock (mi_FifoData)
{
mi_FifoData.Clear();
}
}
/// <summary>
/// Append data to the end of the fifo
/// </summary>
public void Push(Byte[] u8_Data)
{
lock (mi_FifoData)
{
// Internally the .NET framework uses Array.Copy() which is extremely fast
mi_FifoData.AddRange(u8_Data);
}
}
/// <summary>
/// Get data from the beginning of the fifo.
/// returns null if s32_Count bytes are not yet available.
/// </summary>
public Byte[] Pop(int s32_Count)
{
lock (mi_FifoData)
{
if (mi_FifoData.Count < s32_Count)
return null;
// Internally the .NET framework uses Array.Copy() which is extremely fast
Byte[] u8_PopData = new Byte[s32_Count];
mi_FifoData.CopyTo(0, u8_PopData, 0, s32_Count);
mi_FifoData.RemoveRange(0, s32_Count);
return u8_PopData;
}
}
/// <summary>
/// Gets a byte without removing it from the Fifo buffer
/// returns -1 if the index is invalid
/// </summary>
public int PeekAt(int s32_Index)
{
lock (mi_FifoData)
{
if (s32_Index < 0 || s32_Index >= mi_FifoData.Count)
return -1;
return mi_FifoData[s32_Index];
}
}
}