MemoryStream: why convert to byte after readByte - c#

In this example from MS, you'll notice that after we read a byte from memory stream, it goes into an int which must then be converted to byte. It stikes me as strange that a function like .ReadByte() doesn't return a byte in the first place. Is there a reason why MS did it this way?
// Read the remaining bytes, byte by byte.
while(count < memStream.Length)
{
byteArray[count++] =
Convert.ToByte(memStream.ReadByte());
}
a thought occured to me. Perhaps this comes down to usage. Perhaps ReadByte() is often used to retrieve short lengths, which subsequents get consumed in the retrieve via length variety
int length=ms.ReadByte();
ms.Read(buf,0,lenth);
i.e. you can use the length without a cast. Is this a good enough reason?

This is not specific to Memory stream, rather it is because of the design of base class "Stream" and the reason for that is
Return value:
The unsigned byte cast to an Int32, or -1 if at the end of the stream.
-1 cannot be represented using unsigned byte

When you use ReadByte If the read is successful then the current position within the stream is advanced by one byte. but its designed to return -1 if the end of the stream has been reached.
Now this would not be a valid value for Byte (its unsigned)
ms.Read(buf,0,lenth); here lenth is the number of bytes to read from the stream and what you get from ReadByte is first byte its not be used in the this fashion, something like
byte[] buff = new byte[ms.Length];
ms.Read(buff , 0, buff .Length);

I do believe they are converting with that from int to byte in a reallllllly nice way, since ReadByte() returns an int and their byteArray is of type int[].

Related

How to detect a serial bit byte error in SerialPort class C#

I am using System.IO.Ports.SerialPort to read data from serial communication. The problem is that I want to determine which byte is bad when I read the byte array buffer and write a file. If I know which byte is bad, then I can recreate the correct file since I know the hash of the file. But It looks like System.IO.Ports.SerialPort only gives a way to "overwrite" an erroneous byte with the SerialPort.ParityReplace property. If I'm reading a million byte array, then I don't want to set a bit pattern as a replacement value and then search for this bit pattern in the massive array since I may have lots of matches. Is there a way for me to determine which byte failed a parity check when I read the byte buffer? If not, what would be a better way for me to get parity style error detection while sending a file over serial?
The code below is the way I'm currently looking at the serial data, but I'm open to other methods if its faster or gives more reliability.
//... earlier code:
_serialPort.ReadBufferSize = 100000000;
//... more irrelevant code
Thread.Sleep(150000); // wait for 150 seconds for the data to come in.
byte[] HundredKBBuffer = new byte[_serialPort.ReadBufferSize]; // the byte array I'll read from
//read data then discard buffer to get new data from the transmitting machine
_serialPort.Read(HundredKBBuffer, 0, HundredKBBuffer.Length);
_serialPort.DiscardInBuffer();
Console.WriteLine("data received");
//code that reads the byte array, looks for header and trailer and writes file
findHeadAndWriteDataToFile(HundredKBBuffer);
Have you tried reading the data in asynchronously as a stream instead of waiting to get the whole block at once? This sounds like it would allow you more opportunities to error check.
What is the correct way to read a serial port using .NET framework?
First idea is to you parity check after each byte, but you could loose speed communication (1 byte of data, 1 byte of parity check).
You can laso use CRC Code which is like an extension of the parity check. For example, you send 8 bytes and the ninth byte is the CRC. This allow you to control datas for a size-specified packet. The CRC function looks like this (it is the CRC-8 function, but you can use an other one):
private byte CRC8(byte[] Array, int length)
{
byte CRC = 0x00;
int length_buffer = length;
int length_refreshed = length;
CRC = Array[0];
length_refreshed--; ;
for (; length_refreshed > 0; length_refreshed--)
{
CRC = (byte)(((int)CRC) ^ (int)Array[length_buffer - length_refreshed]);
}
return CRC;
}
EDIT
Check here for CRC: https://en.wikipedia.org/wiki/Cyclic_redundancy_check

UTF8 byte[] to string conversion

I have UTF8 byte[] of infinite size (i.e. of very large size). I want to truncate it to 1024 bytes only and then convert it to string.
Encoding.UTF8.GetString(byte[], int, int) does that for me. It first shortens 1024 bytes and then gives me its converted string.
But in this conversion, if last character is of UTF8 character set, which is made of 2 bytes and whose first byte falls in range and another byte is out of range then it displays ? for that character in converted string.
Is there any way so that this ? does not come in converted string?
That's what the Decoder class is for. It allows you to stream byte data into char data, while maintaining enough state to handle partial code-points correctly:
Encoding.UTF8.GetDecoder().GetChars(buffer, 0, 1024, charBuffer, 0)
Of course, when the code-point is split in the middle, the Decoder is left with a "partial char" in its state, but that doesn't concern you in your case (and is desirable in all the other use cases :)).

Convert 32 bit float audio to 16 bit byte array?

I am getting audio using the NAudio library which returns a 32 bit float[] of audio data. I'm trying to find a way to convert this to a 16 bit byte[] for playback.
private void sendData(float[] samples)
{
Buffer.BlockCopy(samples, 0, byteArray, 0, samples.Length);
byte[] encoded = codec.Encode(byteArray, 0, byteArray.Length);
waveProvider.AddSamples(byteArray, 0, byteArray.Length);
s.Send(encoded, SocketFlags.None);
}
The audio being sent to waveProvider is coming out static-y — I don't think I'm converting correctly. How can I convert to a byte array of 16 bit samples?
Buffer.BlockCopy copies a number of bytes, but you're passing it a number of elements. Since a float is 4 bytes and a byte is obviously 1, you're using a fourth of samples to fill up half of byteArray, leaving the rest untouched. That probably won't give you very good audio, to say the least.
What you'll need to do is convert from a floating-point value between −1 and 1 to a 16-bit integer value between −215 and 215−1. If we convert to shorts rather than bytes, it's rather simple:
shortSample = (short)Math.Floor(floatSample * 32767);
(If you know that floatSample will always be less than 1, you should multiply by 32,768 rather than 32,767.)
Of course, you want a byte array rather than a short array. Unfortunately, you've not given enough information for that last step. There's two things that you'll need to know: endianness and signedness. If it's unsigned, you'll need to convert that short to a ushort by adding 32,768. Then you need to split each short or ushort up into two bytes. Endianness determines the order, but you'll probably need to do some bit-shifting.

Why FileStream.Length is long type, but FileStream.Read argument - offset has a shorter length?

Why FileStream.Length is long type, but FileStream.Read argument - offset has a shorter length int instead?
Bryan
The offset parameter tells where to start writing data in your array, the array parameter. It does not point out an offset in the file data.
The offset parameter gives the offset of the byte in array (the buffer index) at which to begin reading, and the count parameter gives the maximum number of bytes to be read from this stream. The returned value is the actual number of bytes read, or zero if the end of the stream is reached. If the read operation is successful, the current position of the stream is advanced by the number of bytes read. If an exception occurs, the current position of the stream is unchanged.
Source: FileStream.Read
The offset is the index into the byte array where the data is placed. You can't allocate an array that is larger than 2 GB, so there is no need for a bigger number for the offset.
I'm assuming you are referring to this method which is overridden from the base class Stream.
The offset is the location in the array argument to place the bytes not the offset from the beginning of the FileStream. The array argument is of type byte[] which cannot have more than int.MaxValue elements.
As addition to mike z answer, why byte[] cannot be indexed more than int.MaxValue - class Array implements IList with object this[int index] { get; set; } method, so index can be only integer.
FileStream.Length gets the length in bytes of the stream and FileStream.Read reads a block of bytes from the stream. So, logically you'll have more single bytes than blocks of that bytes. I'm assuming that for this reason FileStream.Length requires long type.
FileStream extending Stream,
Stream can handle number of byte[int.MaxValue] arrays and together they have a long length.
But when you use Read, you can read only part of it to a byte array with int.MaxValue.
Think about that if you want to read from disk a file bigger then 2G = int.MaxValue ,
you will need to read it in chunks of byte[int.MaxValue]
(:

what's the difference between a streamwriter and a binarywriter?

this really confuses me, say i want to save an integer into a file, int x=56, the binarywriter takes the ascii equivalent of the representation of 56 in memory
00000000 00000000 00000000 00111000 , which would be : null null null 8 and write it to the file? am i correct? can someone explain how those twofunction and when should i use each of them? im using c# btw. thanx in advance!
From the MSDN pages for StreamWriter and BinaryWriter you can clearly see the differences:
StreamWriter:
Implements a TextWriter for writing
characters to a stream in a particular
encoding.
And:
BinaryWriter:
Writes primitive types in binary to a
stream and supports writing strings in
a specific encoding.
The first one writes things as text, the second writes in binary, little endian, so int x = 56 would be written 00111000 00000000 00000000 00000000.
The binary writer writes the in-memory binary representation of the integer. The stream writer writes the ASCII representation. Generally speaking, the former can be more compact and efficient (consider writing the integer 23861398 - the binary writer would require 4 bytes, but the stream writer would require 8, 16, or even 32 depending on the encoding) but the latter results in plain old text.
From what I can discern... StreamWriter is more for text and BinaryWriter is for primitive types including strings of particular encodings. Saying that the BinaryWriter writes in binary though is kind of misleading to people who take things at face value... as I did. I assumed that when I write an integer to the underlying stream it would actually write it in binary and I could read it again as a stream of 1's and 0's.
To put things down as it looks in code:
MemoryStream stream = new MemoryStream();
BinaryWriter bw = new BinaryWriter(stream);
bw.Write(35);
// is equivalent to doing:
stream.Write(BitConverter.GetBytes((int)35), 0, 4);
Though the BinaryWriter uses bit shifting to extract the bytes and BitConverter uses unsafe pointer casting, the result is the same. An int is 32 bits or 4 bytes in length, and all it simply does is writes the bytes that represent that int to it's underlying stream.
StreamWriter does the same thing only that it's meant for text, so integers won't be converted to bytes, but instead to chars... this is similar to writing:
byte[] buffer = Encoding.UTF8.GetBytes("my string here 1234");
stream.Write(buffer, 0, buffer.Length);
That is why I said it's misleading to say it writes in binary.. because it does.. technically. Break down each written byte into bits and you get the binary values. However it would make more sense to say that it writes primitive types as byte arrays. If you were to convert the stream to a string you would not get a string of 1's and 0's.
StreamWriter is for text and BinaryWriter writes the actual binary representation of what you want to write. I'm not 100 % sure, but almost :).

Categories

Resources