Самое легкое преобразование веса из шестнадцатеричного в байт в C#? [дубликат]
Возможные Дубликаты:
как преобразовать массив байтов в шестнадцатеричную строку и наоборот?
мне нужен эффективный и быстрый способ, чтобы сделать это преобразование. Я пробовал два разных способа, но они недостаточно эффективны для меня. Есть ли другой быстрый способ выполнить это в режиме реального времени для приложения с огромными данными?
public byte[] StringToByteArray(string hex)
{
return Enumerable.Range(0, hex.Length / 2).Select(x => Byte.Parse(hex.Substring(2 * x, 2), NumberStyles.HexNumber)).ToArray();
}
выше было более эффективным мне.
public static byte[] stringTobyte(string hexString)
{
try
{
int bytesCount = (hexString.Length) / 2;
byte[] bytes = new byte[bytesCount];
for (int x = 0; x < bytesCount; ++x)
{
bytes[x] = Convert.ToByte(hexString.Substring(x * 2, 2), 16);
}
return bytes;
}
catch
{
throw;
}
3 ответов
Я взял код бенчмаркинга от другой вопрос, и переработал его, чтобы проверить методы hex to bytes, приведенные здесь:
HexToBytesJon: 36979.7 average ticks (over 150 runs)
HexToBytesJon2: 35886.4 average ticks (over 150 runs)
HexToBytesJonCiC: 31230.2 average ticks (over 150 runs)
HexToBytesJase: 15359.1 average ticks (over 150 runs)
HexToBytesJon
и Йонпервая версия, и HexToBytesJon2
- второй вариант.
HexToBytesJonCiC
версия Джона с CodesInChaosпредложенный код.
HexToBytesJase
моя попытка, основанная на обоих выше, но с альтернативным преобразованием nybble, которое избегает проверки ошибок и ветвления:
public static byte[] HexToBytesJase(string hexString)
{
if ((hexString.Length & 1) != 0)
{
throw new ArgumentException("Input must have even number of characters");
}
byte[] ret = new byte[hexString.Length/2];
for (int i = 0; i < ret.Length; i++)
{
int high = hexString[i*2];
int low = hexString[i*2+1];
high = (high & 0xf) + ((high & 0x40) >> 6) * 9;
low = (low & 0xf) + ((low & 0x40) >> 6) * 9;
ret[i] = (byte)((high << 4) | low);
}
return ret;
}
если вы действительно нужна эффективность, то:
- не создавайте подстроки
- не создать iterator
или, и избавиться от try
блоки, которые имеют только catch
блок, который возвращает... для простоты, а не эффективности.
Это была бы довольно эффективная версия:
public static byte[] ParseHex(string hexString)
{
if ((hexString.Length & 1) != 0)
{
throw new ArgumentException("Input must have even number of characters");
}
int length = hexString.Length / 2;
byte[] ret = new byte[length];
for (int i = 0, j = 0; i < length; i++)
{
int high = ParseNybble(hexString[j++]);
int low = ParseNybble(hexString[j++]);
ret[i] = (byte) ((high << 4) | low);
}
return ret;
}
private static int ParseNybble(char c)
{
// TODO: Benchmark using if statements instead
switch (c)
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
return c - '0';
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
return c - ('a' - 10);
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
return c - ('A' - 10);
default:
throw new ArgumentException("Invalid nybble: " + c);
}
return c;
}
задача относится к альтернативе, как это. Я не измерил, что быстрее.
private static int ParseNybble(char c)
{
if (c >= '0' && c <= '9')
{
return c - '0';
}
c = (char) (c & ~0x20);
if (c >= 'A' && c <= 'F')
{
return c - ('A' - 10);
}
throw new ArgumentException("Invalid nybble: " + c);
}
как вариант на основе ParseNybble
:
public static byte[] ParseHex(string hexString)
{
if ((hexString.Length & 1) != 0)
{
throw new ArgumentException("Input must have even number of characters");
}
byte[] ret = new byte[hexString.Length / 2];
for (int i = 0; i < ret.Length; i++)
{
int high = ParseNybble(hexString[i*2]);
int low = ParseNybble(hexString[i*2+1]);
ret[i] = (byte) ((high << 4) | low);
}
return ret;
}
private static int ParseNybble(char c)
{
unchecked
{
uint i = (uint)(c - '0');
if(i < 10)
return (int)i;
i = ((uint)c & ~0x20u) - 'A';
if(i < 6)
return (int)i+10;
throw new ArgumentException("Invalid nybble: " + c);
}
}