I've almost finished converting a PHP script to a C# one to use in ASP.net.
I've already converted this to match the the correct result so far:-
function sign_url($url, $key, $secret)
{
if (strpos($url,'?') !== false)
{
$url .= "&";
}
else
{
$url .= "?";
}
$url .= "ApplicationKey=" . $key;
$signature = hash_hmac("sha1", urldecode($url), $secret);
$url .= "&Signature=" . hex_to_base64($signature);
return $url;
}
Here is the part i'm struggling with:-
function hex_to_base64($hex){
$return = '';
foreach(str_split($hex, 2) as $pair){
$return .= chr(hexdec($pair));
}
return base64_encode($return);
}
From what i can gather it splits the input string ($hex) into sets of 2 characters.
It then converts these hexadecimal strings to decimal numbers before getting the chr() value of this number.
Storing all these conversions in a $return string.
Finally it does the base 64 conversion.
I'm struggling to find the best way to do this in C#, particularly the splitting into 2 characters while doing the other conversions.
Old, good, C-style code that do not use LINQ and megabytes of other libraries:
static string HexToBase64(string hex)
{
byte[] buf = new byte[hex.Length / 2];
for (int i = 0; i < hex.Length / 2; i++)
{
buf[i] = Convert.ToByte(hex.Substring(i*2,2), 16);
}
return Convert.ToBase64String(buf);
}
You can do it using two amazing .Net technologies - LINQ and Rx:
private static string HexStringToBase64String(string hexString)
{
var byteArray = hexString
.ToObservable()
.Buffer(2)
.Select(pair => new string(pair.ToArray()))
.Select(numberString => Byte.Parse(numberString, NumberStyles.HexNumber))
.ToEnumerable()
.ToArray();
return Convert.ToBase64String(byteArray);
}
There's no need to split each hex byte into two characters, or loop through each character pair for that matter.
Take a look at the following questions:
How to convert numbers between hexadecimal and decimal in C#?
How can I convert a hex string to a byte array?
I would do something like this
public static string HexToBase64String(string hex)
{
if (string.IsNullOrEmpty(hex) || hex.Length % 2 == 1)
throw new ArgumentException("Invalid hex value", "hex");
var bytes = Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
return System.Convert.ToBase64String(bytes);
}
Try these:
str_split = String.Split() (http://msdn.microsoft.com/en-us/library/system.string.split(v=vs.110).aspx)
base64_encode = Convert.ToBase64String() (http://msdn.microsoft.com/en-us/library/system.convert.tobase64string(v=vs.110).aspx)
chr = Convert.ToChar() (http://msdn.microsoft.com/en-us/library/system.convert.tochar(v=vs.110).aspx)
hexdec = .ToString("X") (http://msdn.microsoft.com/en-us/library/8wch342y(v=vs.110).aspx)
hash_hmac = SHA1.ComputeHash() (http://msdn.microsoft.com/en-us/library/s02tk69a(v=vs.110).aspx)
Related
I'm using a third party SMS provider and have hit an issue with converting from UCS-2 messages back into readable text.
Their API documentation has this code sample which converts UCS-2 messges into what I'm picking up on the API.
string message = "Это тестовое сообщение юникода";
byte[] ba = Encoding.BigEndianUnicode.GetBytes (message);
var hexString = BitConverter.ToString (ba);
Console.WriteLine ("#U" + hexString.Replace("-",""));
Which converts the message string into
#U042D0442043E00200442043504410442043E0432043E043500200441043E043E043104490435043D043804350020044E043D0438043A043E04340430
This looks like the UCS-2 messages I'm picking up from their API.
Unfortunately they don't give any code samples of how to convert the messages back into a readable form.
I'm sure its not there in the docs because its something simple - but I just seem to figure out how to do it.
To reverse what you have (the string of hex prefixed with #U)
var message = "Это тестовое сообщение юникода";
var ba = Encoding.BigEndianUnicode.GetBytes(message);
var hexString = BitConverter.ToString(ba);
var encoded = "#U" + hexString.Replace("-", "");
Console.WriteLine(encoded);
// reverse
var bytes = Enumerable.Range(2, encoded.Length-2)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(encoded.Substring(x, 2), 16))
.ToArray();
var result = Encoding.BigEndianUnicode.GetString(bytes);
Console.WriteLine(result);
Output
#U042D0442043E00200442043504410442043E0432043E043500200441043E043E043104490435043D043804350020044E043D0438043A043E04340430
Это тестовое сообщение юникода
Demo here
looks like this would be the reverse:
string message = Encoding.BigEndianUnicode.GetString(ba);
The extraction of bytes could be done by such a method:
private IEnumerable<byte> GetTheBytes(string uc2Message)
{
string bytesOnly = uc2Message.Trim('#', 'U');
for (int i = 0; i < bytesOnly.Length-2; i+=2)
{
yield return Convert.ToByte($"{bytesOnly[i]}{bytesOnly[i+1]}", 16);
}
}
Console.WriteLine(Encoding.BigEndianUnicode.GetString(GetTheBytes(uc2Message).ToArray()));
I need to format an integer as a MAC-Address (01-1A-1B-2B-30 and so on). Is there a way to to this directly with string.format()?
All my attepts so far have failed:
string.Format("{0:X}", 1234567); //Output: 12D687 It is hex, but not formatted
string.Format("{0:00-00-00-00}", 1234567); //Output: 01-23-45-67 Formatted, but not hex
string.Format("{0:00-00-00-00}", string.Format("{0:X}", 1234567)); //Output: 01-23-45-67 Also dosn't work and is ugly.
string.Format("{0:X00-00-00-00}", 1234567); //Output: X01-23-45-67 Well. Still no success here.
This will include a - delimiter;
BitConverter.ToString(BitConverter.GetBytes(1234567))
Use
BitConverter.ToString(BitConverter.GetBytes(1234567))
You need to have a placeholder for each byte, and pass the integer in as an array:
// We have a format string that spits out hex for each byte seperated by a dash.
// ToString expects either a params or an object array, so let's get the bytes
// as a byte array, and convert it to an array of object
String.Format("{0:X}-{1:X}-{2:X}-{3:X}", BitConverter.GetBytes(1234567).Cast<Object>().ToArray())
Once you turn it into a hex string, you could use this method to split it up into chunkSize 2, then rejoin it with hyphens
void Main()
{
var str = string.Format("{0:X}", 12345678);
var splits = Split(str, 2);
var rejoinedSplits = string.Join("-",splits);
Console.WriteLine (rejoinedSplits); //tested in linqpad, gave me BC-61-4E
}
static IEnumerable<string> Split(string str, int chunkSize)
{
return Enumerable.Range(0, str.Length / chunkSize).Select(i => str.Substring(i * chunkSize, chunkSize));
}
Use the following function to separate every 4 digits:
public static string NumberToHexStr<T>(T obj) where T : IComparable, IFormattable, IConvertible // Any Number Type
{
string strHex = string.Format("0x{0:X2}", obj);
if (strHex.Length > 6)
{
while (((strHex.Length - 2) % 4) != 0)
strHex = strHex.Insert(2, "0");
int nIndex = strHex.Length - 4;
while (nIndex > 2)
{
strHex = strHex.Insert(nIndex, " ");
nIndex -= 4;
}
}
return strHex;
}
Example: 1,407,392,063,619,074 will be displayed as 0x0005 0004 0003 0002.
How to remove leading zeros in strings using C#?
For example in the following numbers, I would like to remove all the leading zeros.
0001234
0000001234
00001234
This is the code you need:
string strInput = "0001234";
strInput = strInput.TrimStart('0');
It really depends on how long the NVARCHAR is, as a few of the above (especially the ones that convert through IntXX) methods will not work for:
String s = "005780327584329067506780657065786378061754654532164953264952469215462934562914562194562149516249516294563219437859043758430587066748932647329814687194673219673294677438907385032758065763278963247982360675680570678407806473296472036454612945621946";
Something like this would
String s ="0000058757843950000120465875468465874567456745674000004000".TrimStart(new Char[] { '0' } );
// s = "58757843950000120465875468465874567456745674000004000"
Code to avoid returning an empty string ( when input is like "00000").
string myStr = "00012345";
myStr = myStr.TrimStart('0');
myStr = myStr.Length > 0 ? myStr : "0";
return numberString.TrimStart('0');
Using the following will return a single 0 when input is all 0.
string s = "0000000"
s = int.Parse(s).ToString();
TryParse works if your number is less than Int32.MaxValue. This also gives you the opportunity to handle badly formatted strings. Works the same for Int64.MaxValue and Int64.TryParse.
int number;
if(Int32.TryParse(nvarchar, out number))
{
// etc...
number.ToString();
}
This Regex let you avoid wrong result with digits which consits only from zeroes "0000" and work on digits of any length:
using System.Text.RegularExpressions;
/*
00123 => 123
00000 => 0
00000a => 0a
00001a => 1a
00001a => 1a
0000132423423424565443546546356546454654633333a => 132423423424565443546546356546454654633333a
*/
Regex removeLeadingZeroesReg = new Regex(#"^0+(?=\d)");
var strs = new string[]
{
"00123",
"00000",
"00000a",
"00001a",
"00001a",
"0000132423423424565443546546356546454654633333a",
};
foreach (string str in strs)
{
Debug.Print(string.Format("{0} => {1}", str, removeLeadingZeroesReg.Replace(str, "")));
}
And this regex will remove leading zeroes anywhere inside string:
new Regex(#"(?<!\d)0+(?=\d)");
// "0000123432 d=0 p=002 3?0574 m=600"
// => "123432 d=0 p=2 3?574 m=600"
Regex rx = new Regex(#"^0+(\d+)$");
rx.Replace("0001234", #"$1"); // => "1234"
rx.Replace("0001234000", #"$1"); // => "1234000"
rx.Replace("000", #"$1"); // => "0" (TrimStart will convert this to "")
// usage
var outString = rx.Replace(inputString, #"$1");
I just crafted this as I needed a good, simple way.
If it gets to the final digit, and if it is a zero, it will stay.
You could also use a foreach loop instead for super long strings.
I just replace each leading oldChar with the newChar.
This is great for a problem I just solved, after formatting an int into a string.
/* Like this: */
int counterMax = 1000;
int counter = ...;
string counterString = counter.ToString($"D{counterMax.ToString().Length}");
counterString = RemoveLeadingChars('0', ' ', counterString);
string fullCounter = $"({counterString}/{counterMax})";
// = ( 1/1000) ... ( 430/1000) ... (1000/1000)
static string RemoveLeadingChars(char oldChar, char newChar, char[] chars)
{
string result = "";
bool stop = false;
for (int i = 0; i < chars.Length; i++)
{
if (i == (chars.Length - 1)) stop = true;
if (!stop && chars[i] == oldChar) chars[i] = newChar;
else stop = true;
result += chars[i];
}
return result;
}
static string RemoveLeadingChars(char oldChar, char newChar, string text)
{
return RemoveLeadingChars(oldChar, newChar, text.ToCharArray());
}
I always tend to make my functions suitable for my own library, so there are options.
I wrote a function to convert byte[] to string, and I add ";" after each byte. Now I want to convert this string to byte[] by splitting the string (similar to a CSV string).
public string ByteArrayToString(byte[] byteArray,string s)
{
for (int i = 0; i < byteArray.Length; i++)
{
s += byteArray[i].ToString() + ";";
}
s = s.Substring(0, s.Length - 1);
return s;
}
How could I write a function to convert this string to that byte array again?
try this
var byteArray = new byte[] {123, 11, 111};
var stringBytes = string.Join(";", byteArray.Select(b => b.ToString()));
var newByteArray = stringBytes.Split(';').Select(s => byte.Parse(s)).ToArray();
I guess that you want to get rid of the ; when converting also. I think you want to do something like this:
byte[] result = Encoding.UTF8.GetBytes(s.Replace(";",""));
This will fail if the original byte array actually contains a ;that is valid data, but in that case you will have lots of problems anyway since your "CSV" file will be wrongly formatted.
Consider using Split String
StringBuilder will be useful instead of String (Performance wise).
With StringBuilder:
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(objStringBuilder.ToString());
with String:
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(objString);
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
return encoding.GetBytes(yourStringVariable);
I know you already know the answer by now... but this code solves the problem, i hope it helps someone else.
int counter= 0;
string cadena = "8,5,6,3,4,6,3"
string[] foto = cadena.Split(',');
byte[] fotoFinal = new byte[foto.Length];
foreach (string s in foto)
{
fotoFinal[contador] = Convert.ToByte(s);
counter++;
}
str.Split(new char[]{';'},
StringSplitOptions.RemoveEmptyEntries).Select(s => byte.Parse(s)).ToArray();
Simply :)
public static byte[] Bytes ( this string Key )
{
return Enumerable.Range(0, Key.Binary().Length / 8 )
.Select(Index => Convert.ToByte(
Key.Binary().Substring(Index * 8, 8), 2))
.ToArray();
}
string[] sbytes = sl.Split(',');
byte[] b = new byte[sbytes.Length];
for (int j = 0; j < sbytes.Length; j++)
{
byte newByte = byte.Parse(sbytes[j], System.Globalization.NumberStyles.HexNumber);
b[j] = newByte;
}
I like using number styles hex number.
Is there a method in c# that would talk the ip address 10.13.216.41
and display it as 00001010.00001101.11011000.00101001. If not, how can it be done?
While I won't rewrite the format-as-binary code (Larsenal's answer was fine), I'll point out that splitting on "." won't work for IPv6 addresses. If you use IPAddress.Parse, though, it will work for any address format. You can then use IPAddress.GetAddressBytes to get each part of the address.
So instead of:
input.Split('.').Select( ... )
do:
IPAddress.Parse(input).GetAddressBytes().Select( ... )
static string IPAddrToBinary( string input) {
// assumes a valid IP Address format
return String.Join(".", (input.Split('.').Select(x => Convert.ToString(Int32.Parse(x), 2).PadLeft(8, '0'))).ToArray());
}
Here's a version with comments, which may be a little easier to understand:
static string IPAddrToBinary(string input)
{
return String.Join(".", ( // join segments
input.Split('.').Select( // split segments into a string[]
// take each element of array, name it "x",
// and return binary format string
x => Convert.ToString(Int32.Parse(x), 2).PadLeft(8, '0')
// convert the IEnumerable<string> to string[],
// which is 2nd parameter of String.Join
)).ToArray());
}
First, you would need to get the number you want to convert to binary (using String.Split, for example). Then, you can use an overload of the Convert.ToString method to return a string of the specified number in the specified base. For example:
Convert.ToString (128, 2);
returns
10000000
Funny, I wrote a javascript version of this today for another question.
Here's the c# translation of that code:
int dottedQuadToInt(string ip)
{
var parts = ip.Split(new char[] {'.'}, 4);
if (parts.Length != 4) return -1;
var result = 0;
var bitPos = 1;
foreach(var part in parts)
{
//validation
if (part.Length == 0 || part.Length > 3) return -1;
int segment;
if (!int.TryParse(part, out segment) || segment<0 || segment > 255) return -1;
//compute next segment
result += bitPos * segment;
bitPos = bitPos << 8;
}
return result;
}
Now, this isn't exactly what you asked for, but it's arguably more useful and it shoudl point you in the right direction.
You could do:
var parts = (from p in ("10.13.216.41").Split('.')
select int.Parse(p)).ToArray();
string result = string.Format("{0}.{1}.{2}.{3}",
Convert.ToString(part[0], 2).PadLeft(8,'0'),
Convert.ToString(part[1], 2).PadLeft(8,'0'),
Convert.ToString(part[2], 2).PadLeft(8,'0'),
Convert.ToString(part[3], 2).PadLeft(8,'0'));
This method can help you:
static string IPDecToBinary(string IPAdresa)
{
string IPverBinare = null;
IPAddress IPDec = IPAddress.Parse(IPAdresa);
byte[] IPByte = IPDec.GetAddressBytes();
IPverBinare = string.Format("{0}.{1}.{2}.{3}",
Convert.ToString(IPByte[0], 2).PadLeft(8, '0'),
Convert.ToString(IPByte[1], 2).PadLeft(8, '0'),
Convert.ToString(IPByte[2], 2).PadLeft(8, '0'),
Convert.ToString(IPByte[3], 2).PadLeft(8, '0')
);
return IPverBinare;
}