I have in input the string: "0080801D803480002A1168301FE16E09"
and when i convert it to byteArray with the code:
Convert.ToByte(inputWrite.Substring(i, 2), 16);
I get the byte array in first position = "0", but i need to have "00", so when i convert it again into a String a don't get "08" but "00" at the begining.
i get in the and the string "080801D80348002A1168301FE16E9" and like this i'm missing some important 0, that i need to convert then from this last string to byte again and to decimal values.
Once you have your byes in an array, there's no difference between 0 and 00.
What you need to do is, when converting those bytes back to a string, make sure you put any leading zeros back in. You can do this by calling
string byteAsTwoDigitString = myByte.ToString("X2");
The X says "as hexadecimal", the 2 says "with at least two digits".
You can also do this using LINQ:
public static byte[] StringToByteArray(string hex) {
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
You can also refer this
You seem to be confusing things. Because each byte is represented by two characters, bytes array will be two times shorter than the string. When parsing back, you have to make sure that each byte must be converted to two-characters string, even if it is less than 0x10, i.e. does not require second character.
That said, you can use following LINQ oneliner:
string convertedBack = string.Join(string.Empty, bytes.Select(x => x.ToString("X2")).ToArray());
Related
I have got this code from somewhere to convert hex string to normal string.
But I cannot understand this. Can anybody explain this please ?
In this string, The first line takes each two characters from the string and convert it to byte.
But, I dont understand why they are assigning array to only half length of byte array ?
Sometimes it gets error too, i.e if Inputstring length is 350, byte length would be 175, and char length is 87.5, and char array is assigned to 87 only, thats not enough to hold all the characters in byte array.
public static string HextoString(string InputText)
{
byte[] bb = Enumerable.Range(0, InputText.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(InputText.Substring(x, 2), 16))
.ToArray();
//return Convert.ToBase64String(bb);
char[] chars = new char[bb.Length / sizeof(char)];
System.Buffer.BlockCopy(bb, 0, chars, 0, bb.Length);
return new string(chars);
}
That is because .Where(x => x % 2 == 0) filters the input string to only those values, that have even indexes, so the output will have half the length of the original.
I have an int[]:
RXBuffer[0], RXBuffer[1],..., RXBuffer[9]
where each value represents an ASCII code, so 0x31 represents 1, 0x41 represents A.
How do I convert this to a 10 character string ?
So far I've tried Data = RxBuffer.ToString();. But it shows Data equals to System.Int32[] which is not what my data is.
How can I do this?
Assuming the "int array" is values in the 0-9 range (which is the only way that makes sense to convert an "int array" length 10 to a 10-character string) - a bit of an exotic way:
string s = new string(Array.ConvertAll(RXBuffer, x => (char)('0' + x)));
But pretty efficient (the char[] is right-sized automatically, and the string conversion is done just with math, instead of ToString()).
Edit: with the revision that makes it clear that these are actually ASCII codes, it becomes simpler:
string s = new string(Array.ConvertAll(RXBuffer, x => (char)x));
Although frankly, if the values are ASCII (or even unicode) it would be better to store it as a char[]; this covers the same range, takes half the space, and is just:
string s = new string(RXBuffer);
LolCoder
All you need is :
string.Join("",RXBuffer);
============== Or =================
int[] RXBuffer = {0,1,2,3,4,5,6,7,8,9};
string result = string.Join(",",RXBuffer);
Aim :
To convert a integer value first to hexstring and then to byte[].
Example :
Need to convert int:1024 to hexstring:400 to byte[]: 00000100 00000000
Method:
For converting from integer to hex string i tried below code
int i=1024;
string hexString = i.ToString("X");
i got hexstring value as "400". Then i tried converting hex string to byte[] using below code
byte[] value = HexStringToByteArray(hexValue);
/* function for converting hexstring to byte array */
public byte[] HexStringToByteArray(string hex)
{
int NumberChars = hex.Length;
if(NumberChars %2==1)
throw new Exception("Hex string cannot have an odd number of digits.");
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
return bytes;
}
Error:
Here i got the exception "Hex String cannot have a odd number of digits"
Solution: ??
You can force the ToString to return a specific number of digits:
string hexString = i.ToString("X08");
The exception is thrown by your own code. You can make your code more flexible to accept hex strings that have an odd number of digits:
if (hex.Length % 2 == 1) hex = "0"+hex;
Now you can remove the odd/even check, and your code will be alright.
Your code throws the exception you're seeing:
throw new Exception("Hex string cannot have an odd number of digits.");
You can improve the conversion method to also accept odd hex string lengths like this:
using System.Collections.Generic;
using System.Linq;
// ...
public byte[] HexStringToByteArray(string hex)
{
var result = new List<byte>();
for (int i = hex.Length - 1; i >= 0; i -= 2)
{
if (i > 0)
{
result.Insert(0, Convert.ToByte(hex.Substring(i - 1, 2), 16));
}
else
{
result.Insert(0, Convert.ToByte(hex.Substring(i, 1), 16));
}
}
return bytes.ToArray();
}
This code should iterate through the hex string from its end, adding new bytes to the beginning of the resulting list (that will be transformed into an array before returning the value). If a single digit remains, it will be treated separately.
Your hex string has an odd number of digits and you are explicitly checking for that and throwing the exception. You need to decide why you put this line of code in there and whether you need to remove that in favour of other logic.
Other options are:
add a "0" to the beginning of the string to make it even length
force whoever is calling that code to always provide an even length string
change the later code to deal with odd numbers of characters properly...
In comments you have suggested that the first is what you need to know in which case:
if(hex.Length%2==1)
hex = "0"+hex;
Put this at the beginning of your method and if you get an odd number in then you will add the zero to it automatically. You can of course then take out your later check and exception throw.
Of note is that you may want to validate the input string as hex or possibly just put a try catch round the conversion to make sure that it is a valid hex string.
Also since it isn't clear whether the string is a necessary intermediate step or just one that you think is necessary, you might be interested in C# int to byte[] which deals with converting to bytes without the intermediate string.
I'm converting a List<string> into a byte array like this:
Byte[] bArray = userList
.SelectMany(s => System.Text.Encoding.ASCII.GetByte(s))
.ToArray();
How can I convert it back to a List<string>? I tried using ASCII.GetString(s) in the code above, but GetString expected a byte[], not a single byte.
It's not possible to reverse your algorithm.
The problem can be seen if you consider what happens when you have two users called "ab" and "c". This will give the exact same bytes as if you have two users called "a" and "bc". There is no way to distinguish between these two cases with your approach.
Instead of inventing your own serialization format you could just the serialization that is built into the .NET framework, such as the BinaryFormatter.
As a bit of a sidenote, if you preserve the zero-byte string termination you can easily concatenate the strings and extract all information, e.g.
Byte[] bArray = userList
.SelectMany(s => System.Text.Encoding.ASCII.GetBytes(s + '\0')) // Add 0 byte
.ToArray();
List<string> names = new List<string>();
for (int i = 0; i < bArray.Length; i++)
{
int end = i;
while (bArray[end] != 0) // Scan for zero byte
end++;
var length = end - i;
var word = new byte[length];
Array.Copy(bArray, i, word, 0, length);
names.Add(ASCIIEncoding.ASCII.GetString(word));
i += length;
}
You need to insert a delimter between your strings so that you can split the big byte array back into the original users. The delimiter should be a character which cannot be part of a user name.
Example (assuming | cannot be part of a user name):
var bytes = System.Text.Encoding.ASCII.GetByte(string.Join("|", userList.ToArray()));
You can't do this since the delimiters of the array structure were lost in the SelectMany method.
What I need is very simple, but before I reinvent the wheel, I would like to know if something similar exist in the framework already.
I would like to encode (and decode) strings from a predefined characters table. I have many strings that contains few characters. Here is a string I would like to encode:
cn=1;pl=23;vf=3;vv=0
This string size is 20 chars, so 20 bytes.
In the string, I only use the following characters: cn=1;p23vf0
A total of 11 characters. So each character can be encoded with 4 bits only isn't ? Reducing the total amount of bytes used to 10.
Is there any existing method in .NET that can take a string in parameter and the reference table array and return the encoded bytes ?
char[] reference = "cn=1;p23vf0".ToCharArray();
string input = "cn=1;pl=23;vf=3;vv=0";
byte[] encoded = someClass.Encode(input, reference);
string decoded = someClass.Decode(encoded, reference);
Assert.AreEqual(input, decoded);
Any compression algorithm uses Huffman encoding. Which is basically what you are looking for here. That encoding isn't exposed as a class separately, it is part of the algorithm of the DeflateStream and GZipStream classes. Which is what you ought to use, as long as your strings are a reasonable size. If they are short then there isn't any point in encoding them.
Interresting question... There isn't anything built in the framework, but it can be done for example like this:
public static byte[] Encode(string input, string reference) {
int size = 1;
while ((1 << ++size) < reference.Length);
byte[] result = new byte[(size * input.Length + 7) / 8];
new BitArray(
input
.Select(c => {
int index = reference.IndexOf(c);
return Enumerable.Range(0, size).Select(i => (index & (1 << i)) != 0);
})
.SelectMany(a => a)
.ToArray()
).CopyTo(result, 0);
return result;
}
public static string Decode(byte[] encoded, int length, string reference) {
int size = 1;
while ((1 << ++size) < reference.Length);
return new String(
new BitArray(encoded)
.Cast<bool>()
.Take(length * size)
.Select((b, i) => new { Index = i / size, Bit = b })
.GroupBy(g => g.Index)
.Select(g => reference[g.Select((b, i) => (b.Bit ? 1 : 0) << i).Sum()])
.ToArray()
);
}
The code is a bit complicated, but that is because it works with any number of bits per character, not just four.
You encode the string like in your question, except the string contains twelve different characters, not eleven:
string reference = "cn=1;pl23vf0";
string input = "cn=1;pl=23;vf=3;vv=0";
byte[] encoded = Encode(input, reference);
To decode the string you also need the length of the original string, as that is impossible to tell from the length of the encoded data:
string decoded = Decode(encoded, input.Length, reference);
(Alternatively to supplying the length you could of course introduce an EOF character, or a padding character similar to how base64 pads the data.)
There's no out-of-the-box class that does exactly this, but it's not too hard using the BitArray class of .NET.
Once you have a bit-array, you can convert it to a string, or a packed byte representation.
// modify this as appropriate to divide your original input string...
public IEnumerable<string> Divide( string s )
{
for( int i = 0; i < s.Length; i += 2 )
yield return s.Substring( i, 2 );
}
public IEnumerable<bool> AsBoolArray( byte b )
{
var i = 4; // assume we only want 4-bits
while( i-- > 0 )
{
yield return (b & 0x01) != 0;
b >>= 1;
}
}
// define your own mapping table...
var mappingTable =
new Dictionary<string,int>() { {"cn", 1}, {"pl",23}, {"vf",3}, {"vv",0} /*...*/ };
var originalString = "cncnvfvvplvvplpl";
// encode the data by mapping each string to the dictionary...
var encodedData = DivideString( originalString ).Select( s => mappingTable[s] );
// then convert into a bitVector based on the boolean representation of each value...
// The AsBoolArray() method return the 4-bit encoded bool[] for each value
var packedBitVector =
new BitArray( encodedData.Select( x => AsBoolArray(x) ).ToArray() );
// you can use BitArray.CopyTo() to get the representation out as a packed int[]
I think if you want to minimize size of string it's better to use System.IO.Compression.GZipStream here. It's very simple and will likely to compress your string much more than 2 times.
There is nothing like that built into the Base Class Library. You will have to build your own.
Take a look at the Encoder class from System.Text - some elements may be of help.
Would the StringBuilder class be of any help?
You can use the CrytpAPI. here is a good example, including the methods to Encrypt and Decrypt a string. I don't think it will "compress" your data for you, though.