You're doing quite a few things wrong. First of all, I don't know why you need a
loop in your code. The only purpose it serves is to make it impossible to quit the process gracefully.
Second, the byte counter you're using is actually not a byte counter but a character byte counter. If you're converting your bytes (which don't hold any encoding due to the way you're generating them) into a specific encoding such as ASCII or UTF8, you are effectively unable to display certain byte values, because for example the ASCII character sets don't handle all characters and byte values.
There's also the 'small' matter of how many bytes it requires to represent a character. UTF8, for example, requires minimum one byte, but if the value is bigger than 127 then UTF8 may take multiple bytes (2, 3 or 4 bytes since it's variable width). That is evident, for example, by the display of those question mark 'place holder' characters. What you are getting, is an incomplete or 'broken' representation, if you can even call it that. I'd like to call it the result of programmer that doesn't know what he's doing.
If you take the following byte value for example:
You will not get a correct UTF8 string because it's value is much larger than the maximum of 127 (
0x7F) for a single byte.
Third, if you count the length of the byte array, you'll notice that it really is 24 bytes because you set it to be a maximum of 24 bytes long:
Code
byte[] b = new byte[24];
If you were to attempt to set byte at index 25, you'd get an
IndexOutOfRangeException:
Go ahead and run that and see for yourself. So, now that we're absolutely positive that your byte array is in fact 24 bytes long, what else are you doing wrong? Well, you're not using OOP standards. This might be overkill in some scenario's, but just for the sake of following good coding principles, let me fix that for you:
Code
using System;
namespace ByteTest
{
public sealed class ByteGenerator
{
private readonly Random _random;
/// <summary>
/// Initialize a new ByteGenerator
/// </summary>
/// <param name="seed">The seed that can be used to initialize a Random object</param>
public ByteGenerator(int seed)
{
_random = new Random(seed);
}
/// <summary>
/// Initialize a new ByteGenerator
/// </summary>
public ByteGenerator()
{
_random = new Random();
}
/// <summary>
/// Generate an array of random bytes with a given length
/// </summary>
/// <param name="length">The length of the byte array that should be generated</param>
/// <returns>A byte array that contains random bytes with a given length</returns>
public byte[] GenerateBytes(int length)
{
if (length <= 0) throw new ArgumentOutOfRangeException(nameof(length));
byte[] data = new byte[length];
_random.NextBytes(data);
return data;
}
}
}
What this class does, is allow you to reuse the same code, in different environments. As you can see the class is sealed which means it cannot be inherited by other classes.
Next up. How do you properly display those bytes? Well, there are a few ways in which you can get a correct representation of said bytes. The first way to do it would be to adhere to the character sets, but then again you'd possibly be generating more (or less) bytes than your desired amount of bytes which beats the purpose of your question. While
ASCII and
UTF8 are representations or character sets, you are not adhering to their (or any) standards, hence the weird place holder characters and missing or extra characters. What I recommend that you do, instead, is to display them in hexadecimal format, by using the
BitConverter class:
Code
ByteGenerator generator = new ByteGenerator(); // You can use initialize using a seed as well, if required.
BitConverter.ToString(generator.GenerateBytes(24));
This will output something similar to:
Code
26-5F-65-B2-C6-0F-1D-7C-D0-DB-10-95-7A-DA-BF-DA-89-18-9C-13-B0-D3-13-6A
If you know how the
hexadecimal positional system works, you can clearly see that there are exactly 24 bytes in there, which is exactly what you're asking for. Your code essentially generates 24 bytes as well and the way they're being counted is 'illogical' because you're not thinking straight in regards to the representation of said bytes and conversion mechanics. For example, the hexadecimal representation of the bytes above is invalid UTF8.
This is all a very simplified explanation, but you should understand that your code is actually generating 24 bytes, like you're asking it to do. I would recommend that you seriously consider looking more into character sets and what they actually are. Here's some reading material for you:
https://en.wikipedia.org/wiki/Character_encoding
http://kunststube.net/encoding/
https://javarevisited.blogspot.com/2015/...d-utf.html
Fun fact: Something you may or may not be aware of, is that the default string in the .NET Framework (<=4.8 at the time of writing) is encoded in UTF16.