C# hex to ascii - c#

I'm trying to convert a String of hex to ASCII, using this:
public void ConvertHex(String hexString)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hexString.Length; i += 2)
{
String hs = hexString.Substring(i, i + 2);
System.Convert.ToChar(System.Convert.ToUInt32(hexString.Substring(0, 2), 16)).ToString();
}
String ascii = sb.ToString();
MessageBox.Show(ascii);
}
but I get an out or bounds exception, I'm sure its a glaring error but other code I have tried does not work either. What am I doing wrong?

This code will convert the hex string into ASCII, you can copy paste this into a class and use it without instancing
public static string ConvertHex(String hexString)
{
try
{
string ascii = string.Empty;
for (int i = 0; i < hexString.Length; i += 2)
{
String hs = string.Empty;
hs = hexString.Substring(i,2);
uint decval = System.Convert.ToUInt32(hs, 16);
char character = System.Convert.ToChar(decval);
ascii += character;
}
return ascii;
}
catch (Exception ex) { Console.WriteLine(ex.Message); }
return string.Empty;
}
Notes
2 = the no. of hexString chars used to represent an ASCII character.
System.Convert.ToUInt32(hs, 16) = "convert the base 16 hex substrings to an unsigned 32 bit int"

There are four three problems here:
Since you're incrementing i by 2 on each iteration, you need to terminate at hexString.Length - 1. This doesn't actually matter; incrementing by two after the final iteration will bring the counter above the checked length regardless.
You're taking the wrong number of characters from hexString.
hs is never used.
You're not appending anything to sb.
Try this:
for (int i = 0; i < hexString.Length; i += 2)
{
string hs = hexString.Substring(i, 2);
sb.Append(Convert.ToChar(Convert.ToUInt32(hs, 16)));
}
Note that there's no need to qualify the types with their namespace, System (assuming you've referenced it at the top of the file with a using statement).

String hs = hexString.Substring(i, i + 2);
System.Convert.ToChar(System.Convert.ToUInt32(hexString.Substring(0, 2), 16)).ToString();
Do you notice you're never using hs ??
And that you're converting the first 2 chars over and over?

Since you are incrementing your index by 2, you need to stop your loop one-before-the-end of the length of the string. Otherwise your last iteration of the loop will try to read characters past the end of the string.
for (int i = 0; i < hexString.Length - 1, i += 2)

Related

Given a number and a length, prepend (length - number.count) 0s to that int in a performant manner in C#

I am trying to create a helper function that prepends x amounts of zeroes to the integer where x is the difference between a given length and the number of characters in that int.
For example:
// data = 9573132375
// length = 15
// should return (15 - 10) 000009573132375
public string ModulateData(long data, int length)
{
if (data.ToString().Length <= length)
{
int noToPrepend = length - data.ToString().Length;
string leadingzeros = "";
for (int i = 0; i < noToPrepend; i++)
{
leadingzeros += "0";
}
return leadingzeros + data.ToString();
}
return "";
}
I can only think of converting the data variable to a string, prepending 0s, and converting the string back to an integer later. However, I am concerned about the performance of this approach, as this method will be part of my core design, it needs to be as performant as possible. Is there a faster way this can be done? Are there any performance penalties with my current code?
EDIT
I am communicating the data variable as request data to a machine that accepts bytes, so I will be using this function as follows -
string requestdata = "";
requestdata += ModulateData(x,20);
requestdata += ModulateData(y,5);
requestdata += ModulateData(z,10); // Could be about 20 or so lines like this.
After that I will convert requestdata to a byte array in Hex Format. I already have working code for that.
Shorter version:
public static string ModulateData(long data, int length) =>
(data.ToString().Length <= length)
? $"{new string('0', length - data.ToString().Length)}{data}"
: string.Empty;
And more debuggable version, if you want:
public static string ModulateData(long data, int length)
{
var dataAsText = data.ToString();
if (dataAsText.Length <= length)
{
int noToPrepend = length - dataAsText.Length;
var leadingZeros = new string('0', noToPrepend);
return $"{leadingZeros}{dataAsText}";
}
return string.Empty;
}
And a usage:
// to make this more optimal you can calculate the StringBuilder initial capacity here,
// by taking into account possible characters length output
var requestData = new StringBuilder();
requestData.Append(ModulateData(x, 20));
requestData.Append(ModulateData(y, 5));
requestData.Append(ModulateData(z, 10));

"Pad Left" with 0's on a char array

G'day,
I have a char array that varies in size based on the length of some data. The array will never be larger than 24 though. It may however, be less than 24. As a result of this I need to "pad left" with 0's, as in add more elements to the left of the array to make it 24. I have below some code that does this, just wondering if there is a faster way or more efficient way to do so. Thanks!
Note: I don't think this is a duplicate as I am working with char[]'s not strings.
char[] dataLen = Convert.ToString(data.Length, 2).ToCharArray();
int j = 0;
char[] tmp = new char[24];
for (int i = 0; i < 24; i++)
{
if (i < (24 - dataLen.Length))
tmp[i] = '0';
else
tmp[i] = dataLen[j++];
}
dataLen = tmp;
Why don't you simply use String.PadLeft?
char[] data = "abcdefgh".ToCharArray(); // sample data
data = new string(data).PadLeft(24, '0').ToCharArray();
That should be efficient and is also very readable.
how about :
string z24 = "000000000000000000000";
tmp = z24.Take(24 - dataLen.Length).Union(dataLen).ToArray();
I would simply use a string for all operations, and use PadLeft to do the padding.
string input = new string(data);
string result = input.PadLeft(24, '0');
Then convert it to a char[] if you really need to:
char[] chars = result.ToCharArray();
(Also, your Convert.ToString(data.Length, 2) doesn't return their string representation, new string(data) does)

Masking all characters of a string except for the last n characters

I want to know how can I replace a character of a string with condition of "except last number characters"?
Example:
string = "4111111111111111";
And I want to make it that
new_string = "XXXXXXXXXXXXX1111"
In this example I replace the character to "X" except the last 4 characters.
How can I possibly achieve this?
Would that suit you?
var input = "4111111111111111";
var length = input.Length;
var result = new String('X', length - 4) + input.Substring(length - 4);
Console.WriteLine(result);
// Ouput: XXXXXXXXXXXX1111
How about something like...
new_string = new String('X', YourString.Length - 4)
+ YourString.Substring(YourString.Length - 4);
create a new string based on the length of the current string -4 and just have it all "X"s. Then add on the last 4 characters of the original string
Here's a way to think through it. Call the last number characters to leave n:
How many characters will be replaced by X? The length of the string minus n.
How can we replace characters with other characters? You can't directly modify a string, but you can build a new one.
How to get the last n characters from the original string? There's a couple ways to do this, but the simplest is probably Substring, which allows us to grab part of a string by specifying the starting point and optionally the ending point.
So it would look something like this (where n is the number of characters to leave from the original, and str is the original string - string can't be the name of your variable because it's a reserved keyword):
// 2. Start with a blank string
var new_string = "";
// 1. Replace first Length - n characters with X
for (var i = 0; i < str.Length - n; i++)
new_string += "X";
// 3. Add in the last n characters from original string.
new_string += str.Substring(str.Length - n);
This might be a little Overkill for your ask. But here is a quick extension method that does this.
it defaults to using x as the masking Char but can be changed with an optional char
public static class Masking
{
public static string MaskAllButLast(this string input, int charsToDisplay, char maskingChar = 'x')
{
int charsToMask = input.Length - charsToDisplay;
return charsToMask > 0 ? $"{new string(maskingChar, charsToMask)}{input.Substring(charsToMask)}" : input;
}
}
Here a unit tests to prove it works
using Xunit;
namespace Tests
{
public class MaskingTest
{
[Theory]
[InlineData("ThisIsATest", 4, 'x', "xxxxxxxTest")]
[InlineData("Test", 4, null, "Test")]
[InlineData("ThisIsATest", 4, '*', "*******Test")]
[InlineData("Test", 16, 'x', "Test")]
[InlineData("Test", 0, 'y', "yyyy")]
public void Testing_Masking(string input, int charToDisplay, char maskingChar, string expected)
{
//Act
string actual = input.MaskAllButLast(charToDisplay, maskingChar);
//Assert
Assert.Equal(expected, actual);
}
}
}
StringBuilder sb = new StringBuilder();
Char[] stringChar = string.toCharArray();
for(int x = 0; x < stringChar.length-4; x++){
sb.append(stringChar[x]);
}
sb.append(string.substring(string.length()-4));
string = sb.toString();
I guess you could use Select with index
string input = "4111111111111111";
string new_string = new string(input.Select((c, i) => i < input.Length - 4 ? 'X' : c).ToArray());
Some of the other concise answers here did not account for strings less than n characters. Here's my take:
var length = input.Length;
input = length > 4 ? new String('*', length - 4) + input.Substring(length - 4) : input;
lui,
Please Try this one...
string dispString = DisplayString("4111111111111111", 4);
Create One function with pass original string and no of digit.
public string DisplayString(string strOriginal,int lastDigit)
{
string strResult = new String('X', strOriginal.Length - lastDigit) + strOriginal.Substring(strOriginal.Length - lastDigit);
return strResult;
}
May be help you....
Try this:
String maskedString = "...."+ (testString.substring(testString.length() - 4, testString.length()));
Late to the party but I also wanted to mask all but the last 'x' characters, but only mask numbers or letters so that any - ( ), other formatting, etc would still be shown. Here's my quick extension method that does this - hopefully it helps someone. I started with the example from Luke Hammer, then changed the guts to fit my needs.
public static string MaskOnlyChars(this string input, int charsToDisplay, char maskingChar = 'x')
{
StringBuilder sbOutput = new StringBuilder();
int intMaskCount = input.Length - charsToDisplay;
if (intMaskCount > 0) //only mask if string is longer than requested unmasked chars
{
for (var intloop = 0; intloop < input.Length; intloop++)
{
char charCurr = Char.Parse(input.Substring(intloop, 1));
byte[] charByte = Encoding.ASCII.GetBytes(charCurr.ToString());
int intCurrAscii = charByte[0];
if (intloop <= (intMaskCount - 1))
{
switch (intCurrAscii)
{
case int n when (n >= 48 && n <= 57):
//0-9
sbOutput.Append(maskingChar);
break;
case int n when (n >= 65 && n <= 90):
//A-Z
sbOutput.Append(maskingChar);
break;
case int n when (n >= 97 && n <= 122):
//a-z
sbOutput.Append(maskingChar);
break;
default:
//Leave other characters unmasked
sbOutput.Append(charCurr);
break;
}
}
else
{
//Characters at end to remain unmasked
sbOutput.Append(charCurr);
}
}
}
else
{
//if not enough characters to mask, show unaltered input
return input;
}
return sbOutput.ToString();
}

How do i convert a number stored in string to binary format?

I have a number that I store in string because it is a long number and I want to convert it to binary format.
string number = "25274132531129322906392322409257377862778880"
I want to get:
string binresult;
that holds value:
0000000000000001001000100010001000000000000000100000001011101000000000000000000011110000000000000000110100000000000000100000000000000000000000000000000000000000
You actually can use Dan Byström's answer to How to convert a gi-normous integer (in string format) to hex format? (C#), like Michael Edenfeld suggested in the comments. It will get you from your large number string to hexadecimal. I will repost his code for your convenience:
var s = "25274132531129322906392322409257377862778880";
var result = new List<byte>();
result.Add(0);
foreach (char c in s)
{
int val = (int)(c - '0');
for (int i = 0 ; i < result.Count ; i++)
{
int digit = result[i] * 10 + val;
result[i] = (byte)(digit & 0x0F);
val = digit >> 4;
}
if (val != 0)
result.Add((byte)val);
}
var hex = "";
foreach (byte b in result)
hex = "0123456789ABCDEF"[b] + hex;
I won't profess to understand how he came up with this, but I have tested it with a few numbers that I know the hex values for, and it appears to work. I'd love to hear an explanation from him.
Now, you want your answer in binary, and luckily for you, converting from hexadecimal to binary is one of the easier things in life. Every hex value converts directly to its 4-bit binary counterpart (0x7 = 0111, 0xA = 1010, etc). You could write a loop to perform this conversion character by character, but Guffa's answer to C# how convert large HEX string to binary provides this handy dandy Linq statement to perform the same action:
string binaryString = string.Join(string.Empty,
hex.Select(c => Convert.ToString(Convert.ToInt32(
c.ToString(), 16), 2).PadLeft(4, '0')));
Running all of this together gives me:
01110001010101010100100000000000110010010010001010100000000000000101110111000000000001010001010000000000110001111111111111111111111111111111111011100010
For your number. I don't know how you plan to verify it, but if Dan's hex translation is right, then that binary string will definitely be right.
System.Convert can help you with bits and pieces like this. See below.
string decString = "12345";
int integer = Convert.ToInt32(decString);
string binString = Convert.ToString(integer, 2);
You can try this:
string number = "25274132531129322906392322409257377862778880";
char[] strArr = number.ToCharArray();
StringBuilder sb = new StringBuilder();
foreach (char chr in strArr)
{
sb.Append(Convert.ToString((int)Char.GetNumericValue(chr), 2));
}
string binresult = sb.ToString();

int[] to string c#

Hi I'm developing an client application in C# and the server is written in c++
the server uses:
inline void StrToInts(int *pInts, int Num, const char *pStr)
{
int Index = 0;
while(Num)
{
char aBuf[4] = {0,0,0,0};
for(int c = 0; c < 4 && pStr[Index]; c++, Index++)
aBuf[c] = pStr[Index];
*pInts = ((aBuf[0]+128)<<24)|((aBuf[1]+128)<<16)|((aBuf[2]+128)<<8)|(aBuf[3]+128);
pInts++;
Num--;
}
// null terminate
pInts[-1] &= 0xffffff00;
}
to convert an string to int[]
in my c# client i recieve:
int[4] { -14240, -12938, -16988, -8832 }
How do I convert the array back to an string?
I don't want to use unsafe code (e.g. pointers)
Any of my tries resulted in unreadable strings.
EDIT:
Here is one of my approch:
private string IntsToString(int[] ints)
{
StringBuilder s = new StringBuilder();
for (int i = 0; i < ints.Length; i++)
{
byte[] bytes = BitConverter.GetBytes(ints[i]);
for (int j = 0; j < bytes.Length; j++)
s.Append((char)(bytes[j] & 0x7F));
}
return s.ToString();
}
I know I need to take care of endianess but as the server is running on my local machine and the server too, I assume that this is not a problem.
My other try was to use an struct with explicit layout and same FieldOffset for integer and chars but it doesn't work, either.
Maybe try something like (using LINQ):
int[] fromServer = { -14240, -12938, -16988, -8832, };
string reconstructedStr = new string(fromServer.SelectMany(BitConverter.GetBytes).Select(b => (char)(b - 128)).ToArray());
Untested, but there's something to start from. Don't know if the subtraction of 128 is correct.
You can create a comma separated string this way:
string str = String.Join(", ", intArray.Select(x => x.ToString()).ToArray());
var ints = new[] {-14240, -12938, -16988, -8832};
var result = string.Join("-", ints.Select(i => BitConverter.ToString(BitConverter.GetBytes(i))));
Console.WriteLine(result); //60-C8-FF-FF-76-CD-FF-FF-A4-BD-FF-FF-80-DD-FF-FF
BitConverter.ToString can be replaced by something else here, depending on how you will parse string later.

Categories