ඔබ බයිට් අරාව ෂඩාස්රාකාර නූලක් බවට පරිවර්තනය කරන්නේ කෙසේද, සහ අනෙක් අතට?


1386

ඔබට බයිට් අරා හෙක්සැඩිසිමල් නූලක් බවට පරිවර්තනය කළ හැක්කේ කෙසේද?


8
පහත පිළිගත් පිළිතුර බයිට් පරිවර්තනය සඳහා නූල්වල බිහිසුණු නූල් ප්‍රමාණයක් වෙන් කර ඇති බව පෙනේ. මෙය ක්‍රියාකාරීත්වයට බලපාන්නේ කෙසේදැයි මම කල්පනා කරමි
Wim Coenen

9
SoapHexBinary පන්තිය මා සිතන ආකාරයටම කරයි.
මයික්‍රොෆ්ට්

එක් පෝස්ට් එකක ප්‍රශ්න 2 ක් ඇසීම තරමක් සම්මත නොවන බව මට පෙනේ.
සැන්ඩ්රොක්

Answers:


1374

එක්කෝ:

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.


25
ඔබ උප ස්ට්‍රිං භාවිතා කරයි. මෙම ලූපය බිහිසුණු නූල් වස්තු ප්‍රමාණයක් වෙන් නොකරයිද?
Wim Coenen

30
අවංකවම - එය කාර්ය සාධනය නාටකාකාර ලෙස කඳුළු සලන තුරු, මම මෙය නොසලකා හැර ධාවන කාලය සහ GC එය රැකබලා ගැනීමට විශ්වාස කරමි.
ටොමලක්

87
බයිට් එකක් නිබල් දෙකක් බැවින්, බයිට් අරාව වලංගු ලෙස නිරූපණය කරන ඕනෑම හෙක්ස් නූලකට ඊටත් වඩා අනුලකුණු සංඛ්‍යාවක් තිබිය යුතුය. 0 කොතැනකවත් එකතු නොකළ යුතුය - එකක් එකතු කිරීම අනතුරුදායක විය හැකි අවලංගු දත්ත පිළිබඳ උපකල්පනයක් කරයි. කිසියම් දෙයක් නම්, හෙක්ස් නූලෙහි අක්ෂර ගණනක අමුතු සංඛ්‍යාවක් තිබේ නම්, StringToByteArray ක්‍රමය මඟින් FormatException එකක් විසි කළ යුතුය.
ඩේවිඩ් බොයික්

7
J 00jt ඔබ F == 0F යැයි උපකල්පනයක් කළ යුතුය. එක්කෝ එය 0F හා සමාන වේ, නැතහොත් ආදානය ක්ලිප් කර ඇති අතර F යනු ඇත්ත වශයෙන්ම ඔබට නොලැබුණු දෙයක ආරම්භයයි. එම උපකල්පන ඉදිරිපත් කිරීම ඔබේ සන්දර්භය මත රඳා පවතී, නමුත් පොදු අරමුණු ශ්‍රිතයක් ඇමතුම් කේතය සඳහා එම උපකල්පනය කිරීම වෙනුවට අමුතු අක්ෂර අවලංගු යැයි ප්‍රතික්ෂේප කළ යුතු යැයි මම විශ්වාස කරමි.
ඩේවිඩ් බොයික්

11
Av ඩේවිඩ්බොයික් ප්‍රශ්නයට “ක්ලිප් කළ ධාරා අගයන් හසුරුවන්නේ කෙසේද” යන්නට කිසිම සම්බන්ධයක් නැත. නූල් myValue = 10.ToString ("X"); myValue යනු "A" නොව "0A" ය. දැන් ගොස් එම නූල නැවත බයිට් වලට කියවන්න, අපොයි ඔබ එය බිඳ දැමුවා.
00jt

494

කාර්ය සාධන විශ්ලේෂණය

සටහන: 2015-08-20 වන විට නව නායකයා.

මම එක් එක් විවිධ පරිවර්තන ක්‍රම ක්‍රියාත්මක කළේ කිසියම් ගොරහැඩි Stopwatchකාර්ය සාධන පරීක්ෂණයක්, අහඹු වාක්‍යයක් සහිත ධාවනය (n = 61, 1000 පුනරාවර්තන) සහ ව්‍යාපෘති ගුටන්බර්ග් පා text යක් (n = 1,238,957, 150 පුනරාවර්තන) සමඟ ධාවනය කිරීමෙනි. දළ වශයෙන් වේගවත් සිට මන්දගාමී දක්වා ප්‍රති results ල මෙන්න. සියලුම මිනුම් කිනිතුල්ලන් තුළ ඇත (කිනිතුල්ලන් 10,000 = 1 එම්එස් ) සහ සියලු සාපේක්ෂ සටහන් [මන්දගාමී] StringBuilderක්‍රියාත්මක කිරීම සමඟ සැසඳේ . භාවිතා කරන කේතය සඳහා, මෙය ක්‍රියාත්මක කිරීම සඳහා මම දැන් කේතය නඩත්තු කරන පරීක්ෂණ රාමුව නැවත බලන්න .

වියාචනය

අවවාදයයි: කොන්ක්‍රීට් කිසිවක් සඳහා මෙම සංඛ්‍යාලේඛන මත රඳා නොසිටින්න; ඒවා හුදෙක් නියැදි දත්තවල නියැදි ධාවනයකි. ඔබට සැබවින්ම ඉහළ මට්ටමේ කාර්ය සාධනයක් අවශ්‍ය නම්, කරුණාකර මෙම ක්‍රම ඔබේ නිෂ්පාදන අවශ්‍යතා පිළිබඳ පරිසර නියෝජිතයෙකුගෙන් ඔබ භාවිතා කරන දේ පිළිබඳ දත්ත නියෝජිතයා සමඟ පරීක්ෂා කරන්න.

ප්රතිපල

බැලීමේ වගු බයිට් හැසිරවීමට පෙරමුණ ගෙන ඇත. මූලික වශයෙන්, කිසියම් නිබ්ල් හෝ බයිට් හෙක්ස් වල ඇති දේ පූර්ව ගණනය කිරීමේ ක්‍රමයක් තිබේ. ඉන්පසු, ඔබ දත්ත ඉරා දැමූ විට, ඊළඟ කොටස දෙස බැලීමෙන් එය කුමන හෙක්ස් නූල් දැයි බලන්න. එම අගය පසුව යම් ආකාරයකින් ප්‍රති string ලය වන නූල් ප්‍රතිදානයට එකතු වේ. දිගු කලක් තිස්සේ බයිට් හැසිරවීම, සමහර සංවර්ධකයින්ට කියවීමට අපහසු විය හැකි ඉහළම ක්‍රියාකාරී ප්‍රවේශය විය.

ඔබගේ හොඳම ඔට්ටුව තවමත් නියෝජිත දත්ත කිහිපයක් සොයාගෙන එය නිෂ්පාදන වැනි පරිසරයක අත්හදා බැලීමට ය. ඔබට වෙනස් මතක සීමාවන් තිබේ නම්, වේගවත් නමුත් වැඩි මතකයක් පරිභෝජනය කරන ක්‍රමයකට අඩු ප්‍රතිපාදන සහිත ක්‍රමයකට ඔබ කැමති විය හැකිය.

පරීක්ෂණ කේතය

මා භාවිතා කළ පරීක්ෂණ කේතය සමඟ සෙල්ලම් කිරීමට නිදහස් වන්න. ඒ අනුවාදය මෙහි ඇතුළත් නමුත් පරිගණක ක්රිඩාවට සමාන නිදහස් හැඟීම වේ ණයකට හා ඔබේ ම ක්රම එකතු කරන්න. ඔබට සිත්ගන්නාසුලු යමක් හමු වුවහොත් හෝ එය භාවිතා කරන පරීක්ෂණ රාමුව වැඩිදියුණු කිරීමට උදව් කිරීමට අවශ්‍ය නම් කරුණාකර අදින්න ඉල්ලීමක් ඉදිරිපත් කරන්න.

  1. නව ස්ථිතික ක්‍රමය ( Func<byte[], string>) /Tests/ConvertByteArrayToHexString/Test.cs වෙත එක් කරන්න.
  2. TestCandidatesඑම පන්තියේම ප්‍රතිලාභ අගයට එම ක්‍රමයේ නම එක් කරන්න .
  3. GenerateTestInputඑම පන්තියේම අදහස් ටොගල් කිරීමෙන් ඔබට අවශ්‍ය ආදාන අනුවාදය, වාක්‍යය හෝ පෙළ ක්‍රියාත්මක කරන බවට වග බලා ගන්න .
  4. F5ප්‍රතිදානය සඳහා පහර දී රැඳී සිටින්න (/ බින් ෆෝල්ඩරයේ HTML ඩම්ප් එකක් ද ජනනය වේ).
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();
}

යාවත්කාලීන කිරීම (2010-01-13)

විශ්ලේෂණයට වලීඩ්ගේ පිළිතුර එකතු කරන ලදි. ඉතා වේගවත්.

යාවත්කාලීන කිරීම (2011-10-05)

එකතු string.Concat Array.ConvertAllසම්පූර්ණත්වය සඳහා ප්රභේද්යයක් (.NET 4.0 අවශ්ය). හා සම string.Joinඅනුවාදය.

යාවත්කාලීන කිරීම (2012-02-05)

ටෙස්ට් රෙපෝ වැනි තවත් ප්‍රභේද ඇතුළත් වේ StringBuilder.Append(b.ToString("X2")). කිසිවෙකු ප්‍රති the ල අවුල් කළේ නැත. foreachවේගවත් වඩා {IEnumerable}.Aggregateඋදාහරණයක් වශයෙන්, නමුත්, BitConverterතවමත් ජයග්රහණය කර තිබෙනවා.

යාවත්කාලීන කිරීම (2012-04-03)

SoapHexBinaryවිශ්ලේෂණයට මයික්‍රොෆ්ට්ගේ පිළිතුර එක් කළ අතර එය තෙවන ස්ථානයට පත්විය.

යාවත්කාලීන කිරීම (2013-01-15)

CodesInChaos හි බයිට් හැසිරවීමේ පිළිතුර එකතු කරන ලද අතර එය පළමු ස්ථානය ලබා ගත්තේය (විශාල පෙළ කොටස්වල විශාල ආන්තිකයකින්).

යාවත්කාලීන කිරීම (2013-05-23)

නේතන් මොයින්වසිරිගේ විමසුම් පිළිතුර සහ බ්‍රයන් ලැම්බර්ට්ගේ බ්ලොග් අඩවියෙන් ප්‍රභේදය එක් කරන ලදි. දෙකම වේගවත්, නමුත් මා භාවිතා කළ පරීක්ෂණ යන්ත්‍රයට පෙරමුණ නොගැනීම (AMD Phenom 9750).

යාවත්කාලීන කිරීම (2014-07-31)

@ CodesInChaos හි නව බයිට් මත පදනම් වූ විමසුම් පිළිතුර එක් කරන ලදි. එය වාක්‍ය පරීක්ෂණ සහ පූර්ණ-පෙළ පරීක්ෂණ යන දෙකටම පෙරමුණ ගෙන ඇති බව පෙනේ.

යාවත්කාලීන කිරීම (2015-08-20)

එකතු airbreather ගේ ප්රතිස්තිකරණය හා unsafeමේ ප්රභේද්යයක් පිළිතුර ගේ ණයකට . ඔබට අනාරක්ෂිත ක්‍රීඩාවට ක්‍රීඩා කිරීමට අවශ්‍ය නම්, කෙටි නූල් සහ විශාල පෙළ යන දෙකෙහිම පෙර ඕනෑම ජයග්‍රාහකයෙකුට වඩා විශාල කාර්ය සාධනයක් ලබා ගත හැකිය.


වලීඩ්ගේ පිළිතුරෙන් කේතය පරීක්ෂා කිරීමට ඔබ කැමතිද? එය ඉතා වේගවත් බව පෙනේ. stackoverflow.com/questions/311165/…
ක්‍රිස්ටියන් ඩයකොනෙස්කු

6
ඔබ විසින්ම ඉල්ලූ දෙය තනිවම කිරීමට ඔබට කේතය ලබා දී තිබියදීත්, වලීඩ් පිළිතුර ඇතුළත් කිරීම සඳහා මම පරීක්ෂණ කේතය යාවත්කාලීන කළෙමි. සියලු කේන්තිය පසෙකට දමා, එය වඩා වේගවත් ය.
පැට්රිජ්

2
OdesCodesInChaos සිදු විය. එය මගේ පරීක්ෂණ වලදී තරමක් දුරට ජය ගත්තේය. මම තවම ඉහළ ක්‍රම දෙකම සම්පූර්ණයෙන් වටහාගෙන ඇති බවක් මවාපාමින් නැත, නමුත් ඒවා සෘජු අන්තර්ක්‍රියා වලින් පහසුවෙන් සැඟවී ඇත.
patridge

6
මෙම පිළිතුරට “ස්වාභාවික” හෝ පොදු දේ කුමක්ද යන ප්‍රශ්නයට පිළිතුරු දීමට අදහසක් නැත. ඉලක්කය වන්නේ ඔබට මෙම පරිවර්තනයක් කිරීමට අවශ්‍ය වූ විට, ඔබ ඒවා බොහෝ දේ කිරීමට පෙළඹෙන බැවින් මිනිසුන්ට මූලික කාර්ය සාධන මිණුම් සලකුණු ලබා දීමයි. යමෙකුට අමු වේගය අවශ්‍ය නම්, ඔවුන් අපේක්ෂිත පරිගණක පරිසරය තුළ සුදුසු පරීක්ෂණ දත්ත සමඟ මිණුම් සලකුණු ක්‍රියාත්මක කරයි. ඉන්පසුව, ඔබ එය නැවත කිසි විටෙකත් ක්‍රියාත්මක නොකෙරෙන ව්‍යාප්ති ක්‍රමයකට සම්බන්ධ කරන්න (උදා. bytes.ToHexStringAtLudicrousSpeed()).
patridge

2
ඉහළ කාර්ය සාධනයක් සහිත මේස මත පදනම් වූ ක්‍රියාත්මක කිරීමක් නිපදවා ඇත. එහි ආරක්ෂිත ප්‍රභේදය මගේ CPU හි වත්මන් නායකයාට වඩා 30% ක් වේගවත් ය. අනාරක්ෂිත ප්‍රභේද ඊටත් වඩා වේගවත් ය. stackoverflow.com/a/24343727/445517
CodesInChaos

246

ඔබට අවශ්‍ය දේ හරියටම කරන 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();
}

36
SoapHexBinary .NET 1.0 වෙතින් ලබා ගත හැකි අතර එය mscorlib හි ඇත. එය විහිලු නාම අවකාශයක් තිබියදීත්, එය ඇසූ ප්‍රශ්නයම කරයි.
Sly Gryphon

4
නියමයි! අනෙක් විසඳුම මෙන් ඔබට GetStringToBytes සඳහා ප්‍රමුඛ 0 සමඟ අමුතු නූල් පෑඩ් කිරීමට අවශ්‍ය බව සලකන්න.
කාටර් මෙඩ්ලින්

ක්‍රියාත්මක කිරීමේ සිතුවිල්ල ඔබ දැක තිබේද? පිළිගත් පිළිතුරට වඩා හොඳ IMHO එකක් ඇත.
mfloryan

6
මෙහි මොනෝ ක්‍රියාත්මක කිරීම දැකීමට සිත්ගන්නා සුළුය
ජෙරමි

1
.NET Core / .NET Standard හි SoapHexBinary සඳහා සහය නොදක්වයි ...
juFo

141

ක්‍රිප්ටෝ කේතය ලිවීමේදී දත්ත මත යැපෙන වේලාවන් පැති නාලිකා ප්‍රහාරයන්ට තුඩු දිය හැකි බැවින් දත්ත මත යැපෙන ශාඛා සහ වගු බැලීම වළක්වා ගැනීම සාමාන්‍ය වේ.

එය ද ඉතා වේගවත් ය.

static string ByteToHexBitFiddle(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);
}

Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn


මෙහි ඇතුළු වන්නෙනි, සියලු බලාපොරොත්තු අත්හරින්න

අමුතු බිටු විකාරය පිළිබඳ පැහැදිලි කිරීමක්:

  1. bytes[i] >> 4බයිට් එකක ඉහළ නිබ්ල් එක
    bytes[i] & 0xFනිස්සාරණය කරයි
  2. b - 10
    වන < 0අගයන් සඳහා b < 10වූ දශම ඉලක්කම් බවට පත් වනු ඇත,
    වන >= 0අගයන් සඳහා b > 10ලිපියක් බවට පත් වනු ඇත, Aකිරීමට F.
  3. i >> 31අත්සන් කරන ලද බිට් 32 නිඛිලයක් භාවිතා කිරීමෙන් ලකුණ උපුටා ගනී, අත්සන් දිගුවට ස්තූතියි. එය -1සඳහා i < 0සහ 0සඳහා වනු ඇත i >= 0.
  4. ඒකාබද්ධ 2) වන සහ 3), ඒ දර්ශන (b-10)>>31වනු ඇත 0ලිපි හා -1ඉලක්කම් සඳහා.
  5. අක්ෂර සඳහා නඩුව දෙස බලා, පසුගිය summand බවට පත් 0, සහ bඅප එය සිතියම්ගත කිරීමට අවශ්ය 10 15. පරාසයක වේ A(65) දක්වා F(70), 55 එකතු (ගම්ය වන 'A'-10).
  6. ඉලක්කම් සඳහා නඩුව දෙස බලන විට, අපට අවසාන සාරාංශය අනුවර්තනය කිරීමට අවශ්‍ය වන අතර එමඟින් එය b0 සිට 9 පරාසයේ සිට 0(48) සිට 9(57) දක්වා පරාසයට සිතියම් ගත කරයි . මෙයින් අදහස් කරන්නේ එය -7 ( '0' - 55) බවට පත්විය යුතු බවයි.
    දැන් අපි 7. සමග පමණක් ගුණ නමුත් -1 1, සියල්ල බිටු නියෝජනය කරන බැවින්, අපි ඒ වෙනුවට භාවිතා කළ හැකි හැකි & -7බැවින් (0 & -7) == 0හා (-1 & -7) == -7.

තවත් කරුණු කිහිපයක්:

  • cමිනුම් පෙන්වීමෙන් එය ගණනය iකිරීම ලාභදායී බව පෙන්වන බැවින් මම දර්ශකයට දෙවන ලූප විචල්‍යයක් භාවිතා නොකළෙමි .
  • i < bytes.Lengthලූපයේ ඉහළ මායිම හරියටම භාවිතා කිරීමෙන් ජිටර්ට සීමාවන් පරීක්ෂා කිරීම ඉවත් කිරීමට ඉඩ සලසයි bytes[i], එබැවින් මම එම ප්‍රභේදය තෝරා ගතිමි.
  • Int bඑකක් සෑදීමෙන් අනවශ්‍ය ලෙස පරිවර්තනය කිරීමට සහ බයිට් කිරීමට ඉඩ ලබා දේ.

10
හා hex stringකිරීමට byte[] array?
AaA

15
+1 එම මැජික් ක්‍රියාවෙන් පසු ඔබේ මූලාශ්‍රය නිසියාකාරව උපුටා දැක්වීම සඳහා. සියලුම හිම කැට චතුල්හු.
එඩ්වඩ්

4
නූල් බයිට් [] ගැන කුමක් කිව හැකිද?
Syaiful Nizam Yahya

9
හොඳයි! සිම්පල් ප්‍රතිදානය අවශ්‍ය අය සඳහා, ප්‍රකාශනය පැහැදිලිවම වෙනස් වේ87 + b + (((b-10)>>31)&-39)
eXavier

2
AAaA ඔබ කිව්වේ " byte[] array", එහි තේරුම බයිට් අරා සමූහයකි, හෝ byte[][]. මම විනෝද වෙමින් සිටියෙමි.
CoolOppo

98

ඔබට වඩා නම්‍යශීලී බවක් අවශ්‍ය නම් 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")));

(මුල් ලිපිය පිළිබඳ අදහස් දැක්වීමකින් දෙවැන්න.)


21
ඊටත් වඩා කෙටි: String.Concat (Array.ConvertAll (බයිට්, x => x.ToString ("X2"))
නෙස්ටර්

14
ඊටත් වඩා කෙටි: String.Concat (bytes.Select (b => b.ToString ("X2"))) [.NET4]
Allon Guralnek

14
ප්‍රශ්නයට අඩක් පමණක් පිළිතුරු සපයයි.
Sly Gryphon

1
දෙවැන්නාට අවශ්‍ය ඇයි .නෙට් 4? String.Concat .Net 2.0 හි ඇත.
පොලිෆන්

2
එම “90 විලාසිතාවේ” ලූප සාමාන්‍යයෙන් වේගවත් වන නමුත් බොහෝ සන්දර්භයන්හි එය වැදගත් නොවන තරම් සුළු ප්‍රමාණයකින්. තවමත් සඳහන් කිරීම වටී
ඔස්ටින්_ ඇන්ඩර්සන්

70

තවත් විමසුම් වගු පදනම් කරගත් ප්‍රවේශයකි. මෙය එක් එක් බයිටයක් සඳහා එක් බැලීමේ වගුවක් පමණක් භාවිතා කරයි.

private static readonly uint[] _lookup32 = CreateLookup32();

private static uint[] CreateLookup32()
{
    var result = new uint[256];
    for (int i = 0; i < 256; i++)
    {
        string s=i.ToString("X2");
        result[i] = ((uint)s[0]) + ((uint)s[1] << 16);
    }
    return result;
}

private static string ByteArrayToHexViaLookup32(byte[] bytes)
{
    var lookup32 = _lookup32;
    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);
}

ඒ වගේම මම මේ භාවිතා ප්රභේදයන් පරීක්ෂා ushort, struct{char X1, X2}, struct{byte X1, X2}එම විමසුම් වගුවේ.

සම්පාදන ඉලක්කය (x86, X64) මත පදනම්ව, ඒවා දළ වශයෙන් එකම ක්‍රියාකාරීත්වයක් ඇති හෝ මෙම ප්‍රභේදයට වඩා තරමක් මන්දගාමී විය.


ඊටත් වඩා ඉහළ කාර්ය සාධනයක් සඳහා, එහි unsafeසහෝදරයා:

private static readonly uint[] _lookup32Unsafe = CreateLookup32Unsafe();
private static readonly uint* _lookup32UnsafeP = (uint*)GCHandle.Alloc(_lookup32Unsafe,GCHandleType.Pinned).AddrOfPinnedObject();

private static uint[] CreateLookup32Unsafe()
{
    var result = new uint[256];
    for (int i = 0; i < 256; i++)
    {
        string s=i.ToString("X2");
        if(BitConverter.IsLittleEndian)
            result[i] = ((uint)s[0]) + ((uint)s[1] << 16);
        else
            result[i] = ((uint)s[1]) + ((uint)s[0] << 16);
    }
    return result;
}

public static string ByteArrayToHexViaLookup32Unsafe(byte[] bytes)
{
    var lookupP = _lookup32UnsafeP;
    var result = new char[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 new string(result);
}

නැතහොත් කෙලින්ම නූලට ලිවීම පිළිගත හැකි යැයි ඔබ සලකන්නේ නම්:

public 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;
}

අනාරක්ෂිත අනුවාදයේ බැලීමේ වගුව නිර්මාණය කිරීම පෙර සැකසූ බයිට් වල නිබ්බල් මාරු කරන්නේ ඇයි? මම හිතුවේ එන්ඩියන්ස් එක වෙනස් කළේ බයිට් ගණනකින් සෑදී ඇති ආයතනවල අනුපිළිවෙල පමණක් බවයි.
රයිෆ් ආටෙෆ්

A රයිෆාටෙෆ් මෙහි වැදගත් වන්නේ නිබ්ල්ස් අනුපිළිවෙල නොවේ. නමුත් බිට් 32 නිඛිලයක බිට් වචන 16 ක අනුපිළිවෙල. නමුත් මම එය නැවත ලිවීමට සලකා බලමින් සිටිමි.
CodesInChaos

කේතය නැවත කියවන විට, ඔබ මෙය කළේ ඔබ වර්‍ගය * පසුව යූන්ට් එකකට දමා එය පැවරූ විට (හෙක්ස් වර්‍ගය ජනනය කරන විට), ධාවන කාලය / සීපීයූ විසින් බයිට් පෙරළනු ඇත (යූන්ට සලකන්නේ නැති නිසා වෙනම 16-බිටු අක්ෂර 2 කට සමාන වේ) එබැවින් ඔබ වන්දි ගෙවීම සඳහා ඒවා පෙරළා දමයි. මම හරිද? එන්ඩියන්ස් ව්‍යාකූලයි :-).
රයිෆ් ආටෙෆ්

4
මෙය ප්‍රශ්නයෙන් අඩකටම පිළිතුරු සපයයි ... හෙක්ස් නූල් සිට බයිට් දක්වා කෙසේද?
නාර්වාලෙක්ස්

3
OdesCodesInChaos Spanවෙනුවට දැන් භාවිතා කළ හැකිදැයි මම කල්පනා කරමි unsafe??
කොන්රාඩ්

65

ඔබට 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-එෆ්

වැඩි විස්තර: BitConverter.ToString Method (බයිට් [])


14
ප්‍රශ්නයට අඩක් පමණක් පිළිතුරු සපයයි.
Sly Gryphon

3
පිළිතුරේ දෙවන කොටස කොහිද?
සවාන්

57

මට අද එකම ගැටලුවකට මුහුණ දීමට සිදු වූ අතර, මෙම කේතය මට හමු විය:

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 () (පැට්‍රිජ්ගේ තනතුරට අනුව වේගවත්ම) භාවිතා කිරීමට වඩා අට ගුණයකින් වේගවත් විය.


මෙය අවම මතකයක් භාවිතා කරන බව සඳහන් නොකල යුතුය. අතරමැදි නූල් කිසිවක් නිර්මාණය කර නැත.
චොචෝස්

8
ප්‍රශ්නයට අඩක් පමණක් පිළිතුරු සපයයි.
Sly Gryphon

මෙය විශිෂ්ටයි, මන්ද එය මූලික වශයෙන් NETMF ද ඇතුළුව ඕනෑම NET අනුවාදයක් මත ක්‍රියා කරයි. ජයග්රාහකයෙක්!
ජෝන්සම් නැවත ස්ථාපනය කරන්න මොනිකා

1
පිළිගත් පිළිතුර ප්‍රශ්නයේ අනෙක් භාගය නියෝජනය කරන විශිෂ්ට HexToByteArray ක්‍රම 2 ක් සපයයි. මෙම ක්‍රියාවලියේදී නූල් විශාල සංඛ්‍යාවක් නිර්මාණය නොකර මෙය කරන්නේ කෙසේද යන ප්‍රශ්නයට වලීඩ්ගේ විසඳුම පිළිතුරු සපයයි.
බ්‍රෙන්ඩන් අයික්ස්ටෙඩ්

නව නූල් (ඇ) පිටපත් කර නැවත වෙන් කර තිබේද? නැතහොත් එය හුදෙක් වර්‍ගය ඔතා තැබිය හැක්කේ කවදාදැයි දැන ගැනීමට තරම් බුද්ධිමත්ද?
jjxtra

19

මෙය ටොමලක්ගේ අතිශය ජනප්‍රිය පිළිතුරේ 4 වන සංශෝධනයට පිළිතුරකි (සහ පසුව කරන ලද සංස්කරණයන්).

මෙම සංස්කරණය වැරදියි කියා මම නඩුව ඉදිරිපත් කර එය ආපසු හැරවිය හැක්කේ මන්දැයි පැහැදිලි කරමි. මඟදී, ඔබට සමහර අභ්‍යන්තරයන් ගැන යමක් හෝ දෙකක් ඉගෙන ගත හැකි අතර, නොමේරූ ප්‍රශස්තිකරණය යනු කුමක්ද සහ එය ඔබට දෂ්ට කරන්නේ කෙසේද යන්න පිළිබඳ තවත් උදාහරණයක් බලන්න.

TL; dr: යන්තම් භාවිතා Convert.ToByteසහ String.Substringඔබ ඉක්මන් (පහත "මුල් පිටපත කේතය") ඉන්නේ නම්, එය ඔබ නැවත ක්රියාත්මක කිරීමට අවශ්ය නැති නම්, හොඳම එකතුවක් වේ Convert.ToByte. Convert.ToByteඔබට කාර්ය සාධනය අවශ්‍ය නම් භාවිතා නොකරන වඩා දියුණු දෙයක් භාවිතා කරන්න (වෙනත් පිළිතුරු බලන්න) . එපා නොවන හැර වෙනත් වෙන කිසිම දෙයක් භාවිතා String.Substringසංයෝජනය Convert.ToByteකෙනෙකුට ඇති දෙයක් රසවත් මෙම පිළිතුර අදහස් මේ ගැන කියන්න නොමැති නම් මිස,.

අනතුරු ඇඟවීම: මේ පිළිතුර යල් පැන ගිය එකක් වනු ඇත නම් එය Convert.ToByte(char[], Int32)අධි බර රාමුව තුළ ක්රියාත්මක වේ. මෙය ඉක්මනින් සිදුවීමට ඉඩක් නැත.

සාමාන්‍ය රීතියක් ලෙස, “නොමේරූ ලෙස ප්‍රශස්තිකරණය නොකරන්න” යැයි කීමට මම එතරම් කැමැත්තක් නොදක්වන්නෙමි. ප්‍රශස්තිකරණය කළ යුතුද නැද්ද යන්න තීරණය කිරීමේදී ඔබ සලකා බැලිය යුතු එකම දෙය නම්: "ප්‍රශස්තිකරණ ප්‍රවේශයන් නිසි ලෙස විමර්ශනය කිරීමට මට කාලය හා සම්පත් තිබේද?". ඔබ එසේ නම්, එය ඉතා ඉක්මනින් තියෙන්නේ, ඔබගේ ව්යාපෘතිය තෙක් රැක වඩා පරිණත හෝ ඔබට කාර්ය සාධනය අවශ්ය වන තුරු (සැබෑ අවශ්යතාවක් තිබෙනවා නම්, ඔබ ඇත කිරීමට කාලය). මේ අතර, ඒ වෙනුවට වැඩ කළ හැකි සරලම දේ කරන්න.

මුල් කේතය:

    public static byte[] HexadecimalStringToByteArray_Original(string input)
    {
        var outputLength = input.Length / 2;
        var output = new byte[outputLength];
        for (var i = 0; i < outputLength; i++)
            output[i] = Convert.ToByte(input.Substring(i * 2, 2), 16);
        return output;
    }

සංශෝධනය 4:

    public static byte[] HexadecimalStringToByteArray_Rev4(string input)
    {
        var outputLength = input.Length / 2;
        var output = new byte[outputLength];
        using (var sr = new StringReader(input))
        {
            for (var i = 0; i < outputLength; i++)
                output[i] = Convert.ToByte(new string(new char[2] { (char)sr.Read(), (char)sr.Read() }), 16);
        }
        return output;
    }

සංශෝධනය මග හැර ඒ වෙනුවට String.Substringභාවිතා කරයි StringReader. දී ඇති හේතුව:

සංස්කරණය කරන්න: තනි පාස් පාර්සර් එකක් භාවිතා කිරීමෙන් ඔබට දිගු නූල් සඳහා කාර්ය සාධනය වැඩි දියුණු කළ හැකිය:

හොඳයි, සඳහා යොමු කේතයString.Substring දෙස බලන විට , එය පැහැදිලිවම දැනටමත් "තනි පාස්" ය; ඇයි එය එසේ නොවිය යුත්තේ? එය ක්‍රියාත්මක වන්නේ බයිට් මට්ටමින් මිස අන්වාදේශ යුගල මත නොවේ.

කෙසේ වෙතත් එය නව නූලක් වෙන් කරයි, නමුත් පසුව ඔබට Convert.ToByteකෙසේ හෝ සමත් වීමට එකක් වෙන් කළ යුතුය . තවද, සංශෝධනයේ දක්වා ඇති විසඳුම සෑම පුනරාවර්තනයක් සඳහාම තවත් වස්තුවක් වෙන් කරයි (ද්වි-වර්‍ග අරාව); ඔබට එම වෙන් කිරීම ආරක්ෂිතව ලූපයෙන් පිටත තබා එය වළක්වා ගැනීම සඳහා අරාව නැවත භාවිතා කළ හැකිය.

    public static byte[] HexadecimalStringToByteArray(string input)
    {
        var outputLength = input.Length / 2;
        var output = new byte[outputLength];
        var numeral = new char[2];
        using (var sr = new StringReader(input))
        {
            for (var i = 0; i < outputLength; i++)
            {
                numeral[0] = (char)sr.Read();
                numeral[1] = (char)sr.Read();
                output[i] = Convert.ToByte(new string(numeral), 16);
            }
        }
        return output;
    }

සෑම ෂඩාස්රාකාරයක්ම numeralඉලක්කම් දෙකක් (සංකේත) භාවිතා කරමින් තනි අෂ්ටකයක් නියෝජනය කරයි.

නමුත් එසේ නම්, StringReader.Readදෙවරක් අමතන්නේ ඇයි? එහි දෙවන අධි භාරය අමතා වර්‍ග දෙකේ අරාවෙහි අක්ෂර දෙකක් එකවර කියවීමට ඉල්ලා සිටින්න; ඇමතුම් ප්‍රමාණය දෙකකින් අඩු කරන්න.

    public static byte[] HexadecimalStringToByteArray(string input)
    {
        var outputLength = input.Length / 2;
        var output = new byte[outputLength];
        var numeral = new char[2];
        using (var sr = new StringReader(input))
        {
            for (var i = 0; i < outputLength; i++)
            {
                var read = sr.Read(numeral, 0, 2);
                Debug.Assert(read == 2);
                output[i] = Convert.ToByte(new string(numeral), 16);
            }
        }
        return output;
    }

ඔබට ඉතිරිව ඇත්තේ “අගය” එකතු කළ සමාන්තර දර්ශකයක් (අභ්‍යන්තරය _pos) වන අතර එය ඔබට ඔබම ප්‍රකාශ කළ හැකිය ( jනිදසුනක් ලෙස), අතිරික්ත දිග විචල්‍යය (අභ්‍යන්තර _length) සහ ආදානය පිළිබඳ අතිරික්ත සඳහනක් නූල් (අභ්‍යන්තර _s). වෙනත් වචන වලින් කිවහොත්, එය නිෂ් .ල ය.

Read"කියවන්නේ" කෙසේදැයි ඔබ සිතන්නේ නම්, කේතය දෙස බලන්න , එය කරන්නේ String.CopyToආදාන නූලට ඇමතීම පමණි . ඉතිරිය අපට අවශ්‍ය නොවන සාරධර්ම පවත්වා ගැනීම සඳහා පොත් තැබීමේ පොදු කාර්යයකි.

එබැවින්, දැනටමත් නූල් කියවනය ඉවත් කර CopyToඔබම අමතන්න ; එය සරල, පැහැදිලි සහ කාර්යක්ෂම වේ.

    public static byte[] HexadecimalStringToByteArray(string input)
    {
        var outputLength = input.Length / 2;
        var output = new byte[outputLength];
        var numeral = new char[2];
        for (int i = 0, j = 0; i < outputLength; i++, j += 2)
        {
            input.CopyTo(j, numeral, 0, 2);
            output[i] = Convert.ToByte(new string(numeral), 16);
        }
        return output;
    }

ඔබට jසමාන්තරව පියවර දෙකක වර්ධක දර්ශකයක් iඅවශ්‍යද? ඇත්ත වශයෙන්ම නැත, iදෙකකින් ගුණ කරන්න (සම්පාදකයාට එකතු කිරීමකට ප්‍රශස්තිකරණය කළ හැකි).

    public static byte[] HexadecimalStringToByteArray_BestEffort(string input)
    {
        var outputLength = input.Length / 2;
        var output = new byte[outputLength];
        var numeral = new char[2];
        for (int i = 0; i < outputLength; i++)
        {
            input.CopyTo(i * 2, numeral, 0, 2);
            output[i] = Convert.ToByte(new string(numeral), 16);
        }
        return output;
    }

විසඳුම දැන් මොන වගේද? එය ආරම්භයේ දී පමණක් වෙනුවට භාවිතා විය හරියටම වැනි String.Substringවැල වෙන් කිරීමට සහ ඒ සඳහා දත්ත පිටපත්, ඔබ කිරීමට ෂඩ් දශම ඉලක්කම් පිටපත් කුමන අතරමැදියා අරා භාවිතා කරන්නේ නම් වැල ඔබ වෙන් කිරීම සහ එම දත්ත පිටපත් නැවත සිට අරාව සහ නූලට (ඔබ එය නූල් සාදන්නා තුළ සමත් වූ විට). දෙවන පිටපත දැනටමත් අභ්‍යන්තර තටාකයේ තිබේ නම් දෙවන පිටපත ප්‍රශස්තිකරණය කළ හැකි නමුත් String.Substringමෙම අවස්ථා වලදී එය වළක්වා ගත හැකිය.

ඇත්ත වශයෙන්ම, ඔබ String.Substringනැවත බැලුවහොත් , එය සාමාන්‍යයෙන් ඔබට කළ හැකි ප්‍රමාණයට වඩා වේගයෙන් නූල් වෙන් කිරීම සඳහා නූල් සාදා ඇති ආකාරය පිළිබඳ පහත් මට්ටමේ අභ්‍යන්තර දැනුමක් භාවිතා කරන බව ඔබට පෙනේ, තවද එය CopyToවළක්වා ගැනීම සඳහා කෙලින්ම එහි භාවිතා කරන කේතයම දක්වයි. ඇමතුම ඉහළින්.

String.Substring

  • නරකම අවස්ථාව: එක් වේගවත් වෙන් කිරීමක්, එක් වේගවත් පිටපතක්.
  • හොඳම අවස්ථාව: වෙන් කිරීමක් නැත, පිටපතක් නොමැත.

අත්පොත ක්‍රමය

  • නරකම අවස්ථාව: සාමාන්‍ය ප්‍රතිපාදන දෙකක්, එක් සාමාන්‍ය පිටපතක්, එක් වේගවත් පිටපතක්.
  • හොඳම අවස්ථාව: එක් සාමාන්‍ය වෙන් කිරීමක්, එක් සාමාන්‍ය පිටපතක්.

නිගමනය? ඔබට භාවිතා කිරීමට අවශ්‍ය නම්Convert.ToByte(String, Int32) (එම ක්‍රියාකාරිත්වය ඔබම නැවත ක්‍රියාත්මක කිරීමට ඔබට අවශ්‍ය නැති නිසා), පරාජය කිරීමට ක්‍රමයක් නොපෙනේ String.Substring; ඔබ කරන්නේ රවුමක ධාවනය වන අතර රෝදය නැවත ප්‍රතිනිර්මාණය කිරීම (උප ප්‍රශස්ත ද්‍රව්‍ය සමඟ පමණි).

ඔබට අතිශය කාර්ය සාධනයක් අවශ්‍ය නොවන්නේ නම් එය භාවිතා කිරීම Convert.ToByteසහ String.Substringවලංගු තේරීමක් බව සලකන්න . මතක තබා ගන්න: විකල්පයක් තෝරා ගන්නේ එය නිසි ලෙස ක්‍රියාත්මක වන්නේ කෙසේදැයි සොයා බැලීමට ඔබට කාලය හා සම්පත් තිබේ නම් පමණි.

එය තිබුනේ නම් Convert.ToByte(char[], Int32), දේවල් ඇත්ත වශයෙන්ම වෙනස් වනු ඇත (මා ඉහත විස්තර කළ දේ කිරීමට සහ සම්පූර්ණයෙන්ම වළක්වා ගැනීමට හැකි වනු ඇත String).

"මග හැරීමෙන් String.Substring" වඩා හොඳ කාර්ය සාධනයක් වාර්තා කරන පුද්ගලයින් ද මග හැරෙනු ඇතැයි මම සැක කරමි Convert.ToByte(String, Int32), ඔබට කෙසේ හෝ කාර්ය සාධනය අවශ්‍ය නම් ඔබ සැබවින්ම කළ යුතුය. ඒ සඳහා විවිධ ප්‍රවේශයන් සොයා ගැනීමට ගණන් කළ නොහැකි වෙනත් පිළිතුරු දෙස බලන්න.

වියාචනය: යොමු මූලාශ්‍රය යාවත්කාලීන දැයි තහවුරු කර ගැනීම සඳහා මම රාමුවේ නවතම අනුවාදය විසන්ධි කර නැත, මම හිතන්නේ එය එසේ ය.

දැන්, මේ සියල්ල හොඳ සහ තර්කානුකූල යැයි පෙනේ, ඔබ මෙතෙක් දුරට සමත් වී ඇත්දැයි බලාපොරොත්තු විය හැකිය. නමුත් එය සත්‍යයක්ද?

Intel(R) Core(TM) i7-3720QM CPU @ 2.60GHz
    Cores: 8
    Current Clock Speed: 2600
    Max Clock Speed: 2600
--------------------
Parsing hexadecimal string into an array of bytes
--------------------
HexadecimalStringToByteArray_Original: 7,777.09 average ticks (over 10000 runs), 1.2X
HexadecimalStringToByteArray_BestEffort: 8,550.82 average ticks (over 10000 runs), 1.1X
HexadecimalStringToByteArray_Rev4: 9,218.03 average ticks (over 10000 runs), 1.0X

ඔව්!

බංකුවේ රාමුව සඳහා පාර්ට්රිජ් වෙත මුක්කු, හැක් කිරීම පහසුය. භාවිතා කරන ආදානය පහත දැක්වෙන SHA-1 හෑෂ් බයිට් 100,000 ක් දිග නූලක් සෑදීම සඳහා 5000 වතාවක් පුනරාවර්තනය වේ.

209113288F93A9AB8E474EA78D899AFDBB874355

විනෝද වන්න! (නමුත් මධ්‍යස්ථව ප්‍රශස්ත කරන්න.)


දෝෂය: {"හඳුනාගත හැකි ඉලක්කම් කිසිවක් සොයාගත නොහැකි විය."}
ප්‍රියා ජග්තාප්

17

@CodesInChaos (ප්‍රතිලෝම ක්‍රමය) මගින් පිළිතුරු දීමට අනුපූරකව

public static byte[] HexToByteUsingByteManipulation(string s)
{
    byte[] bytes = new byte[s.Length / 2];
    for (int i = 0; i < bytes.Length; i++)
    {
        int hi = s[i*2] - 65;
        hi = hi + 10 + ((hi >> 31) & 7);

        int lo = s[i*2 + 1] - 65;
        lo = lo + 10 + ((lo >> 31) & 7) & 0x0f;

        bytes[i] = (byte) (lo | hi << 4);
    }
    return bytes;
}

පැහැදිලි කිරීම:

& 0x0f කුඩා අකුරු සඳහා ද සහාය දැක්වීම ය

hi = hi + 10 + ((hi >> 31) & 7); සමාන වේ:

hi = ch-65 + 10 + (((ch-65) >> 31) & 7);

'0' සඳහා .. '9' යනු එය සමාන hi = ch - 65 + 10 + 7;වේ hi = ch - 48(මෙය හේතුව නිසා 0xffffffff & 7).

'ඒ' සඳහා .. 'එෆ්' යනු එයයි hi = ch - 65 + 10;(මෙයට හේතුව 0x00000000 & 7).

'ඒ' .. 'f' අපි ලොකු සංඛ්යා ඇති නිසා අප යම් බිටු කරමින් පෙරනිමි අනුවාදය සිට 32 අඩු කළ යුතුය 0භාවිතා & 0x0f.

65 යනු කේතයයි 'A'

48 යනු කේතයයි '0'

7 යනු ASCII වගුව ( ) අතර '9'සහ අතර ඇති අකුරු ගණනයි .'A'...456789:;<=>?@ABCD...


16

බැලීමේ වගුවක් භාවිතා කරමින් මෙම ගැටළුව විසඳා ගත හැකිය. මේ සඳහා එන්කෝඩරය සහ විකේතකය යන දෙකම සඳහා ස්ථිතික මතකය කුඩා ප්‍රමාණයක් අවශ්‍ය වේ. කෙසේ වෙතත් මෙම ක්‍රමය වේගවත් වනු ඇත:

  • එන්කෝඩර් වගුව බයිට් 512 ක් හෝ බයිට් 1024 ක් (ඉහළ සහ පහළ අකුරු දෙකම අවශ්‍ය නම් දෙගුණයක් විශාලත්වය)
  • විකේතක වගුව බයිට් 256 ක් හෝ කිබී 64 ක් (තනි වර්‍ග බැලීමක් හෝ ද්විත්ව වර්‍ග බැලීමක්)

මගේ විසඳුම කේතන වගුව සඳහා බයිට් 1024 ක් ද විකේතනය සඳහා බයිට් 256 ක් ද භාවිතා කරයි.

විකේතනය

private static readonly byte[] LookupTable = new byte[] {
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};

private static byte Lookup(char c)
{
  var b = LookupTable[c];
  if (b == 255)
    throw new IOException("Expected a hex character, got " + c);
  return b;
}

public static byte ToByte(char[] chars, int offset)
{
  return (byte)(Lookup(chars[offset]) << 4 | Lookup(chars[offset + 1]));
}

කේතීකරණය

private static readonly char[][] LookupTableUpper;
private static readonly char[][] LookupTableLower;

static Hex()
{
  LookupTableLower = new char[256][];
  LookupTableUpper = new char[256][];
  for (var i = 0; i < 256; i++)
  {
    LookupTableLower[i] = i.ToString("x2").ToCharArray();
    LookupTableUpper[i] = i.ToString("X2").ToCharArray();
  }
}

public static char[] ToCharLower(byte[] b, int bOffset)
{
  return LookupTableLower[b[bOffset]];
}

public static char[] ToCharUpper(byte[] b, int bOffset)
{
  return LookupTableUpper[b[bOffset]];
}

සංසන්දනය

StringBuilderToStringFromBytes:   106148
BitConverterToStringFromBytes:     15783
ArrayConvertAllToStringFromBytes:  54290
ByteManipulationToCharArray:        8444
TableBasedToCharArray:              5651 *

* මෙම විසඳුම

සටහන

විකේතනය කිරීමේදී IOException සහ IndexOutOfRangeException සිදුවිය හැකිය (අක්ෂරයකට වැඩි අගයක් ඇත්නම්> 256). ඩී / කේතන ධාරාවන් හෝ අරා සඳහා ක්‍රම ක්‍රියාත්මක කළ යුතුය, මෙය සංකල්පයේ සාක්ෂියක් පමණි.


2
ඔබ සීඑල්ආර් මත කේතය ධාවනය කරන විට බයිට් 256 ක මතක භාවිතය නොසැලකිය.
ඩොල්මන්

9

මෙය විශිෂ්ට තනතුරකි. මම වලීඩ්ගේ විසඳුමට කැමතියි. මම එය පැට්රිජ් පරීක්ෂණයෙන් ධාවනය කර නැති නමුත් එය තරමක් වේගවත් බව පෙනේ. මට ද ආපසු හැරවීමේ ක්‍රියාවලිය අවශ්‍ය විය, හෙක්ස් නූලක් බයිට් අරා බවට පරිවර්තනය කිරීම, එබැවින් මම එය ලිව්වේ වලීඩ්ගේ විසඳුමේ ආපසු හැරවීමක් ලෙස ය. එය ටොමලක්ගේ මුල් විසඳුමට වඩා වේගවත් දැයි විශ්වාස නැත. නැවතත්, මම පැට්‍රිජ්ගේ පරීක්ෂණයෙන් ප්‍රතිලෝම ක්‍රියාවලිය ක්‍රියාත්මක නොකළෙමි.

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;
}

මෙම කේතය උපකල්පනය කරන්නේ හෙක්ස් නූල ඉහළ අක්ෂර ඇල්ෆා අක්ෂර භාවිතා කරන අතර හෙක්ස් නූල කුඩා අකුරු ඇල්ෆා භාවිතා කරන්නේ නම් පුපුරා යයි. ආරක්ෂිතව සිටීමට ආදාන නූලෙහි "ලොකු අකුරක්" පරිවර්තනය කිරීමට අවශ්‍ය විය හැකිය.
මාක් නොවාකොව්ස්කි

එය විශ්මයජනක නිරීක්ෂණ මාක්. කේතය ලියා ඇත්තේ වලීඩ්ගේ විසඳුම ආපසු හැරවීමට ය. ToUpper ඇමතුම ඇල්ගොරිතම සමහරක් මන්දගාමී කරයි, නමුත් එය කුඩා අක්ෂර ඇල්ෆා අක්ෂර හැසිරවීමට ඉඩ දෙයි.
ක්‍රිස් එෆ්

3
Convert.ToByte (topChar + bottomChar) (බයිට්) (topChar + bottomChar) ලෙස ලිවිය හැකිය
අමීර් රෙසෙයි

විශාල කාර්ය සාධන ද penalty hexString[i] &= ~0x20;
ුවමක්

9

එය සංකීර්ණ කරන්නේ ඇයි? විෂුවල් ස්ටුඩියෝ 2008 හි මෙය සරල ය:

සී #:

string hex = BitConverter.ToString(YourByteArray).Replace("-", "");

VB:

Dim hex As String = BitConverter.ToString(YourByteArray).Replace("-", "")

2
හේතුව කාර්ය සාධනය, ඔබට ඉහළ කාර්ය සාධන විසඳුමක් අවශ්‍ය වූ විට. :)
රිකී

7

මෙහි ඇති බොහෝ පිළිතුරු වලට ගොඩගැසීමට නොවේ, නමුත් හෙක්ස් ස්ට්‍රිං පාර්සර් සෘජුවම ක්‍රියාත්මක කිරීම සඳහා තරමක් ප්‍රශස්ත (පිළිගැනීමට වඩා x 4.5x වඩා හොඳ) මට හමු විය. පළමුව, මගේ පරීක්ෂණ වලින් ප්‍රතිදානය (පළමු කණ්ඩායම මගේ ක්‍රියාත්මක කිරීම):

Give me that string:
04c63f7842740c77e545bb0b2ade90b384f119f6ab57b680b7aa575a2f40939f

Time to parse 100,000 times: 50.4192 ms
Result as base64: BMY/eEJ0DHflRbsLKt6Qs4TxGfarV7aAt6pXWi9Ak58=
BitConverter'd: 04-C6-3F-78-42-74-0C-77-E5-45-BB-0B-2A-DE-90-B3-84-F1-19-F6-AB-5
7-B6-80-B7-AA-57-5A-2F-40-93-9F

Accepted answer: (StringToByteArray)
Time to parse 100000 times: 233.1264ms
Result as base64: BMY/eEJ0DHflRbsLKt6Qs4TxGfarV7aAt6pXWi9Ak58=
BitConverter'd: 04-C6-3F-78-42-74-0C-77-E5-45-BB-0B-2A-DE-90-B3-84-F1-19-F6-AB-5
7-B6-80-B7-AA-57-5A-2F-40-93-9F

With Mono's implementation:
Time to parse 100000 times: 777.2544ms
Result as base64: BMY/eEJ0DHflRbsLKt6Qs4TxGfarV7aAt6pXWi9Ak58=
BitConverter'd: 04-C6-3F-78-42-74-0C-77-E5-45-BB-0B-2A-DE-90-B3-84-F1-19-F6-AB-5
7-B6-80-B7-AA-57-5A-2F-40-93-9F

With SoapHexBinary:
Time to parse 100000 times: 845.1456ms
Result as base64: BMY/eEJ0DHflRbsLKt6Qs4TxGfarV7aAt6pXWi9Ak58=
BitConverter'd: 04-C6-3F-78-42-74-0C-77-E5-45-BB-0B-2A-DE-90-B3-84-F1-19-F6-AB-5
7-B6-80-B7-AA-57-5A-2F-40-93-9F

නිරවද්‍යතාවය පරීක්ෂා කිරීම සඳහා base64 සහ 'BitConverter'd' රේඛා තිබේ. ඒවා සමාන බව සලකන්න.

ක්‍රියාත්මක කිරීම:

public static byte[] ToByteArrayFromHex(string hexString)
{
  if (hexString.Length % 2 != 0) throw new ArgumentException("String must have an even length");
  var array = new byte[hexString.Length / 2];
  for (int i = 0; i < hexString.Length; i += 2)
  {
    array[i/2] = ByteFromTwoChars(hexString[i], hexString[i + 1]);
  }
  return array;
}

private static byte ByteFromTwoChars(char p, char p_2)
{
  byte ret;
  if (p <= '9' && p >= '0')
  {
    ret = (byte) ((p - '0') << 4);
  }
  else if (p <= 'f' && p >= 'a')
  {
    ret = (byte) ((p - 'a' + 10) << 4);
  }
  else if (p <= 'F' && p >= 'A')
  {
    ret = (byte) ((p - 'A' + 10) << 4);
  } else throw new ArgumentException("Char is not a hex digit: " + p,"p");

  if (p_2 <= '9' && p_2 >= '0')
  {
    ret |= (byte) ((p_2 - '0'));
  }
  else if (p_2 <= 'f' && p_2 >= 'a')
  {
    ret |= (byte) ((p_2 - 'a' + 10));
  }
  else if (p_2 <= 'F' && p_2 >= 'A')
  {
    ret |= (byte) ((p_2 - 'A' + 10));
  } else throw new ArgumentException("Char is not a hex digit: " + p_2, "p_2");

  return ret;
}

unsafe(පැහැදිලිවම අතිරික්ත) අක්ෂර-සිට-නිබ්බල් ifඅනුක්‍රමය වෙනත් ක්‍රමයකට ගෙනයාමට මම උත්සාහ කළෙමි , නමුත් එය ලබාගත් වේගවත්ම අවස්ථාව මෙයයි.

(මෙය ප්‍රශ්නයට අඩක් පිළිතුරු සපයන බව මම පිළිගනිමි. වචන-> බයිට් [] පරිවර්තනය අඩුවෙන් නිරූපණය කර ඇති අතර බයිට් [] -> නූල් කෝණය හොඳින් ආවරණය වී ඇති බව පෙනේ. මේ අනුව, මෙම පිළිතුර.)


1
නුත්ගේ අනුගාමිකයන් සඳහා: මම මෙය කළේ සෑම මිනිත්තු කිහිපයකට වරක් හෙක්ස් නූල් දහස් ගණනක් විග්‍රහ කිරීමට අවශ්‍ය නිසාය, එබැවින් එය හැකි තරම් වේගවත් වීම වැදගත්ය (අභ්‍යන්තර පුඩුවේ මෙන්). එවැනි බොහෝ විග්‍රහයන් සිදු නොවන්නේ නම් ටොමලක්ගේ විසඳුම මන්දගාමී නොවේ.
බෙන් මෝෂර්

5

ආරක්ෂිත අනුවාද:

public static class HexHelper
{
    [System.Diagnostics.Contracts.Pure]
    public static string ToHex(this byte[] value)
    {
        if (value == null)
            throw new ArgumentNullException("value");

        const string hexAlphabet = @"0123456789ABCDEF";

        var chars = new char[checked(value.Length * 2)];
        unchecked
        {
            for (int i = 0; i < value.Length; i++)
            {
                chars[i * 2] = hexAlphabet[value[i] >> 4];
                chars[i * 2 + 1] = hexAlphabet[value[i] & 0xF];
            }
        }
        return new string(chars);
    }

    [System.Diagnostics.Contracts.Pure]
    public static byte[] FromHex(this string value)
    {
        if (value == null)
            throw new ArgumentNullException("value");
        if (value.Length % 2 != 0)
            throw new ArgumentException("Hexadecimal value length must be even.", "value");

        unchecked
        {
            byte[] result = new byte[value.Length / 2];
            for (int i = 0; i < result.Length; i++)
            {
                // 0(48) - 9(57) -> 0 - 9
                // A(65) - F(70) -> 10 - 15
                int b = value[i * 2]; // High 4 bits.
                int val = ((b - '0') + ((('9' - b) >> 31) & -7)) << 4;
                b = value[i * 2 + 1]; // Low 4 bits.
                val += (b - '0') + ((('9' - b) >> 31) & -7);
                result[i] = checked((byte)val);
            }
            return result;
        }
    }
}

අනාරක්ෂිත අනුවාදයන් කාර්ය සාධනයට වැඩි කැමැත්තක් දක්වන සහ අනාරක්ෂිතභාවයට බිය නොවන අය සඳහා. ToHex 35% ක් පමණ වේගවත් වන අතර 10% වේගවත් FromHex.

public static class HexUnsafeHelper
{
    [System.Diagnostics.Contracts.Pure]
    public static unsafe string ToHex(this byte[] value)
    {
        if (value == null)
            throw new ArgumentNullException("value");

        const string alphabet = @"0123456789ABCDEF";

        string result = new string(' ', checked(value.Length * 2));
        fixed (char* alphabetPtr = alphabet)
        fixed (char* resultPtr = result)
        {
            char* ptr = resultPtr;
            unchecked
            {
                for (int i = 0; i < value.Length; i++)
                {
                    *ptr++ = *(alphabetPtr + (value[i] >> 4));
                    *ptr++ = *(alphabetPtr + (value[i] & 0xF));
                }
            }
        }
        return result;
    }

    [System.Diagnostics.Contracts.Pure]
    public static unsafe byte[] FromHex(this string value)
    {
        if (value == null)
            throw new ArgumentNullException("value");
        if (value.Length % 2 != 0)
            throw new ArgumentException("Hexadecimal value length must be even.", "value");

        unchecked
        {
            byte[] result = new byte[value.Length / 2];
            fixed (char* valuePtr = value)
            {
                char* valPtr = valuePtr;
                for (int i = 0; i < result.Length; i++)
                {
                    // 0(48) - 9(57) -> 0 - 9
                    // A(65) - F(70) -> 10 - 15
                    int b = *valPtr++; // High 4 bits.
                    int val = ((b - '0') + ((('9' - b) >> 31) & -7)) << 4;
                    b = *valPtr++; // Low 4 bits.
                    val += (b - '0') + ((('9' - b) >> 31) & -7);
                    result[i] = checked((byte)val);
                }
            }
            return result;
        }
    }
}

BTW අක්ෂර පරිවර්තනය ආරම්භ කරන සෑම අවස්ථාවකම වැරදි අක්ෂර වින්‍යාසය ආරම්භ කිරීම සඳහා, අක්ෂර වින්‍යාසය (නූල් සඳහා) හෝ ස්ථිතික කියවීමට පමණක් (වර්‍ගය සඳහා) විය යුතුය. අක්ෂර මත පදනම් වූ බයිට් [] නූල් බවට පරිවර්තනය කිරීම බයිට් හැසිරවීමේ අනුවාදයන් තරම් වේගවත් වේ.

ඇත්ත වශයෙන්ම පරීක්ෂණය මුදා හැරීමේදී (ප්‍රශස්තිකරණය සමඟ) සම්පාදනය කළ යුතු අතර නිදොස් කිරීමේ විකල්පය සමඟ “මර්දනය JIT ප්‍රශස්තිකරණය” අක්‍රිය කර ඇත (කේතය නිදොස්කරණය කළ හැකි නම් “මගේ කේතය සක්‍රීය කරන්න” යන්නට සමාන වේ).


5

වලීඩ් ඊසා කේතය සඳහා ප්‍රතිලෝම ශ්‍රිතය (හයිට්ස් ස්ට්‍රිං ටු බයිට් අරා):

    public static byte[] HexToBytes(this string hexString)        
    {
        byte[] b = new byte[hexString.Length / 2];            
        char c;
        for (int i = 0; i < hexString.Length / 2; i++)
        {
            c = hexString[i * 2];
            b[i] = (byte)((c < 0x40 ? c - 0x30 : (c < 0x47 ? c - 0x37 : c - 0x57)) << 4);
            c = hexString[i * 2 + 1];
            b[i] += (byte)(c < 0x40 ? c - 0x30 : (c < 0x47 ? c - 0x37 : c - 0x57));
        }

        return b;
    }

කුඩා අකුරු ආධාරයෙන් වලීඩ් ඊසා ක්‍රියාකාරිත්වය:

    public static string BytesToHex(this byte[] barray, bool toLowerCase = true)
    {
        byte addByte = 0x37;
        if (toLowerCase) addByte = 0x57;
        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 + addByte : b + 0x30);
            b = ((byte)(barray[i] & 0xF));
            c[i * 2 + 1] = (char)(b > 9 ? b + addByte : b + 0x30);
        }

        return new string(c);
    }

4

දිගු කිරීමේ ක්‍රම (වියාචනය: සම්පූර්ණයෙන්ම පරීක්ෂා නොකළ කේතය, 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();
    }
}

ආදිය. ටොමලක්ගේ විසඳුම් තුනෙන් එකක් භාවිතා කරන්න (අවසාන ක්‍රමය නූල් මත දිගු කිරීමේ ක්‍රමයක් වීම).


ඔබ බොහෝ විට කේතය මෙවැනි ප්‍රශ්නයක් සඳහා ඉදිරිපත් කිරීමට පෙර එය පරීක්ෂා කළ යුතුය.
jww

4

මයික්‍රොසොෆ්ට් හි සංවර්ධකයින්ගෙන්, ලස්සන, සරල පරිවර්තනයක්:

public static string ByteArrayToString(byte[] ba) 
{
    // Concatenate the bytes into one long string
    return ba.Aggregate(new StringBuilder(32),
                            (sb, b) => sb.Append(b.ToString("X2"))
                            ).ToString();
}

ඉහත කරුණු පිරිසිදුව හා සංයුක්තව පැවතුනද, කාර්ය සාධන ජුන්කි ගණන් කරන්නන් භාවිතා කරමින් ඒ ගැන කෑගසනු ඇත. ටොමලක්ගේ මුල් පිළිතුරේ වැඩි දියුණු කළ අනුවාදයක් සමඟ ඔබට උපරිම කාර්ය සාධනය ලබා ගත හැකිය :

public static string ByteArrayToString(byte[] ba)   
{   
   StringBuilder hex = new StringBuilder(ba.Length * 2);   

   for(int i=0; i < ba.Length; i++)       // <-- Use for loop is faster than foreach   
       hex.Append(ba[i].ToString("X2"));   // <-- ToString is faster than AppendFormat   

   return hex.ToString();   
} 

මෙතෙක් මා මෙහි පළ කර ඇති සියලුම ක්‍රියාකාරකම් වලින් වේගවත්ම වේ. ඒ සඳහා මගේ වචනය පමණක් ගන්න එපා ... කාර්ය සාධනය සෑම පුරුද්දක්ම පරීක්ෂා කර එහි CIL කේතය ඔබම පරීක්ෂා කරන්න.


3
මෙම කේතයේ ප්‍රධාන ගැටළුව iterator නොවේ. ඔබ මිණුම් ලකුණක් විය යුතුයි b.ToSting("X2").
ඩොල්මන්

2

SQL නූලකට ඇතුළු කිරීම සඳහා (ඔබ විධාන පරාමිතීන් භාවිතා නොකරන්නේ නම්):

public static String ByteArrayToSQLHexString(byte[] Source)
{
    return = "0x" + BitConverter.ToString(Source).Replace("-", "");
}

නම් Source == nullහෝ Source.Length == 0අපිට ප්රශ්නයක් සර්!
ඇන්ඩ්‍රි ක්‍රසුට්ස්කි

2

වේගය අනුව, මෙය මෙහි ඇති ඕනෑම දෙයකට වඩා හොඳ බව පෙනේ:

  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);
  }

2

ඔබ වැඩ කිරීමට යෝජනා කළ කේතය මට ලැබුණේ නැත, ඔලිප්‍රෝ. hex[i] + hex[i+1]පෙනෙන විදිහට ආපසු int.

කෙසේ වෙතත්, වලීඩ්ස් කේතයෙන් ඉඟි කිහිපයක් ගෙන මෙය එකට පහර දීමෙන් මම යම් සාර්ථකත්වයක් ලබා ගතිමි. එය අපායක් මෙන් කැත නමුත් එය මගේ පරීක්ෂණ අනුව අනෙක් අයට සාපේක්ෂව 1/3 වේලාවට වැඩ කරන බව පෙනේ (පැට්‍රිජ් පරීක්ෂණ යාන්ත්‍රණය භාවිතා කරමින්). ආදාන ප්‍රමාණය අනුව. අකුරු වලට වඩා වැඩි සංඛ්‍යාවක් ඇති බැවින් පළමුව 0-9 වෙන් කිරීම සඳහා:: s වටා මාරුවීම තරමක් වේගවත් ප්‍රති result ලයක් ලබා දෙනු ඇත.

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;
}

2

ByteArrayToHexViaByteManipulation හි මෙම අනුවාදය වේගවත් විය හැකිය.

මගේ වාර්තා වලින්:

  • ByteArrayToHexViaByteManipulation3: සාමාන්‍ය කිනිතුල්ලන් 1,68 ක් (ලකුණු 1000 ට වැඩි), 17,5X
  • ByteArrayToHexViaByteManipulation2: සාමාන්‍ය කිනිතුල්ලන් 1,73 ක් (ලකුණු 1000 ට වැඩි), 16,9X
  • ByteArrayToHexViaByteManipulation: සාමාන්‍ය කිනිතුල්ලන් 2,90 ක් (ලකුණු 1000 ට වැඩි), 10,1X
  • ByteArrayToHexViaLookupAndShift: සාමාන්‍ය කිනිතුල්ලන් 3,22 ක් (ලකුණු 1000 ට වැඩි), 9,1X
  • ...

    static private readonly char[] hexAlphabet = new char[]
        {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    static string ByteArrayToHexViaByteManipulation3(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] = hexAlphabet[b];
            b = ((byte)(bytes[i] & 0xF));
            c[i * 2 + 1] = hexAlphabet[b];
        }
        return new string(c);
    }

මම හිතන්නේ මෙය ප්‍රශස්තකරණයකි:

    static private readonly char[] hexAlphabet = new char[]
        {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    static string ByteArrayToHexViaByteManipulation4(byte[] bytes)
    {
        char[] c = new char[bytes.Length * 2];
        for (int i = 0, ptr = 0; i < bytes.Length; i++, ptr += 2)
        {
            byte b = bytes[i];
            c[ptr] = hexAlphabet[b >> 4];
            c[ptr + 1] = hexAlphabet[b & 0xF];
        }
        return new string(c);
    }

2

ෂඩාස්රාකාර විකේතනය කිරීම සඳහා බිට්-ෆිඩ්ලිං භාවිතා කරන පිළිතුරක් මා සතුව ඇති බැවින් මම මෙම බිට් ෆිඩ්ලිං තරඟයට ඇතුළු වෙමි . ඇමතුම් StringBuilderක්‍රම සඳහාද කාලයක් ගත වන බැවින් අක්ෂර අරා භාවිතා කිරීම ඊටත් වඩා වේගවත් විය හැකි බව සලකන්න .

public static String ToHex (byte[] data)
{
    int dataLength = data.Length;
    // pre-create the stringbuilder using the length of the data * 2, precisely enough
    StringBuilder sb = new StringBuilder (dataLength * 2);
    for (int i = 0; i < dataLength; i++) {
        int b = data [i];

        // check using calculation over bits to see if first tuple is a letter
        // isLetter is zero if it is a digit, 1 if it is a letter
        int isLetter = (b >> 7) & ((b >> 6) | (b >> 5)) & 1;

        // calculate the code using a multiplication to make up the difference between
        // a digit character and an alphanumerical character
        int code = '0' + ((b >> 4) & 0xF) + isLetter * ('A' - '9' - 1);
        // now append the result, after casting the code point to a character
        sb.Append ((Char)code);

        // do the same with the lower (less significant) tuple
        isLetter = (b >> 3) & ((b >> 2) | (b >> 1)) & 1;
        code = '0' + (b & 0xF) + isLetter * ('A' - '9' - 1);
        sb.Append ((Char)code);
    }
    return sb.ToString ();
}

public static byte[] FromHex (String hex)
{

    // pre-create the array
    int resultLength = hex.Length / 2;
    byte[] result = new byte[resultLength];
    // set validity = 0 (0 = valid, anything else is not valid)
    int validity = 0;
    int c, isLetter, value, validDigitStruct, validDigit, validLetterStruct, validLetter;
    for (int i = 0, hexOffset = 0; i < resultLength; i++, hexOffset += 2) {
        c = hex [hexOffset];

        // check using calculation over bits to see if first char is a letter
        // isLetter is zero if it is a digit, 1 if it is a letter (upper & lowercase)
        isLetter = (c >> 6) & 1;

        // calculate the tuple value using a multiplication to make up the difference between
        // a digit character and an alphanumerical character
        // minus 1 for the fact that the letters are not zero based
        value = ((c & 0xF) + isLetter * (-1 + 10)) << 4;

        // check validity of all the other bits
        validity |= c >> 7; // changed to >>, maybe not OK, use UInt?

        validDigitStruct = (c & 0x30) ^ 0x30;
        validDigit = ((c & 0x8) >> 3) * (c & 0x6);
        validity |= (isLetter ^ 1) * (validDigitStruct | validDigit);

        validLetterStruct = c & 0x18;
        validLetter = (((c - 1) & 0x4) >> 2) * ((c - 1) & 0x2);
        validity |= isLetter * (validLetterStruct | validLetter);

        // do the same with the lower (less significant) tuple
        c = hex [hexOffset + 1];
        isLetter = (c >> 6) & 1;
        value ^= (c & 0xF) + isLetter * (-1 + 10);
        result [i] = (byte)value;

        // check validity of all the other bits
        validity |= c >> 7; // changed to >>, maybe not OK, use UInt?

        validDigitStruct = (c & 0x30) ^ 0x30;
        validDigit = ((c & 0x8) >> 3) * (c & 0x6);
        validity |= (isLetter ^ 1) * (validDigitStruct | validDigit);

        validLetterStruct = c & 0x18;
        validLetter = (((c - 1) & 0x4) >> 2) * ((c - 1) & 0x2);
        validity |= isLetter * (validLetterStruct | validLetter);
    }

    if (validity != 0) {
        throw new ArgumentException ("Hexadecimal encoding incorrect for input " + hex);
    }

    return result;
}

ජාවා කේතයෙන් පරිවර්තනය කර ඇත.


හ්ම්, මම ඇත්ත වශයෙන්ම මෙය ප්‍රශස්තිකරණය කළ යුතු අතර Char[]Char
ඉන්ට්ස්

C # සඳහා, ලූපයෙන් පිටත වෙනුවට විචල්‍යයන් භාවිතා කරන ස්ථාන ආරම්භ කිරීම සම්පාදකයාට ප්‍රශස්තිකරණය කිරීමට ඉඩ දීම සඳහා වඩාත් සුදුසු වේ. මට එක හා සමාන කාර්ය සාධනයක් ලැබෙනවා.
පීටර්

2

කාර්ය සාධනය සඳහා මම ඩ්‍රැෆ්‍රොසෙන්ස් විසඳුමක් සමඟ යන්නෙමි. විකේතකය සඳහා ඉතා කුඩා ප්‍රශස්තිකරණයක් වනුයේ "<< 4" ඉවත් කිරීම සඳහා වර්‍ග සඳහා වගුවක් භාවිතා කිරීමයි.

පැහැදිලිවම ක්‍රම දෙකේ ඇමතුම් මිල අධිකය. ආදාන හෝ ප්‍රතිදාන දත්ත මත යම් ආකාරයක චෙක්පතක් සිදු කරන්නේ නම් (සීආර්සී, චෙක්සම් හෝ වෙනත් දෙයක් if (b == 255)...විය හැකිය) මඟ හැරිය හැකි අතර එමඟින් ක්‍රමවේදය මුළුමනින්ම කැඳවනු ලැබේ.

භාවිතා offset++හා offsetවෙනුවට offsetසහ offset + 1සමහර න්යායික ප්රතිලාභ දෙන්න වෙනවා නමුත් මම මට වඩා මෙම වඩා හොඳ සම්පාදකවරයා මගින් හසුරුවනු පොලිසිය සැක කරයි.

private static readonly byte[] LookupTableLow = new byte[] {
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};

private static readonly byte[] LookupTableHigh = new byte[] {
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};

private static byte LookupLow(char c)
{
  var b = LookupTableLow[c];
  if (b == 255)
    throw new IOException("Expected a hex character, got " + c);
  return b;
}

private static byte LookupHigh(char c)
{
  var b = LookupTableHigh[c];
  if (b == 255)
    throw new IOException("Expected a hex character, got " + c);
  return b;
}

public static byte ToByte(char[] chars, int offset)
{
  return (byte)(LookupHigh(chars[offset++]) | LookupLow(chars[offset]));
}

මෙය මගේ හිසට ඉහළින් ඇති අතර එය පරීක්ෂා කර හෝ මිණුම් සලකුණු කර නොමැත.


1

විවිධත්වය සඳහා තවත් වෙනසක්:

public static byte[] FromHexString(string src)
{
    if (String.IsNullOrEmpty(src))
        return null;

    int index = src.Length;
    int sz = index / 2;
    if (sz <= 0)
        return null;

    byte[] rc = new byte[sz];

    while (--sz >= 0)
    {
        char lo = src[--index];
        char hi = src[--index];

        rc[sz] = (byte)(
            (
                (hi >= '0' && hi <= '9') ? hi - '0' :
                (hi >= 'a' && hi <= 'f') ? hi - 'a' + 10 :
                (hi >= 'A' && hi <= 'F') ? hi - 'A' + 10 :
                0
            )
            << 4 | 
            (
                (lo >= '0' && lo <= '9') ? lo - '0' :
                (lo >= 'a' && lo <= 'f') ? lo - 'a' + 10 :
                (lo >= 'A' && lo <= 'F') ? lo - 'A' + 10 :
                0
            )
        );
    }

    return rc;          
}

1

වේගය සඳහා ප්‍රශස්තිකරණය කර නැත, නමුත් බොහෝ පිළිතුරු වලට වඩා LINQy (.NET 4.0):

<Extension()>
Public Function FromHexToByteArray(hex As String) As Byte()
    hex = If(hex, String.Empty)
    If hex.Length Mod 2 = 1 Then hex = "0" & hex
    Return Enumerable.Range(0, hex.Length \ 2).Select(Function(i) Convert.ToByte(hex.Substring(i * 2, 2), 16)).ToArray
End Function

<Extension()>
Public Function ToHexString(bytes As IEnumerable(Of Byte)) As String
    Return String.Concat(bytes.Select(Function(b) b.ToString("X2")))
End Function

1

නිබ්ල් මෙහෙයුම් දෙක එකකට නැමෙන මාෂප් දෙකක්.

බොහෝ විට කාර්යක්ෂම අනුවාදය:

public static string ByteArrayToString2(byte[] ba)
{
    char[] c = new char[ba.Length * 2];
    for( int i = 0; i < ba.Length * 2; ++i)
    {
        byte b = (byte)((ba[i>>1] >> 4*((i&1)^1)) & 0xF);
        c[i] = (char)(55 + b + (((b-10)>>31)&-7));
    }
    return new string( c );
}

බිට්-හැක් කිරීමේ අනුවාදය සහිත පිරිහුණු ලින්ක්:

public static string ByteArrayToString(byte[] ba)
{
    return string.Concat( ba.SelectMany( b => new int[] { b >> 4, b & 0xF }).Select( b => (char)(55 + b + (((b-10)>>31)&-7))) );
}

සහ ආපසු හැරවීම:

public static byte[] HexStringToByteArray( string s )
{
    byte[] ab = new byte[s.Length>>1];
    for( int i = 0; i < s.Length; i++ )
    {
        int b = s[i];
        b = (b - '0') + ((('9' - b)>>31)&-7);
        ab[i>>1] |= (byte)(b << 4*((i&1)^1));
    }
    return ab;
}

1
HexStringToByteArray ("09") 0x02 ආපසු ලබා දෙන අතර එය නරකයි
CoperNick

1

තවත් ක්‍රමයක් නම් stackallocGC මතක පීඩනය අඩු කිරීම සඳහා භාවිතා කිරීමයි:

static string ByteToHexBitFiddle(byte[] bytes)
{
        var c = stackalloc char[bytes.Length * 2 + 1];
        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));
        }
        c[bytes.Length * 2 ] = '\0';
        return new string(c);
}

1

මෙන්න මගේ වෙඩි පහර. නූල් සහ බයිට් දිගු කිරීම සඳහා මම දිගු පන්ති යුගලයක් නිර්මාණය කර ඇත්තෙමි. විශාල ගොනු පරීක්ෂණයකදී, කාර්ය සාධනය බයිට් හැසිරවීම 2 සමඟ සැසඳිය හැකිය.

ToHexString සඳහා පහත කේතය යනු බැලීමේ සහ මාරුවීමේ ඇල්ගොරිතම ප්‍රශස්ත ලෙස ක්‍රියාත්මක කිරීමයි. එය බෙහ්රූස්ගේ කතාවට බොහෝ දුරට සමාන ය, නමුත් එය නැවත භාවිතා foreachකිරීමට භාවිතා කරන අතර කවුන්ටරය පැහැදිලිවම සුචිගත කිරීමට වඩා වේගවත් වේ for.

එය මගේ යන්ත්‍රයේ බයිට් හැසිරවීම 2 ට පිටුපසින් 2 වන ස්ථානයට පැමිණ ඇති අතර එය ඉතා පහසුවෙන් කියවිය හැකි කේතයකි. පහත දැක්වෙන පරීක්ෂණ ප්‍රති results ල ද උනන්දුවක් දක්වයි:

ToHexStringCharArrayWithCharArrayLookup: සාමාන්‍ය කිනිතුල්ලන් 41,589.69 ක් (ලකුණු 1000 ට වැඩි), 1.5X ToHexStringCharArrayWithStringLookup: 50,764.06 සාමාන්‍ය කිනිතුල්ලන් (ලකුණු 1000 ට වැඩි), 1.2X ToHexStringStringCoringerUper2

ඉහත ප්‍රති results ල මත පදනම්ව එය නිගමනය කිරීම ආරක්ෂිත බව පෙනේ:

  1. විශාල ගොනු පරීක්ෂණයකදී වර්‍ග අරාවකට එදිරිව බැලීම සඳහා දණ්ඩකට දර්ශක කිරීම සඳහා වන ද ties ුවම් වැදගත් වේ.
  2. දන්නා ධාරිතාවයකින් යුත් ස්ට්‍රිංබිල්ඩරයක් එදිරිව එදිරිව භාවිතා කිරීම සඳහා වන ද ties ුවම් ඊටත් වඩා වැදගත් වේ.

මෙන්න කේතය:

using System;

namespace ConversionExtensions
{
    public static class ByteArrayExtensions
    {
        private readonly static char[] digits = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

        public static string ToHexString(this byte[] bytes)
        {
            char[] hex = new char[bytes.Length * 2];
            int index = 0;

            foreach (byte b in bytes)
            {
                hex[index++] = digits[b >> 4];
                hex[index++] = digits[b & 0x0F];
            }

            return new string(hex);
        }
    }
}


using System;
using System.IO;

namespace ConversionExtensions
{
    public static class StringExtensions
    {
        public static byte[] ToBytes(this string hexString)
        {
            if (!string.IsNullOrEmpty(hexString) && hexString.Length % 2 != 0)
            {
                throw new FormatException("Hexadecimal string must not be empty and must contain an even number of digits to be valid.");
            }

            hexString = hexString.ToUpperInvariant();
            byte[] data = new byte[hexString.Length / 2];

            for (int index = 0; index < hexString.Length; index += 2)
            {
                int highDigitValue = hexString[index] <= '9' ? hexString[index] - '0' : hexString[index] - 'A' + 10;
                int lowDigitValue = hexString[index + 1] <= '9' ? hexString[index + 1] - '0' : hexString[index + 1] - 'A' + 10;

                if (highDigitValue < 0 || lowDigitValue < 0 || highDigitValue > 15 || lowDigitValue > 15)
                {
                    throw new FormatException("An invalid digit was encountered. Valid hexadecimal digits are 0-9 and A-F.");
                }
                else
                {
                    byte value = (byte)((highDigitValue << 4) | (lowDigitValue & 0x0F));
                    data[index / 2] = value;
                }
            }

            return data;
        }
    }
}

මගේ කේතය @ පැට්‍රිජ්ගේ පරීක්ෂණ ව්‍යාපෘතියට මගේ යන්ත්‍රය මත තැබූ විට මට ලැබුණු පරීක්ෂණ ප්‍රති results ල පහත දැක්වේ. මම ෂඩාස්රාකාරයෙන් බයිට් අරා බවට පරිවර්තනය කිරීම සඳහා පරීක්ෂණයක් ද එක් කළෙමි. මගේ කේතය ක්‍රියාත්මක කළ පරීක්ෂණ ලකුණු වන්නේ බයිට්ආරේටෝහෙක්ස්වියා ඔප්ටිමයිස්ලූකප් ඇන්ඩ්ෂිෆ්ට් සහ හෙක්ස්ටෝබයිට්ආරේ වීවාබයිට් මැනුපියුලේෂන් ය. HexToByteArrayViaConvertToByte XXXX වෙතින් ලබාගෙන ඇත. HexToByteArrayViaSoapHexBinary යනු @ මයික්‍රොෆ්ට්ගේ පිළිතුරෙන්.

Intel Pentium III Xeon ප්‍රොසෙසරය

    Cores: 4 <br/>
    Current Clock Speed: 1576 <br/>
    Max Clock Speed: 3092 <br/>

බයිට් සමූහය ෂඩාස්රාකාර නූල් නිරූපණය බවට පරිවර්තනය කිරීම


ByteArrayToHexViaByteManipulation2: 39,366.64 සාමාන්‍ය කිනිතුල්ලන් (ලකුණු 1000 ට වැඩි), 22.4X

ByteArrayToHexViaOptimizedLookupAndShift: සාමාන්‍ය කිනිතුල්ලන් 41,588.64 (ලකුණු 1000 ට වැඩි), 21.2X

ByteArrayToHexViaLookup: සාමාන්‍ය කිනිතුල්ලන් 55,509.56 (ලකුණු 1000 ට වැඩි), 15.9X

ByteArrayToHexViaByteManipulation: සාමාන්‍ය කිනිතුල්ලන් 65,349.12 (ලකුණු 1000 ට වැඩි), 13.5X

ByteArrayToHexViaLookupAndShift: සාමාන්‍ය කිනිතුල්ලන් 86,926.87 (ලකුණු 1000 ට වැඩි), 10.2X

ByteArrayToHexStringViaBitConverter: සාමාන්‍ය කිනිතුල්ලන් 139,353.73 (ලකුණු 1000 ට වැඩි), 6.3X

ByteArrayToHexViaSoapHexBinary: 314,598.77 සාමාන්‍ය කිනිතුල්ලන් (ලකුණු 1000 ට වැඩි), 2.8X

ByteArrayToHexStringViaStringBuilderForEachByteToString: 344,264.63 සාමාන්‍ය කිනිතුල්ලන් (ලකුණු 1000 ට වැඩි), 2.6X

ByteArrayToHexStringViaStringBuilderAggregateByteToString: 382,623.44 සාමාන්‍ය කිනිතුල්ලන් (ලකුණු 1000 ට වැඩි), 2.3X

ByteArrayToHexStringViaStringBuilderForEachAppendFormat: 818,111.95 සාමාන්‍ය කිනිතුල්ලන් (ලකුණු 1000 ට වැඩි), 1.1X

ByteArrayToHexStringViaStringConcatArrayConvertAll: 839,244.84 සාමාන්‍ය කිනිතුල්ලන් (ලකුණු 1000 ට වැඩි), 1.1X

ByteArrayToHexStringViaStringBuilderAggregateAppendFormat: 867,303.98 සාමාන්‍ය කිනිතුල්ලන් (ලකුණු 1000 ට වැඩි), 1.0X

ByteArrayToHexStringViaStringJoinArrayConvertAll: 882,710.28 සාමාන්‍ය කිනිතුල්ලන් (ලකුණු 1000 ට වැඩි), 1.0X



1

තවත් වේගවත් කාර්යයක් ...

private static readonly byte[] HexNibble = new byte[] {
    0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
    0x8, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
    0x0, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0,
    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
    0x0, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF
};

public static byte[] HexStringToByteArray( string str )
{
    int byteCount = str.Length >> 1;
    byte[] result = new byte[byteCount + (str.Length & 1)];
    for( int i = 0; i < byteCount; i++ )
        result[i] = (byte) (HexNibble[str[i << 1] - 48] << 4 | HexNibble[str[(i << 1) + 1] - 48]);
    if( (str.Length & 1) != 0 )
        result[byteCount] = (byte) HexNibble[str[str.Length - 1] - 48];
    return result;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.