WPF: Failing to perform ToHexString() Operation In C# [duplicate] - c#
This question already has answers here:
How do you convert a byte array to a hexadecimal string, and vice versa?
(53 answers)
Closed 7 years ago.
How do I convert a byte[] to a string? Every time I attempt it, I get
System.Byte[]
instead of the value.
Also, how do I get the value in Hex instead of a decimal?
There is a built in method for this:
byte[] data = { 1, 2, 4, 8, 16, 32 };
string hex = BitConverter.ToString(data);
Result: 01-02-04-08-10-20
If you want it without the dashes, just remove them:
string hex = BitConverter.ToString(data).Replace("-", string.Empty);
Result: 010204081020
If you want a more compact representation, you can use Base64:
string base64 = Convert.ToBase64String(data);
Result: AQIECBAg
.Net5.0 Update
Thanks to #antoninkriz's benchmark comparison we can see that Convert.ToHexString is by far the clear winner today
You'd be foolish to use anything other than Convert.ToHexString. In my opinion it clearly wins in: readability, performance, safety
The rest of this is from before Apr 10, 2012:
I thought I would attempt to compare the speed of each of the methods listed here for the hell of it. I based the speed testing code off this.
The result is that BitConverter+String.Replace seems to be faster than most other simple ways. But the speed can be improved with algorithms like Nathan Moinvaziri's ByteArrayToHexString or Kurt's ToHex.
I also found it interesting that string.Concat and string.Join are much slower than StringBuilder implementations for long strings, but similar for shorter arrays. Probably due to expanding the StringBuilder on the longer strings, so setting the initial size should negate this difference.
Took each bit of code from an answer here:
BitConvertRep = Answer by Guffa, BitConverter and String.Replace (I'd recommend for most cases, [edit:] where you can't use Convert.ToHexString)
StringBuilder = Answer by Quintin Robinson, foreach char StringBuilder.Append
LinqConcat = Answer by Michael Buen, string.Concat of Linq built array
LinqJoin = Answer by mloskot, string.Join of Linq built array
LinqAgg = Answer by Matthew Whited, IEnumerable.Aggregate with StringBuilder
ToHex = Answer by Kurt, sets chars in an array, using byte values to get hex
ByteArrayToHexString = Answer by Nathan Moinvaziri, approx same speed as the ToHex above, and is probably easier to read (I'd recommend for speed, [edit:] where you can't use Convert.ToHexString)
ToHexFromTable = Linked in answer by Nathan Moinvaziri, for me this is near the same speed as the above 2 but requires an array of 256 strings to always exist
With: LONG_STRING_LENGTH = 1000 * 1024;
BitConvertRep calculation Time Elapsed 27,202 ms (fastest built in/simple)
StringBuilder calculation Time Elapsed 75,723 ms (StringBuilder no reallocate)
LinqConcat calculation Time Elapsed 182,094 ms
LinqJoin calculation Time Elapsed 181,142 ms
LinqAgg calculation Time Elapsed 93,087 ms (StringBuilder with reallocating)
ToHex calculation Time Elapsed 19,167 ms (fastest)
With: LONG_STRING_LENGTH = 100 * 1024;, Similar results
BitConvertReplace calculation Time Elapsed 3431 ms
StringBuilder calculation Time Elapsed 8289 ms
LinqConcat calculation Time Elapsed 21512 ms
LinqJoin calculation Time Elapsed 19433 ms
LinqAgg calculation Time Elapsed 9230 ms
ToHex calculation Time Elapsed 1976 ms
With: int MANY_STRING_COUNT = 1000; int MANY_STRING_LENGTH = 1024;
(Same byte count as first test but in different arrays)
BitConvertReplace calculation Time Elapsed 25,680 ms
StringBuilder calculation Time Elapsed 78,411 ms
LinqConcat calculation Time Elapsed 101,233 ms
LinqJoin calculation Time Elapsed 99,311 ms
LinqAgg calculation Time Elapsed 84,660 ms
ToHex calculation Time Elapsed 18,221 ms
With: int MANY_STRING_COUNT = 2000; int MANY_STRING_LENGTH = 20;
BitConvertReplace calculation Time Elapsed 1347 ms
StringBuilder calculation Time Elapsed 3234 ms
LinqConcat calculation Time Elapsed 5013 ms
LinqJoin calculation Time Elapsed 4826 ms
LinqAgg calculation Time Elapsed 3589 ms
ToHex calculation Time Elapsed 772 ms
Testing code I used:
void Main()
{
int LONG_STRING_LENGTH = 100 * 1024;
int MANY_STRING_COUNT = 1024;
int MANY_STRING_LENGTH = 100;
var source = GetRandomBytes(LONG_STRING_LENGTH);
List<byte[]> manyString = new List<byte[]>(MANY_STRING_COUNT);
for (int i = 0; i < MANY_STRING_COUNT; ++i)
{
manyString.Add(GetRandomBytes(MANY_STRING_LENGTH));
}
var algorithms = new Dictionary<string,Func<byte[], string>>();
algorithms["BitConvertReplace"] = BitConv;
algorithms["StringBuilder"] = StringBuilderTest;
algorithms["LinqConcat"] = LinqConcat;
algorithms["LinqJoin"] = LinqJoin;
algorithms["LinqAgg"] = LinqAgg;
algorithms["ToHex"] = ToHex;
algorithms["ByteArrayToHexString"] = ByteArrayToHexString;
Console.WriteLine(" === Long string test");
foreach (var pair in algorithms) {
TimeAction(pair.Key + " calculation", 500, () =>
{
pair.Value(source);
});
}
Console.WriteLine(" === Many string test");
foreach (var pair in algorithms) {
TimeAction(pair.Key + " calculation", 500, () =>
{
foreach (var str in manyString)
{
pair.Value(str);
}
});
}
}
// Define other methods and classes here
static void TimeAction(string description, int iterations, Action func) {
var watch = new Stopwatch();
watch.Start();
for (int i = 0; i < iterations; i++) {
func();
}
watch.Stop();
Console.Write(description);
Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds);
}
//static byte[] GetRandomBytes(int count) {
// var bytes = new byte[count];
// (new Random()).NextBytes(bytes);
// return bytes;
//}
static Random rand = new Random();
static byte[] GetRandomBytes(int count) {
var bytes = new byte[count];
rand.NextBytes(bytes);
return bytes;
}
static string BitConv(byte[] data)
{
return BitConverter.ToString(data).Replace("-", string.Empty);
}
static string StringBuilderTest(byte[] data)
{
StringBuilder sb = new StringBuilder(data.Length*2);
foreach (byte b in data)
sb.Append(b.ToString("X2"));
return sb.ToString();
}
static string LinqConcat(byte[] data)
{
return string.Concat(data.Select(b => b.ToString("X2")).ToArray());
}
static string LinqJoin(byte[] data)
{
return string.Join("",
data.Select(
bin => bin.ToString("X2")
).ToArray());
}
static string LinqAgg(byte[] data)
{
return data.Aggregate(new StringBuilder(),
(sb,v)=>sb.Append(v.ToString("X2"))
).ToString();
}
static string ToHex(byte[] bytes)
{
char[] c = new char[bytes.Length * 2];
byte b;
for(int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx)
{
b = ((byte)(bytes[bx] >> 4));
c[cx] = (char)(b > 9 ? b - 10 + 'A' : b + '0');
b = ((byte)(bytes[bx] & 0x0F));
c[++cx] = (char)(b > 9 ? b - 10 + 'A' : b + '0');
}
return new string(c);
}
public static string ByteArrayToHexString(byte[] Bytes)
{
StringBuilder Result = new StringBuilder(Bytes.Length*2);
string HexAlphabet = "0123456789ABCDEF";
foreach (byte B in Bytes)
{
Result.Append(HexAlphabet[(int)(B >> 4)]);
Result.Append(HexAlphabet[(int)(B & 0xF)]);
}
return Result.ToString();
}
Also another answer with a similar process, I haven't compared our results yet.
Hex, Linq-fu:
string.Concat(ba.Select(b => b.ToString("X2")).ToArray())
UPDATE with the times
As noted by #RubenBartelink, the code that don't have a conversion of IEnumerable<string> to an array: ba.Select(b => b.ToString("X2")) does not work prior to 4.0, the same code is now working on 4.0.
This code...
byte[] ba = { 1, 2, 4, 8, 16, 32 };
string s = string.Concat(ba.Select(b => b.ToString("X2")));
string t = string.Concat(ba.Select(b => b.ToString("X2")).ToArray());
Console.WriteLine (s);
Console.WriteLine (t);
...prior to .NET 4.0, the output is:
System.Linq.Enumerable+<CreateSelectIterator>c__Iterator10`2[System.Byte,System.String]
010204081020
On .NET 4.0 onwards, string.Concat has an overload that accepts IEnumerable. Hence on 4.0, the above code will have same output for both variables s and t
010204081020
010204081020
Prior to 4.0, ba.Select(b => b.ToString("X2")) goes to overload (object arg0), the way for the IEnumerable<string> to go to a proper overload, i.e. (params string[] values), is we need to convert the IEnumerable<string> to string array. Prior to 4.0, string.Concat has 10 overload functions, on 4.0 it is now 12
Here is another method:
public static string ByteArrayToHexString(byte[] Bytes)
{
StringBuilder Result = new StringBuilder(Bytes.Length * 2);
string HexAlphabet = "0123456789ABCDEF";
foreach (byte B in Bytes)
{
Result.Append(HexAlphabet[(int)(B >> 4)]);
Result.Append(HexAlphabet[(int)(B & 0xF)]);
}
return Result.ToString();
}
public static byte[] HexStringToByteArray(string Hex)
{
byte[] Bytes = new byte[Hex.Length / 2];
int[] HexValue = new int[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
for (int x = 0, i = 0; i < Hex.Length; i += 2, x += 1)
{
Bytes[x] = (byte)(HexValue[Char.ToUpper(Hex[i + 0]) - '0'] << 4 |
HexValue[Char.ToUpper(Hex[i + 1]) - '0']);
}
return Bytes;
}
Alternatively, you could pre-build the translation table like so to achieve even faster results:
http://blogs.msdn.com/b/blambert/archive/2009/02/22/blambert-codesnip-fast-byte-array-to-hex-string-conversion.aspx
I like using extension methods for conversions like this, even if they just wrap standard library methods. In the case of hexadecimal conversions, I use the following hand-tuned (i.e., fast) algorithms:
public static string ToHex(this byte[] bytes)
{
char[] c = new char[bytes.Length * 2];
byte b;
for(int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx)
{
b = ((byte)(bytes[bx] >> 4));
c[cx] = (char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30);
b = ((byte)(bytes[bx] & 0x0F));
c[++cx]=(char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30);
}
return new string(c);
}
public static byte[] HexToBytes(this string str)
{
if (str.Length == 0 || str.Length % 2 != 0)
return new byte[0];
byte[] buffer = new byte[str.Length / 2];
char c;
for (int bx = 0, sx = 0; bx < buffer.Length; ++bx, ++sx)
{
// Convert first half of byte
c = str[sx];
buffer[bx] = (byte)((c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0')) << 4);
// Convert second half of byte
c = str[++sx];
buffer[bx] |= (byte)(c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0'));
}
return buffer;
}
Well I don't convert bytes to hex often so I have to say I don't know if there is a better way then this, but here is a way to do it.
StringBuilder sb = new StringBuilder();
foreach (byte b in myByteArray)
sb.Append(b.ToString("X2"));
string hexString = sb.ToString();
I thought I should provide an answer. From my test this method is the fastest
public static class Helper
{
public static string[] HexTbl = Enumerable.Range(0, 256).Select(v => v.ToString("X2")).ToArray();
public static string ToHex(this IEnumerable<byte> array)
{
StringBuilder s = new StringBuilder();
foreach (var v in array)
s.Append(HexTbl[v]);
return s.ToString();
}
public static string ToHex(this byte[] array)
{
StringBuilder s = new StringBuilder(array.Length*2);
foreach (var v in array)
s.Append(HexTbl[v]);
return s.ToString();
}
}
Very fast extension methods (with reversal):
public static class ExtensionMethods {
public static string ToHex(this byte[] data) {
return ToHex(data, "");
}
public static string ToHex(this byte[] data, string prefix) {
char[] lookup = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
int i = 0, p = prefix.Length, l = data.Length;
char[] c = new char[l * 2 + p];
byte d;
for(; i < p; ++i) c[i] = prefix[i];
i = -1;
--l;
--p;
while(i < l) {
d = data[++i];
c[++p] = lookup[d >> 4];
c[++p] = lookup[d & 0xF];
}
return new string(c, 0, c.Length);
}
public static byte[] FromHex(this string str) {
return FromHex(str, 0, 0, 0);
}
public static byte[] FromHex(this string str, int offset, int step) {
return FromHex(str, offset, step, 0);
}
public static byte[] FromHex(this string str, int offset, int step, int tail) {
byte[] b = new byte[(str.Length - offset - tail + step) / (2 + step)];
byte c1, c2;
int l = str.Length - tail;
int s = step + 1;
for(int y = 0, x = offset; x < l; ++y, x += s) {
c1 = (byte)str[x];
if(c1 > 0x60) c1 -= 0x57;
else if(c1 > 0x40) c1 -= 0x37;
else c1 -= 0x30;
c2 = (byte)str[++x];
if(c2 > 0x60) c2 -= 0x57;
else if(c2 > 0x40) c2 -= 0x37;
else c2 -= 0x30;
b[y] = (byte)((c1 << 4) + c2);
}
return b;
}
}
Beats all the others in the speed test above:
=== Long string test
BitConvertReplace calculation Time Elapsed 2415 ms
StringBuilder calculation Time Elapsed 5668 ms
LinqConcat calculation Time Elapsed 11826 ms
LinqJoin calculation Time Elapsed 9323 ms
LinqAgg calculation Time Elapsed 7444 ms
ToHexTable calculation Time Elapsed 1028 ms
ToHexAcidzombie calculation Time Elapsed 1035 ms
ToHexPatrick calculation Time Elapsed 814 ms
ToHexKurt calculation Time Elapsed 1604 ms
ByteArrayToHexString calculation Time Elapsed 1330 ms
=== Many string test
BitConvertReplace calculation Time Elapsed 2238 ms
StringBuilder calculation Time Elapsed 5393 ms
LinqConcat calculation Time Elapsed 9043 ms
LinqJoin calculation Time Elapsed 9131 ms
LinqAgg calculation Time Elapsed 7324 ms
ToHexTable calculation Time Elapsed 968 ms
ToHexAcidzombie calculation Time Elapsed 969 ms
ToHexPatrick calculation Time Elapsed 956 ms
ToHexKurt calculation Time Elapsed 1547 ms
ByteArrayToHexString calculation Time Elapsed 1277 ms
Just to add one more answer to the pile, there is a System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary class that I've used which can convert bytes to and from hex:
string hex = new SoapHexBinary(bytes).ToString();
byte[] bytes = SoapHexBinary.Parse(hex).Value;
Not sure how it compares (benchmark) to other implementations, but IMO it is pretty simple -- especially for converting from hex back into bytes.
With:
byte[] data = new byte[] { 0x01, 0x02, 0x03, 0x0D, 0x0E, 0x0F };
string hex = string.Empty;
data.ToList().ForEach(b => hex += b.ToString("x2"));
// use "X2" for uppercase hex letters
Console.WriteLine(hex);
Result: 0102030d0e0f
You have to know the encoding of the string represented in bytes, but you can say System.Text.UTF8Encoding.GetString(bytes) or System.Text.ASCIIEncoding.GetString(bytes). (I'm doing this from memory, so the API may not be exactly correct, but it's very close.)
For the answer to your second question, see this question.
Here is a extension method for byte array (byte[]), e.g.,
var b = new byte[] { 15, 22, 255, 84, 45, 65, 7, 28, 59, 10 };
Console.WriteLine(b.ToHexString());
public static class HexByteArrayExtensionMethods
{
private const int AllocateThreshold = 256;
private const string UpperHexChars = "0123456789ABCDEF";
private const string LowerhexChars = "0123456789abcdef";
private static string[] upperHexBytes;
private static string[] lowerHexBytes;
public static string ToHexString(this byte[] value)
{
return ToHexString(value, false);
}
public static string ToHexString(this byte[] value, bool upperCase)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
if (value.Length == 0)
{
return string.Empty;
}
if (upperCase)
{
if (upperHexBytes != null)
{
return ToHexStringFast(value, upperHexBytes);
}
if (value.Length > AllocateThreshold)
{
return ToHexStringFast(value, UpperHexBytes);
}
return ToHexStringSlow(value, UpperHexChars);
}
if (lowerHexBytes != null)
{
return ToHexStringFast(value, lowerHexBytes);
}
if (value.Length > AllocateThreshold)
{
return ToHexStringFast(value, LowerHexBytes);
}
return ToHexStringSlow(value, LowerhexChars);
}
private static string ToHexStringSlow(byte[] value, string hexChars)
{
var hex = new char[value.Length * 2];
int j = 0;
for (var i = 0; i < value.Length; i++)
{
var b = value[i];
hex[j++] = hexChars[b >> 4];
hex[j++] = hexChars[b & 15];
}
return new string(hex);
}
private static string ToHexStringFast(byte[] value, string[] hexBytes)
{
var hex = new char[value.Length * 2];
int j = 0;
for (var i = 0; i < value.Length; i++)
{
var s = hexBytes[value[i]];
hex[j++] = s[0];
hex[j++] = s[1];
}
return new string(hex);
}
private static string[] UpperHexBytes
{
get
{
return (upperHexBytes ?? (upperHexBytes = new[] {
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
"C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
"E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
"F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF" }));
}
}
private static string[] LowerHexBytes
{
get
{
return (lowerHexBytes ?? (lowerHexBytes = new[] {
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
"b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
"c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df",
"e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff" }));
}
}
}
You combine LINQ with string methods:
string hex = string.Join("",
bin.Select(
bin => bin.ToString("X2")
).ToArray());
No one here mentioned the reason why you get the "System.Byte[]" string instead of the value, so I will.
When an object is implicitly cast to a String, the program will default to the object's public String ToString() method which is inherited from System.Object:
public virtual string ToString()
{
return this.GetType().ToString();
}
If you find that you are often making this conversion, you could simply create a wrapper class and override this method like so:
public override string ToString()
{
// do the processing here
// return the nicely formatted string
}
Now each time you print this wrapper object you will get your value instead of the value from this.GetType().ToString().
As others have said it depends on the encoding of the values in the byte array. Despite this you need to be very careful with this sort of thing or you may try to convert bytes that are not handled by the chosen encoding.
Jon Skeet has a good article about encoding and unicode in .NET. Recommended reading.
I think I made a faster byte array to string convertor:
public static class HexTable
{
private static readonly string[] table = BitConverter.ToString(Enumerable.Range(0, 256).Select(x => (byte)x).ToArray()).Split('-');
public static string ToHexTable(byte[] value)
{
StringBuilder sb = new StringBuilder(2 * value.Length);
for (int i = 0; i < value.Length; i++)
sb.Append(table[value[i]]);
return sb.ToString();
}
And the test set up:
static void Main(string[] args)
{
const int TEST_COUNT = 10000;
const int BUFFER_LENGTH = 100000;
Random random = new Random();
Stopwatch sw = new Stopwatch();
Stopwatch sw2 = new Stopwatch();
byte[] buffer = new byte[BUFFER_LENGTH];
random.NextBytes(buffer);
sw.Start();
for (int j = 0; j < TEST_COUNT; j++)
HexTable.ToHexTable(buffer);
sw.Stop();
sw2.Start();
for (int j = 0; j < TEST_COUNT; j++)
ToHexChar.ToHex(buffer);
sw2.Stop();
Console.WriteLine("Hex Table Elapsed Milliseconds: {0}", sw.ElapsedMilliseconds);
Console.WriteLine("ToHex Elapsed Milliseconds: {0}", sw2.ElapsedMilliseconds);
}
The ToHexChar.ToHEx() method is the ToHex() method shown previously.
Results are as follows:
HexTable = 11808 ms
ToHEx = 12168ms
It may not look that much of a difference, but it's still faster :)
I'm not sure if you need perfomance for doing this, but here is the fastest method to convert byte[] to hex string that I can think of :
static readonly char[] hexchar = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
public static string HexStr(byte[] data, int offset, int len, bool space = false)
{
int i = 0, k = 2;
if (space) k++;
var c = new char[len * k];
while (i < len)
{
byte d = data[offset + i];
c[i * k] = hexchar[d / 0x10];
c[i * k + 1] = hexchar[d % 0x10];
if (space && i < len - 1) c[i * k + 2] = ' ';
i++;
}
return new string(c, 0, c.Length);
}
Nice way to do this with LINQ...
var data = new byte[] { 1, 2, 4, 8, 16, 32 };
var hexString = data.Aggregate(new StringBuilder(),
(sb,v)=>sb.Append(v.ToString("X2"))
).ToString();
private static string GuidToRaw(Guid guid)
{
byte[] bytes = guid.ToByteArray();
int сharCount = bytes.Length * 2;
char[] chars = new char[сharCount];
int index = 0;
for (int i = 0; i < сharCount; i += 2)
{
byte b = bytes[index++];
chars[i] = GetHexValue((int)(b / 16));
chars[i + 1] = GetHexValue((int)(b % 16));
}
return new string(chars, 0, chars.Length);
}
private static char GetHexValue(int i)
{
return (char)(i < 10 ? i + 48 : i + 55);
}
Related
How to out all the int values from a string array and store that int values in another array
There are words and int values in a string array. My goal is to retrieve the int values from another array. I have seen two methods for converting and finding int values from a string array. To get all the int values from the string, I first create another int array and use an Array.ConvertAll init. The second method is to loop through isDigit(). Now, the problem is that I cannot find a way to store that value in an int array that has been converted to an int. The final goal is to find the minimum and maximum value from the converted values. string[] strArray1 = { "Bautik", "99", "Sagar", "3", "Tisha", "12", "Riya", "109" }; int result; int[] num = Array.ConvertAll(strArray1, x => { bool convertStrIntoInt = int.TryParse(x, out int result); return result; }); In here, I don't how to get the result outside of it to do a sort to find min and max values.
I don't understand what you want but if you want only int then use this List<int> list = new List<int>(); string[] strArray1 = { "Bautik", "99", "Sagar", "3", "Tisha", "12", "Riya", "109" }; foreach (string str in strArray1) { if (int.TryParse(str, out int val)) { list.Add(val); } } int[] vs = list.ToArray(); now all the int values are stored in vs array, if there are some words which contains the int value and you want them to be extracted you can use regex to find the digits in word also
I'd use LINQ for this: string[] strArray1 = { "Bautik", "99", "Sagar", "3", "Tisha", "12", "Riya", "109" }; int[] num = ( from x in strArray1 let n = int.TryParse(x, out int n) ? (int?)n : null where n.HasValue select n.Value ).ToArray(); That outputs: Then you can do this: int max = num.Max(); int min = num.Min();
Little optimized solution could be something like below string[] strArray1 = { "Bautik", "99", "Sagar", "3", "Tisha", "12", "Riya", "109" }; var numArray = strArray1.Where(var=> new Regex(#"^\d+").IsMatch(var)).ToArray(); var res = Array.ConvertAll(numArray,s => int.Parse(s)); If we don't want to use Regex can try something like below string[] strArray1 = { "Bautik", "99", "Sagar", "3", "Tisha", "12", "Riya", "109" }; int testNum; var numArray = strArray1.Where(var=> int.TryParse(var,out testNum)).ToArray(); var res = Array.ConvertAll(numArray,s => int.Parse(s)); You can then get max and min value using res.Min(), res.Max() This should give you a starting point for your problem
You can try Regex like below : string[] strArray1 = {"Bautik", "99", "Sagar", "3", "Tisha", "12", "Riya", "109"}; int[] num = strArray1.Where(v => Regex.IsMatch(v, #"^\d+$")).Select(int.Parse).ToArray(); int min = num.Min(); int max = num.Max(); As you don't want to use Regex, you can go with your solution, just do a small modification to get your desired result. Try this : string[] strArray1 = { "Bautik", "99", "Sagar", "3", "Tisha", "12", "Riya", "109" }; int[] num = Array.ConvertAll(strArray1, x => { bool convertStrIntoInt = int.TryParse(x, out int result); return result; }).Where(x => x > 0).ToArray(); int max = num.OrderByDescending(c => c).ToArray()[0]; int min = num.OrderBy(c => c).ToArray()[0];
Here is another way to get int values from a string array into an int array. Try it on dotnetfiddle. public static class Extensions { public static int[] ToIntegerArray(this string[] sender) { var intArray = Array .ConvertAll(sender, (input) => new { IsInteger = int.TryParse(input, out var integerValue), Value = integerValue }) .Where(result => result.IsInteger) .Select(result => result.Value) .ToArray(); return intArray; } } Use string[] strArray1 = { "Bautik", "99", "Sagar", "3", "Tisha", "12", "Riya", "109" }; int[] intArray = strArray1.ToIntegerArray(); Array.Sort(intArray); foreach (var value in intArray) { Console.WriteLine(value); } Console.WriteLine($"Min: {intArray.Min()}"); Console.WriteLine($"Max: {intArray.Max()}");
Targeting your intial question: I don't [know] how to get the result outside of it to do a sort to find min and max values. You simply can't get a complete solution for your Problem using ConvertAll() with a "normal" int. So if we take a look at your result: int[] num = Array.ConvertAll(strArray1, x => { bool convertStrIntoInt = int.TryParse(x, out int result); return result; }); // num: int[8] { 0, 99, 0, 3, 0, 12, 0, 109 } We can see each word will result in a 0, since 0 will be returned if the parsing failed - see: Int32.TryParse(...). And therefore it is impossible to differentiate between an real 0 in your input or a word, which could not be parsed. But we can tweek the convert a little bit by using Nullable<int>/int? int?[] num = Array.ConvertAll(strArray1, x => { return (int?)( int.TryParse(x, out int result) ? result : null); }); // num: Nullable<int>[8] { null, 99, null, 3, null, 12, null, 109 } So with this we are able to differ between a 0 and a word - represented by null. Now you can perform other operations like num.Max() and num.Min(). If you need an int[] array, you have add some more function calls. int[] num = Array.ConvertAll(strArray1, x => { return (int?)( int.TryParse(x, out int result) ? result : null); }).OfType<int>().ToArray(); //num: int[4] { 99, 3, 12, 109 } So this is not quite optimal. My solution for this would be a simple loop. // Your intput string[] strArray1 = { "Bautik", "99", "Sagar", "3", "Tisha", "12", "Riya", "109" }; // Output Variables List<int> result = new(); int min = int.MaxValue; int max = int.MinValue; // Loop foreach( string item in strArray1) { if(int.TryParse(item, out int value)) { result.Add(value); min = min > value ? value : min; max = max < value ? value : max; } } // Output // result: List<int>[4] { 99, 3, 12, 109 } // min: 3 // max: 109 As already mentioned by Gian Paolo in the comments of this answer working with a List<int> is much easier than working with an int[] ..., but if you really need an array, then you can just call ToArray(). int[] resultArray = result.ToArray(); Which results in int[4] { 99, 3, 12, 109 }.
Conversion of array string to array ulong in c#
I have a array of strings having values string[] words = {"0B", "00", " 00", "00", "00", "07", "3F", "14", "1D"}; I need it to convert into array of ulong ulong[] words1; How should I do it in c# I think I should add some background. The data in the string is coming from textbox and I need to write the content of this textbox in the hexUpDown.Value parameter.
var ulongs = words.Select(x => ulong.Parse(x, NumberStyles.HexNumber)).ToArray();
If you need to combine the bytes into 64 bit values then try this (assumes correct endieness). string[] words = { "0B", "00", " 00", "00", "00", "07", "3F", "14", "1D" }; var words64 = new List<string>(); int wc = 0; var s = string.Empty; var results = new List<ulong>(); // Concat string to make 64 bit words foreach (var word in words) { // remove extra whitespace s += word.Trim(); wc++; // Added the word when it's 64 bits if (wc % 4 == 0) { words64.Add(s); wc = 0; s = string.Empty; } } // If there are any leftover bits, append those if (!string.IsNullOrEmpty(s)) { words64.Add(s); } // Now attempt to convert each string to a ulong foreach (var word in words64) { ulong r; if (ulong.TryParse(word, System.Globalization.NumberStyles.AllowHexSpecifier, System.Globalization.CultureInfo.InvariantCulture, out r)) { results.Add(r); } } Results: List<ulong>(3) { 184549376, 474900, 29 }
How to measure the amount of times 0 & 1 occurs
Here is the code that outputs 1 or 0 depending on the equality of the 2 arrays static void Main(string[] args) { while (true) { Console.WriteLine(Here()); } Here is where the magic happens. static int Here() { Random rnd = new Random(); PlayerInput(); int[] intarray = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; string[] sarray = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; int i = rnd.Next(10); // creates a number between 1 and 10 int x = rnd.Next(10); string iarray = intarray[x].ToString(); if (iarray == sarray[i]) { return 1; } else { return 0; } } it outputs 0 when the two arrays don't equal and 1 vise versa. now I want to count the amount of times it outputs 0 & 1. Questions: How could I do that? Should I transfer the output to an array for easier manipulation?
Unless I'm misunderstanding your question, it seems like you could simply have two counter variables: static void Main(string[] args) { int totalOnes = 0; int totalZeroes = 0; while (true) // need to replace this with something that will actually exit!! { int ret = Here(); if (ret == 1) totalOnes++; else totalZeroes++; Console.WriteLine(ret); } Console.WriteLine("Total Ones: {0} Total Zeroes: {1}", totalOnes, totalZeroes); } EDIT: Thanks to L J for pointing out that your while loop will never exit since you have while (true). You need to address that.
like this static void Main(string[] args) { var zeroCount = 0; var oneCount = 0; while (true) { var result = Here(); if (result == 1) oneCount++; if (result == 0) zeroCount++; Console.WriteLine($"Actual result {result}, zero count {zeroCount}, One count {oneCount}"); } }
static int Here() { Random rnd = new Random(); PlayerInput(); int[] intarray = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; string[] sarray = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; **var Count1 = 0; var Count0 = 0;** int i = rnd.Next(10); // creates a number between 1 and 10 int x = rnd.Next(10); string iarray = intarray[x].ToString(); if (iarray == sarray[i]) { **Count1++;** return 1; } else { **Count0++;** return 0; } } Count0 will contain the number of times 0 was outputted. Count1 will contain the number of times 1 was outputted.
Group items of array by three using Linq
I have an Array of bytes, representing the RGB values of an image. How could I group each offset of 3 values (RGB) of this array to apply my tweaks (like removing the repeated colors), maybe using Linq? ["120", "100", "10", "120", "100", "10", "10", "60", "110"] to ["120", "100", "10", "10", "60", "110"]
You can use Select to add index to your enumeration and later group by index / 3. A bit of post-processing on each of the groups and you should be able to get what you want: var grouped = source.Select((x,i) => new { x, i }) .GroupBy(x -> x.i / 3) .Select(g => g.ToList()) .Select(g => new { R = g[0], G = g[1], B = g[2] }) .Distinct(); But that feels quite ugly. If I were you I'd probably write a simple custom LINQ method (an extension method on IEnumerable<int>) to do this more efficiently.
Shorter version that gets the distinct RGB values and their indexes: string[] a = { "120", "100", "10", "120", "100", "10", "10", "60", "110" }; var l = Enumerable.Range(0, a.Length / 3) .ToLookup(i => new { R = a[i * 3], G = a[i * 3 + 1], B = a[i * 3 + 2] });
If you don't mind using a loop instead of Linq: class Program { static void Main(string[] args) { byte[] array = new byte[] { 120, 100, 10, 120, 100, 10, 10, 60, 110 }; List<byte[]> grouped = new List<byte[]>(); // This loop will populate the list grouped with arrays of 3 bytes each, each representing an value for RGB for(int i = 0; i + 2 < array.Length; i += 3) { byte[] currentColor = new byte[] { array[i], array[i + 1], array[i + 2] }; grouped.Add(currentColor); } // Here you will remove repeated elements for RGB // Notice you will have to create the ByteArrayComparer class, you will find the code right under this one var noRepeatedElements = grouped.Distinct<byte[]>(new ByteArrayComparer()); // Print the non repeated elements for testing purposes foreach(var rgb in noRepeatedElements) { foreach(var value in rgb) { Console.Write($"\"{value}\""); } } Console.ReadKey(); } } Where ByteArrayComparer is the following class // This class will compare two distinct byte arrays and check if their elements are the same public class ByteArrayComparer : IEqualityComparer<byte[]> { public bool Equals(byte[] x, byte[] y) { int smallerArrayLength = Math.Min(x.Length, y.Length); bool elementsWithSameValue = true; for(int i = 0; i < smallerArrayLength; i++) { // If there is a single element which is different, we know the arrays are different and can break the loop. if(x[i] != y[i]) { elementsWithSameValue = false; break; } } return elementsWithSameValue; } public int GetHashCode(byte[] obj) { int hash = 0; for(int i = 0; i < obj.Length; i++) { hash += obj[i].GetHashCode(); } return hash; } } Note that grouped now is a List of arrays of bytes. Each element in grouped has three elements, representing a single RGB value. Now you can work with the rgb values as you please.
Using Microsoft's Reactive Framework Team's Interactive Extensions (NuGet "Ix-Main") you can do this: byte[] array = new byte[] { 120, 100, 10, 120, 100, 10, 10, 60, 110 }; byte[] results = array .Buffer(3) .Distinct(xs => String.Join(",", xs)) .SelectMany(x => x) .ToArray(); That will give you { 120, 100, 10, 10, 60, 110 }.
Developing an effective barcode system/code
I'm sorry if the title is misleading but I have to develop the format for a barcode (either 1D or 2D, doesn't matter). The barcode needs to include a Purchase Order #, Bill of lading #, as well as the Line #, product ID # and quantity of each item that appears on the purchase order. Anyone have any ideas for doing this? Here is what I've come up with so far: PurchaseOrder # - Bill of Lading # | Product1ID Line# Qty | Product2ID Line# Qty| Product3... What the string for this idea may actually look like: VO12340000-APX132 * 65465 1 12 * 897965 2 5 * 98464 3 88 * This idea uses "*" as a break character to tell the difference between items as well as having a required length for each specific trait. To me it seems like there must be a better way to accomplish this. This idea would be very hard to have one of my company's suppliers implement as it is very complicated and precise. Any insight or ideas on how to accomplish this would be greatly appreciated. EDIT: Although I am using VB.NET. This is more of a general programming logic question.
We're going with QR Codes here. In your application you could use the plain text format and then process them with Regex. Also, they have redundancy and lots of free/open source software to support generation and reading.
There are other complex bar codes like HIBC LIC and HIBC PAS with implementations using Code39 or Code128 (http://www.hibcc.org/autoidupn/standards.htm). What is important is to use a symbology that will be able to generate a condensed bar code, in order to be readable by common bar code scanners. So you can go with Code39 or Code128 (GS1 family) and replace * with whatever (AIs/FUNC). If I was you I would go with Code93 Extended symbology leaving the content spec as it is. The following code is from a library I made in the past for almost all symbologies, that will give you what is needed to implement Code93 Extended. It's in C# but it's easy to convert it to VB.NET. Have in mind that you will have to modify it for your needs, and that it only generates a sequence of bars without drawing them. private static int[] C93Table = { 131112, 111213, 111312, 111411, 121113, 121212, 121311, 111114, 131211, 141111, 211113, 211212, 211311, 221112, 221211, 231111, 112113, 112212, 112311, 122112, 132111, 111123, 111222, 111321, 121122, 131121, 212112, 212211, 211122, 211221, 221121, 222111, 112122, 112221, 122121, 123111, 121131, 311112, 311211, 321111, 112131, 113121, 211131, 121221, 312111, 311121, 122211 }; static string[] C93TableX = { "bU", "aA", "aB", "aC", "aD", "aE", "aF", "aG", "aH", "aI", "aJ", "aK", "aL", "aM", "aN", "aO", "aP", "aQ", "aR", "aS", "aT", "aU", "aV", "aW", "aX", "aY", "aZ", "bA", "bB", "bC", "bD", "bE", " ", "cA", "cB", "cC", "cD", "cE", "cF", "cG", "cH", "cI", "cJ", "cK", "cL", "cM", "cN", "cO", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "cZ", "bF", "bG", "bH", "bI", "bJ", "bV", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bK", "bL", "bM", "bN", "bO", "bW", "dA", "dB", "dC", "dD", "dE", "dF", "dG", "dH", "dI", "dJ", "dK", "dL", "dM", "dN", "dO", "dP", "dQ", "dR", "dS", "dT", "dU", "dV", "dW", "dX", "dY", "dZ", "bP", "bQ", "bR", "bS", "bT" }; static string C93Set = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%abcd"; private void Code93X() { string source = request.Data; Error valid = Validate(source, 197, C93Set); if (valid != Error.None) { encoded = new Encoded() { Error = valid }; return; } StringBuilder adapt = new StringBuilder(); for (int i = 0; i < source.Length; i++) adapt.Append(C93TableX[(byte)source[i]]); Code93(adapt.ToString()); } private void Code93(string source) { StringBuilder bars = new StringBuilder(); bars.Append(111141); int c = 0, k = 0; int[] values = new int[source.Length + 1]; for (int i = 0; i < source.Length; i++) { values[i] = C93Set.IndexOf(source[i]); bars.Append(C93Table[values[i]]); } if (request.AddChecksum) { int weight = 1; for (int i = source.Length - 1; i >= 0; i--) { c += values[i] * weight; if (++weight == 21) weight = 1; } c %= 47; values[source.Length] = c; bars.Append(C93Table[c]); source += C93Set[c]; weight = 1; for (int i = source.Length - 1; i >= 0; i--) { k += values[i] + weight; if (++weight == 16) weight = 1; } k %= 47; bars.Append(C93Table[k]); if (request.DisplayChecksum) source += C93Set[k]; } bars.Append(1111411); source = string.Concat("*", source, "*"); encoded = new Encoded(bars.ToString(), source); } private Error Validate(string source, int maxLength, string set) { Error valid = Validate(source, maxLength); if (valid == Error.None) for (var i = 0; i < source.Length; i++) if (set.IndexOf(source[i]) < 0) { valid = Error.InvalidCharacters; break; } return valid; }