Похоже на формат даты и времени Excel, называемый последовательной датой . Быстрый и грязный способ его преобразования:
>>> import datetime
>>> serial = 43111.0
>>> seconds = (serial - 25569) * 86400.0
>>> datetime.datetime.utcfromtimestamp(seconds)
datetime.datetime(2018, 1, 11, 0, 0)
Также:
public static string ByteArrayToString(byte[] ba)
{
StringBuilder hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
или:
public static string ByteArrayToString(byte[] ba)
{
return BitConverter.ToString(ba).Replace("-","");
}
существует еще больше вариантов выполнения его, например здесь .
обратная конверсия пошла бы как это:
public static byte[] StringToByteArray(String hex)
{
int NumberChars = hex.Length;
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;
}
<час> Используя Substring
наилучший вариант в сочетании с Convert.ToByte
. См. этот ответ для получения дополнительной информации. При необходимости в лучшей производительности необходимо избежать Convert.ToByte
, прежде чем можно будет отбросить SubString
.
Если Вы хотите больше гибкости, чем BitConverter
, но не хотите тех неуклюжий стиль 1990-х явные циклы, то можно сделать:
String.Join(String.Empty, Array.ConvertAll(bytes, x => x.ToString("X2")));
Или, если Вы используете.NET 4.0:
String.Concat(Array.ConvertAll(bytes, x => x.ToString("X2")));
(Последний из комментария к исходному сообщению.)
Дополнительные методы (правовая оговорка: полностью непротестированный код, BTW...):
public static class ByteExtensions
{
public static string ToHexString(this byte[] ba)
{
StringBuilder hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
{
hex.AppendFormat("{0:x2}", b);
}
return hex.ToString();
}
}
и т.д. Используйте любой из три решения Tomalak (с последним, являющимся дополнительным методом на строке).
Можно использовать BitConverter. Метод ToString:
byte[] bytes = {0, 1, 2, 4, 8, 16, 32, 64, 128, 256}
Console.WriteLine( BitConverter.ToString(bytes));
Вывод:
00-01-02-04-08-10-20-40-80-FF
Больше информации: BitConverter. Метод ToString (Байт [])
Примечание: новый лидер с 20.08.2015.
я выполнил каждый из различных методов преобразования через небольшое количество сырой нефти Stopwatch
тестирование производительности, выполнение со случайным предложением (n=61, 1 000 повторений) и выполнение с Проектом текст Гутенберга (n=1,238,957, 150 повторений). Вот результаты, примерно от самого быстрого до самого медленного. Все измерения находятся в галочках ( 10 000 галочек = 1 мс ), и все относительные примечания сравниваются [самый медленный] StringBuilder
реализация. Для используемого кода посмотрите ниже или среда тестирования repo , где я теперь поддерживаю код для выполнения этого.
, ПРЕДУПРЕЖДАЮЩАЯ: не полагайтесь на эту статистику ни для чего конкретного; они - просто демонстрационное выполнение демонстрационных данных. При реальной необходимости в первоклассной производительности протестируйте эти методы в представителе среды производственных потребностей с представителем данных того, что Вы будете использовать.
unsafe
(через CodesInChaos) (добавленный к тесту repo [1 133] воздушно-реактивный двигатель ) BitConverter
(через Tomalak) {SoapHexBinary}.ToString
(через Mykroft) {byte}.ToString("X2")
(использование foreach
) (полученный на основании ответа Will Dean) {byte}.ToString("X2")
(использование {IEnumerable}.Aggregate
, требует Системы. Linq) (через Mark) Array.ConvertAll
(использование string.Join
) (через Will Dean) Array.ConvertAll
(использование string.Concat
, требует.NET 4.0) (через Will Dean) {StringBuilder}.AppendFormat
(использование foreach
) (через Tomalak) {StringBuilder}.AppendFormat
(использование {IEnumerable}.Aggregate
, требует Системы. Linq) (полученный на основании ответа Tomalak) Таблицы поиска взяли на себя инициативу по управлению байтом. В основном существует некоторая форма предварительных вычислений, чем любое данное откусывание или байт будут в шестнадцатеричном числе. Затем поскольку Вы разрываетесь через данные, Вы просто ищете следующую часть для наблюдения, каково шестнадцатеричная строка это было бы. То значение тогда добавляется к выводу получившей строки некоторым способом. В течение долгого времени управление байтом, потенциально тяжелее для чтения некоторыми разработчиками, было наиболее эффективным подходом.
Ваш лучший выбор все еще будет нахождением некоторых представительных данных и испытанием это в подобной производству среде. Если бы у Вас есть различные ограничения памяти, можно предпочесть метод с меньшим количеством выделений к тому, которое было бы быстрее, но использовало бы больше памяти.
Не стесняется играть с кодом тестирования, который я использовал. Версия включена здесь, но не стесняйтесь клонироваться repo и добавлять Ваши собственные методы. Отправьте запрос получения по запросу, если Вы находите что-нибудь интересным или хотите помочь улучшить среду тестирования, она использует.
Func<byte[], string>
) к/Tests/ConvertByteArrayToHexString/Test.cs. TestCandidates
возвращаемое значение в том же самом классе. static string ByteArrayToHexStringViaStringJoinArrayConvertAll(byte[] bytes) {
return string.Join(string.Empty, Array.ConvertAll(bytes, b => b.ToString("X2")));
}
static string ByteArrayToHexStringViaStringConcatArrayConvertAll(byte[] bytes) {
return string.Concat(Array.ConvertAll(bytes, b => b.ToString("X2")));
}
static string ByteArrayToHexStringViaBitConverter(byte[] bytes) {
string hex = BitConverter.ToString(bytes);
return hex.Replace("-", "");
}
static string ByteArrayToHexStringViaStringBuilderAggregateByteToString(byte[] bytes) {
return bytes.Aggregate(new StringBuilder(bytes.Length * 2), (sb, b) => sb.Append(b.ToString("X2"))).ToString();
}
static string ByteArrayToHexStringViaStringBuilderForEachByteToString(byte[] bytes) {
StringBuilder hex = new StringBuilder(bytes.Length * 2);
foreach (byte b in bytes)
hex.Append(b.ToString("X2"));
return hex.ToString();
}
static string ByteArrayToHexStringViaStringBuilderAggregateAppendFormat(byte[] bytes) {
return bytes.Aggregate(new StringBuilder(bytes.Length * 2), (sb, b) => sb.AppendFormat("{0:X2}", b)).ToString();
}
static string ByteArrayToHexStringViaStringBuilderForEachAppendFormat(byte[] bytes) {
StringBuilder hex = new StringBuilder(bytes.Length * 2);
foreach (byte b in bytes)
hex.AppendFormat("{0:X2}", b);
return hex.ToString();
}
static string ByteArrayToHexViaByteManipulation(byte[] bytes) {
char[] c = new char[bytes.Length * 2];
byte b;
for (int i = 0; i < bytes.Length; i++) {
b = ((byte)(bytes[i] >> 4));
c[i * 2] = (char)(b > 9 ? b + 0x37 : b + 0x30);
b = ((byte)(bytes[i] & 0xF));
c[i * 2 + 1] = (char)(b > 9 ? b + 0x37 : b + 0x30);
}
return new string(c);
}
static string ByteArrayToHexViaByteManipulation2(byte[] bytes) {
char[] c = new char[bytes.Length * 2];
int b;
for (int i = 0; i < bytes.Length; i++) {
b = bytes[i] >> 4;
c[i * 2] = (char)(55 + b + (((b - 10) >> 31) & -7));
b = bytes[i] & 0xF;
c[i * 2 + 1] = (char)(55 + b + (((b - 10) >> 31) & -7));
}
return new string(c);
}
static string ByteArrayToHexViaSoapHexBinary(byte[] bytes) {
SoapHexBinary soapHexBinary = new SoapHexBinary(bytes);
return soapHexBinary.ToString();
}
static string ByteArrayToHexViaLookupAndShift(byte[] bytes) {
StringBuilder result = new StringBuilder(bytes.Length * 2);
string hexAlphabet = "0123456789ABCDEF";
foreach (byte b in bytes) {
result.Append(hexAlphabet[(int)(b >> 4)]);
result.Append(hexAlphabet[(int)(b & 0xF)]);
}
return result.ToString();
}
static readonly uint* _lookup32UnsafeP = (uint*)GCHandle.Alloc(_Lookup32, GCHandleType.Pinned).AddrOfPinnedObject();
static string ByteArrayToHexViaLookup32UnsafeDirect(byte[] bytes) {
var lookupP = _lookup32UnsafeP;
var result = new string((char)0, bytes.Length * 2);
fixed (byte* bytesP = bytes)
fixed (char* resultP = result) {
uint* resultP2 = (uint*)resultP;
for (int i = 0; i < bytes.Length; i++) {
resultP2[i] = lookupP[bytesP[i]];
}
}
return result;
}
static uint[] _Lookup32 = Enumerable.Range(0, 255).Select(i => {
string s = i.ToString("X2");
return ((uint)s[0]) + ((uint)s[1] << 16);
}).ToArray();
static string ByteArrayToHexViaLookupPerByte(byte[] bytes) {
var result = new char[bytes.Length * 2];
for (int i = 0; i < bytes.Length; i++)
{
var val = _Lookup32[bytes[i]];
result[2*i] = (char)val;
result[2*i + 1] = (char) (val >> 16);
}
return new string(result);
}
static string ByteArrayToHexViaLookup(byte[] bytes) {
string[] hexStringTable = new string[] {
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
"C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
"E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
"F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF",
};
StringBuilder result = new StringBuilder(bytes.Length * 2);
foreach (byte b in bytes) {
result.Append(hexStringTable[b]);
}
return result.ToString();
}
ответ Добавленного Waleed на анализ. Довольно быстро.
Добавленный string.Concat
Array.ConvertAll
вариант для полноты (требует.NET 4.0). Наравне с [1 123] версия.
Тест repo включает больше вариантов такой как [1 124]. Ни один не нарушил результаты никто. foreach
быстрее, чем [1 126], например, но BitConverter
все еще победы.
Добавленный Mykroft SoapHexBinary
ответ на анализ, который принял третье место.
ответ управления байтом Добавленного CodesInChaos, который принял первое место (большим полем на больших блоках текста).
ответ поиска Добавленного Nathan Moinvaziri и вариант из блога Brian Lambert. Оба довольно быстро, но не берущий на себя инициативу в тестовой машине я использовал (Явление AMD 9750).
новый основанный на байте ответ поиска Добавленного @CodesInChaos. Это, кажется, взяло на себя инициативу и в тестах предложения и в полнотекстовых тестах.
Добавленный воздушно-реактивный двигатель оптимизация и unsafe
вариант к этому repo ответа. Если Вы хотите играть в небезопасной игре, можно получить некоторое огромное увеличение производительности по любому из предшествующих главных победителей и на коротких строках и на крупных текстах.
Сегодня я просто встретился с той же самой проблемой, и я столкнулся с этим кодом:
private static string ByteArrayToHex(byte[] barray)
{
char[] c = new char[barray.Length * 2];
byte b;
for (int i = 0; i < barray.Length; ++i)
{
b = ((byte)(barray[i] >> 4));
c[i * 2] = (char)(b > 9 ? b + 0x37 : b + 0x30);
b = ((byte)(barray[i] & 0xF));
c[i * 2 + 1] = (char)(b > 9 ? b + 0x37 : b + 0x30);
}
return new string(c);
}
Источник: сообщение Форума байт [] Массив для Преобразовывания Строки в шестнадцатеричную систему (см. сообщение PZahra). Я изменил код немного для удаления 0x префикса.
я сделал некоторое тестирование производительности к коду, и это было почти в восемь раз быстрее, чем использование BitConverter. ToString () (самое быстрое согласно сообщению patridge).
И для вставки в строку SQL (если вы не используете параметры команды):
public static String ByteArrayToSQLHexString(byte[] Source)
{
return = "0x" + BitConverter.ToString(Source).Replace("-", "");
}
Это отличный пост. Мне нравится решение Waleed. Я не запустил его через тест Патриджа, но кажется, что это довольно быстро. Мне также нужен обратный процесс, преобразуя шестигранную строку в байтовый массив, поэтому я написал его как разворотный раствор Waleed. Не уверен, что это кажется быстрее, чем оригинальное решение Томалака. Опять же, я тоже не пробивал обратный процесс через тест Патриджа.
private byte[] HexStringToByteArray(string hexString)
{
int hexStringLength = hexString.Length;
byte[] b = new byte[hexStringLength / 2];
for (int i = 0; i < hexStringLength; i += 2)
{
int topChar = (hexString[i] > 0x40 ? hexString[i] - 0x37 : hexString[i] - 0x30) << 4;
int bottomChar = hexString[i + 1] > 0x40 ? hexString[i + 1] - 0x37 : hexString[i + 1] - 0x30;
b[i / 2] = Convert.ToByte(topChar + bottomChar);
}
return b;
}
Есть класс под названием SoapHexBinary , который делает именно то, что вы хотите.
using System.Runtime.Remoting.Metadata.W3cXsd2001;
public static byte[] GetStringToBytes(string value)
{
SoapHexBinary shb = SoapHexBinary.Parse(value);
return shb.Value;
}
public static string GetBytesToString(byte[] value)
{
SoapHexBinary shb = new SoapHexBinary(value);
return shb.ToString();
}
Мне не удалось заставить работать предложенный вами код, Olipro. hex[i] + hex[i+1]
, очевидно, возвращает int
.
Тем не менее, я добился некоторого успеха, взяв несколько подсказок из кода Waleeds и собрав это вместе. Он чертовски уродлив, но, похоже, работает и выполняет 1/3 времени по сравнению с другими, согласно моим тестам (используя механизм тестирования patridges). В зависимости от размера входных данных. Если поменять местами ?:s, чтобы сначала отделить 0-9, то результат, вероятно, будет немного быстрее, поскольку цифр больше, чем букв.
public static byte[] StringToByteArray2(string hex)
{
byte[] bytes = new byte[hex.Length/2];
int bl = bytes.Length;
for (int i = 0; i < bl; ++i)
{
bytes[i] = (byte)((hex[2 * i] > 'F' ? hex[2 * i] - 0x57 : hex[2 * i] > '9' ? hex[2 * i] - 0x37 : hex[2 * i] - 0x30) << 4);
bytes[i] |= (byte)(hex[2 * i + 1] > 'F' ? hex[2 * i + 1] - 0x57 : hex[2 * i + 1] > '9' ? hex[2 * i + 1] - 0x37 : hex[2 * i + 1] - 0x30);
}
return bytes;
}
С точки зрения скорости, это, кажется, лучше, чем что-либо здесь:
public static string ToHexString(byte[] data) {
byte b;
int i, j, k;
int l = data.Length;
char[] r = new char[l * 2];
for (i = 0, j = 0; i < l; ++i) {
b = data[i];
k = b >> 4;
r[j++] = (char)(k > 9 ? k + 0x37 : k + 0x30);
k = b & 15;
r[j++] = (char)(k > 9 ? k + 0x37 : k + 0x30);
}
return new string(r);
}
Если вы хотите получить "4-кратное увеличение скорости", о котором сообщает wcoenen, то если это не очевидно: замените hex. Substring(i, 2)
с помощью hex[i]+hex[i+1]
Вы также можете сделать шаг дальше и избавиться от i+=2
, используя i++
в обоих местах.