I'm trying to use an integer as the numerical representation of a string, for example, storing "ABCD" as 0x41424344. However, when it comes to output, I've got to convert the integer back into 4 ASCII characters. Right now, I'm using bit shifts and masking, as follows:
int value = 0x41424344;
string s = new string (
new char [] {
(char)(value >> 24),
(char)(value >> 16 & 0xFF),
(char)(value >> 8 & 0xFF),
(char)(value & 0xFF) });
Is there a cleaner way to do this? I've tried various casts, but the compiler, as expected, complained about it.
Characters are 16 bit, so you have to encode them into eight bit values to pack them in an integer. You can use the Encoding class to convert between characters and bytes, and the BitConverter class to convert between bytes and integer
Here is conversion both ways:
string original = "ABCD";
int number = BitConverter.ToInt32(Encoding.ASCII.GetBytes(original), 0);
string decoded = Encoding.ASCII.GetString(BitConverter.GetBytes(number));
Note that the order of the bytes in the integer depends on the endianess of the computer. On a little endian system the numeric value of "ABCD" will be 0x44434241. To get the reverse order, you can reverse the byte array:
byte[] data = Encoding.ASCII.GetBytes(original);
Array.Reverse(data);
int number = BitConverter.ToInt32(data, 0);
byte[] data2 = BitConverter.GetBytes(number);
Array.Reverse(data2);
string decoded = Encoding.ASCII.GetString(data2);
Or if you are using framework 3.5:
int number =
BitConverter.ToInt32(Encoding.ASCII.GetBytes(original).Reverse().ToArray() , 0);
string decoded =
Encoding.ASCII.GetString(BitConverter.GetBytes(number).Reverse().ToArray());
int value = 0x41424344;
string s = Encoding.ASCII.GetString(
BitConverter.GetBytes(value).Reverse().ToArray());
(The above assumes that you're running on a little-endian system. For big-endian you could just drop the .Reverse().ToArray() part, although if you are on a little-endian system then it would probably make more sense for you to just store "ABCD" as 0x44434241 in the first place, if possible.)
public string ConvertToHex(string asciiString)
{
string hex = "";
foreach (char c in asciiString)
{
int tmp = c;
hex += String.Format("{0:x2}", (uint)System.Convert.ToUInt32(tmp.ToString()));
}
return hex;
}
It will convert string to hex as you required.
public static string ToHexString(string value)
{
return value.Aggregate(new StringBuilder("0x"),
(sb, c) => sb.AppendFormat("{0:x2}", (int)c)).ToString();
}
if the string is never longer than 8 chars and a kind of Hexstring, you could use
the base variable 16 have a look at the Conversion functions from the Convert class.
string s = "ABCD";
uint i = Convert.ToUInt32( s, 16 );
MessageBox.Show( Convert.ToString( i, 16 ) );
regards
Oops
Related
I am using the float 16 Half type from here -
https://gist.github.com/vermorel/1d5c0212752b3e611faf84771ad4ff0d
I have defined the following method to convert a Half value to binary string:
static string HalfToBinaryString(Half value)
{
int bitCount = Marshal.SizeOf(value) * 8;
string s = String.Empty;
// value is the value you want to convert to a string (double, long, int, ...)
foreach (byte b in Half.GetBytes(value))
{
s += Convert.ToString(b, 2).PadLeft(8, '0'); // for hex. For binary, use 2 and 8. For octal, use 8 and 3
}
return s;
}
And the following method to convert from binary string value to Half:
static Half HalfFromBinaryString(string bstra)
{
int intValue = Convert.ToInt16(bstra, 2);
return (Half)BitConverter.ToInt16(Half.GetBytes(intValue), 0);
}
When I perform the following division, I get:
string dividend = "11001001001111111";
Half result = (Half)(Convert.ToSingle(Convert.ToInt32(dividend, 2)) / 65536.0);
var rawbits = HalfToBinaryString(result);
//result = 1.571289
//rawbits = "0100100100111110"
However when I perform the reverse operation, I get:
Half halfval = HalfFromBinaryString(rawbits);
//halfval = 29840 //(instead of 1.571289)
How do I convert from a 16 bit binary string representation to the correct Half value (1.571289)?
Your implementation of HalfFromBinaryString is wrong, because your code is really just interpreting the string as an int in binary, and casting that int to a Half and returning. You could simplify your return line to return (Half)intValue; and it will still do the same thing.
Since the Half struct provides you with a ToHalf(ushort) method, you can use it to create a Half. Essentially, parse the string as a ushort, and pass the ushort into ToHalf:
ushort bits = Convert.ToUInt16(bstra, 2);
return Half.ToHalf(bits);
Your HalfToBinaryString method can also be simplified, as Half also provides the reverse operation of ToHalf - GetBits:
ushort bits = Half.GetBits(value);
return Convert.ToString(bits, 2).PadLeft(16, '0');
I'm currently trying to convert a .NET JSON Encoder to NETMF but have hit a problem with Convert.ToString() as there isn't such thing in NETMF.
The original line of the encoder looks like this:
Convert.ToString(codepoint, 16);
And after looking at the documentation for Convert.ToString(Int32, Int32) it says it's for converting an int32 into int 2, 8, 10 or 16 by providing the int as the first parameter and the base as the second.
What are some low level code of how to do this or how would I go about doing this?
As you can see from the code, I only need conversion from an Int32 to Int16.
EDIT
Ah, the encoder also then wants to do:
PadLeft(4, '0');
on the string, is this just adding 4 '0' + '0' + '0' + '0' to the start of the string?
If you mean you want to change a 32-bit integer value into a string which shows the value in hexadecimal:
string hex = intValue.ToString("x");
For variations, please see Stack Overflow question Convert a number into the hex value in .NET.
Disclaimer: I'm not sure if this function exists in NETMF, but it is so fundamental that I think it should.
Here’s some sample code for converting an integer to hexadecimal (base 16):
int num = 48764; // assign your number
// Generate hexadecimal number in reverse.
var sb = new StringBuilder();
do
{
sb.Append(hexChars[num & 15]);
num >>= 4;
}
while (num > 0);
// Pad with leading 0s for a minimum length of 4 characters.
while (sb.Length < 4)
sb.Append('0');
// Reverse string and get result.
char[] chars = new char[sb.Length];
sb.CopyTo(0, chars, 0, sb.Length);
Array.Reverse(chars);
string result = new string(chars);
PadLeft(4, '0') prepends leading 0s to the string to ensure a minimum length of 4 characters.
The hexChars value lookup may be trivially defined as a string:
internal static readonly string hexChars = "0123456789ABCDEF";
Edit: Replacing StringBuilder with List<char>:
// Generate hexadecimal number in reverse.
List<char> builder = new List<char>();
do
{
builder.Add(hexChars[num & 15]);
num >>= 4;
}
while (num > 0);
// Pad with leading 0s for a minimum length of 4 characters.
while (builder.Count < 4)
builder.Add('0');
// Reverse string and get result.
char[] chars = new char[builder.Count];
for (int i = 0; i < builder.Count; ++i)
chars[i] = builder[builder.Count - i - 1];
string result = new string(chars);
Note: Refer to the “Hexadecimal Number Output” section of Expert .NET Micro Framework for a discussion of this conversion.
I got a boolean list with 92 booleans, I want the list to be converted to a string, I thought I ll take 8 booleans(bits) and put them in a Byte(8 bits) and then use the ASCII to convert it the byte value to a char then add the chars to a string. However after googeling for more then 2 hours, no luck atm. I tried converting the List to a Byte list but it didn t work either ^^.
String strbyte = null;
for (int x = 0; x != tmpboolist.Count; x++) //tmpboolist is the 90+- boolean list
{
//this loop checks for true then puts a 1 or a 0 in the string(strbyte)
if (tmpboolist[x])
{
strbyte = strbyte + '1';
}
else
{
strbyte = strbyte + '0';
}
}
//here I try to convert the string to a byte list but no success
//no success because the testbytearray has the SAME size as the
//tmpboolist(but it should have less since 8 booleans should be 1 Byte)
//however all the 'Bytes' are 48 & 49 (which is 1 and 0 according to
//http://www.asciitable.com/)
Byte[] testbytearray = Encoding.Default.GetBytes(strbyte);
PS If anyone has a better suggestion on how to code & decode a Boolean list to a String?
(Because I want people to share their boolean list with a string rather then a list of 90 1 and 0s.)
EDIT: got it working now! ty all for helping
string text = new string(tmpboolist.Select(x => x ? '1' : '0').ToArray());
byte[] bytes = getBitwiseByteArray(text); //http://stackoverflow.com/a/6756231/1184013
String Arraycode = Convert.ToBase64String(bytes);
System.Windows.MessageBox.Show(Arraycode);
//first it makes a string out of the boolean list then it uses the converter to make it an Byte[](array), then we use the base64 encoding to make the byte[] a String.(that can be decoded later)
I ll look into the encoding32 later, ty for all the help again :)
You should store your boolean values in a BitArray.
var values = new BitArray(92);
values[0] = false;
values[1] = true;
values[2] = true;
...
Then you can convert the BitArray to a byte array
var bytes = new byte[(values.Length + 7) / 8];
values.CopyTo(bytes);
and the byte array to a Base64 string
var result = Convert.ToBase64String(bytes);
Reversely, you can convert a Base64 string to a byte array
var bytes2 = Convert.FromBase64String(result);
and the byte array to a BitArray
var values2 = new BitArray(bytes2);
The Base64 string looks like this: "Liwd7bRv6TMY2cNE". This is probably a bit unhandy for sharing between people; have a look at human-oriented base-32 encoding:
Anticipated uses of these [base-32 strings] include cut-
and-paste, text editing (e.g. in HTML files), manual transcription via a
keyboard, manual transcription via pen-and-paper, vocal transcription over
phone or radio, etc.
The desiderata for such an encoding are:
minimizing transcription errors -- e.g. the well-known problem of confusing
'0' with 'O'
embedding into other structures -- e.g. search engines, structured or
marked-up text, file systems, command shells
brevity -- Shorter [strings] are better than longer ones.
ergonomics -- Human users (especially non-technical ones) should find the
[strings] as easy and pleasant as possible. The uglier the [strings] looks, the worse.
To start with, it's a bad idea to concatenate strings in a loop like that - at least use StringBuilder, or use something like this with LINQ:
string text = new string(tmpboolist.Select(x => x ? '1' : '0').ToArray());
But converting your string to a List<bool> is easy with LINQ, using the fact that string implements IEnumerable<char>:
List<bool> values = text.Select(c => c == '1').ToList();
It's not clear where the byte array comes in... but you should not try to represent arbitrary binary data in a string just using Encoding.GetString. That's not what it's for.
If you don't care what format your string uses, then using Base64 will work well - but be aware that if you're grouping your Boolean values into bytes, you'll need extra information if you need to distinguish between "7 values" and "8 values, the first of which is False" for example.
Since I am infering from your code you want a string with n digits of either 1 or 0 depending onthe internal lists bool value then how about...
public override string ToString()
{
StringBuilder output = new StringBuilder(91);
foreach(bool item in this.tempboolist)
{
output.Append(item ? "1" : "0");
}
return output.ToString();
}
Warning this was off the cuff typing, I have not validated this with a compiler yet!
This function does what you want:
public String convertBArrayToStr(bool[] input)
{
if (input == null)
return "";
int length = input.Count();
int byteArrayCount = (input.Count() - 1) / 8 + 1;
var bytes = new char[byteArrayCount];
for (int i = 0; i < length; i++ )
{
var mappedIndex = (i - 1) / 8;
bytes[mappedIndex] = (char)(2 * bytes[mappedIndex] +(input[i] == true ? 1 : 0));
}
return new string(bytes);
}
I am writing a program that reads '.exe' files and stores their hex values in an array of bytes for comparison with an array containing a series of values. (like a very simple virus scanner)
byte[] buffer = File.ReadAllBytes(currentDirectoryContents[j]);
I have then used BitConverter to create a single string of these values
string hex = BitConverter.ToString(buffer);
The next step is to search this string for a series of values(definitions) and return positive for a match. This is where I am running into problems. My definitions are hex values but created and saved in notepad as defintions.xyz
string[] definitions = File.ReadAllLines(#"C:\definitions.xyz");
I had been trying to read them into a string array and compare the definition elements of the array with string hex
bool[] test = new bool[currentDirectoryContents.Length];
test[j] = hex.Contains(definitions[i]);
This IS a section from a piece of homework, which is why I am not posting my entire code for the program. I had not used C# before last Friday so am most likely making silly mistakes at this point.
Any advice much appreciated :)
It is pretty unclear exactly what kind of format you use of the definitions. Base64 is a good encoding for a byte[], you can rapidly convert back and forth with Convert.ToBase64String and Convert.FromBase64String(). But your question suggests the bytes are encoded in hex. Let's assume it looks like "01020304" for a new byte[] { 1, 2, 3, 4}. Then this helper function converts such a string back to a byte[]:
static byte[] Hex2Bytes(string hex) {
if (hex.Length % 2 != 0) throw new ArgumentException();
var retval = new byte[hex.Length / 2];
for (int ix = 0; ix < hex.Length; ix += 2) {
retval[ix / 2] = byte.Parse(hex.Substring(ix, 2), System.Globalization.NumberStyles.HexNumber);
}
return retval;
}
You can now do a fast pattern search with an algorithm like Boyer-Moore.
I expect you understand that this is a very inefficient way to do it. But except for that, you should just do something like this:
bool[] test = new bool[currentDirectoryContents.Length];
for(int i=0;i<test.Length;i++){
byte[] buffer = File.ReadAllBytes(currentDirectoryContents[j]);
string hex = BitConverter.ToString(buffer);
test[i] = ContainsAny(hex, definitions);
}
bool ContainsAny(string s, string[] values){
foreach(string value in values){
if(s.Contains(value){
return true;
}
}
return false;
}
If you can use LINQ, you can do it like this:
var test = currentDirectoryContents.Select(
file=>definitions.Any(
definition =>
BitConverter.ToString(
File.ReadAllBytes(file)
).Contains(definition)
)
).ToArray();
Also, make sure that your definitions-file is formatted in a way that matches the output of BitConverter.ToString(): upper-case with dashes separating each encoded byte:
12-AB-F0-34
54-AC-FF-01-02
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.