c# - আপনি কিভাবে একটি বাইট অ্যারে একটি হেক্সাডেসিমেল স্ট্রিং রূপান্তর, এবং বিপরীতভাবে?




arrays hex (20)

কর্মক্ষমতা বিশ্লেষণ

নোট: 2015-08-20 হিসাবে নতুন নেতা।

আমি কিছু ক্রুড Stopwatch পারফরম্যান্স পরীক্ষার মাধ্যমে একটি র্যান্ডম বাক্য (এন = 61, 1000 পুনরাবৃত্তি) এবং একটি প্রকল্প গুটেনবার্গ পাঠ্য (এন = 1,২38,957, 150 পুনরাবৃত্তি) সহ একটি রান দিয়ে বিভিন্ন রূপান্তর পদ্ধতিগুলি চালিত। এখানে ফলাফল, মোটামুটি দ্রুততম থেকে ধীরতম। সমস্ত পরিমাপ টিক্সে ( 10,000 টিিক্স = 1 এমএস ) এবং সমস্ত আপেক্ষিক নোটগুলি [ধীরতম] StringBuilder প্রয়োগের সাথে তুলনা করা হয়। ব্যবহৃত কোডের জন্য, নীচের বা পরীক্ষা কাঠামো রেপো দেখুন যেখানে আমি এখন এটি চালানোর জন্য কোডটি বজায় রাখি।

দাবি পরিত্যাগী

সতর্কতা: কিছু কংক্রিট জন্য এই পরিসংখ্যান উপর নির্ভর করবেন না; তারা কেবল নমুনা তথ্য নমুনা রান। আপনি যদি সত্যিই শীর্ষ-পারফরম্যান্সের প্রয়োজন বোধ করেন তবে দয়া করে কীভাবে ব্যবহার করবেন তার ডেটা প্রতিনিধির সাথে আপনার উত্পাদন চাহিদার পরিবেশ পরিবেশে এই পদ্ধতিগুলি পরীক্ষা করুন।

ফলাফল

  • Byte unsafe দ্বারা Lookup (CodesInChaos মাধ্যমে) ( airbreather দ্বারা পরীক্ষা রেপো যোগ করা)
    • পাঠ্য: 4,727.85 (105.2 এক্স)
    • বাক্য: 0.28 (99.7 এক্স)
  • Byte দ্বারা Lookup (CodeInChos মাধ্যমে)
    • পাঠ্য: 10,853.96 (45.8X দ্রুত)
    • বাক্য: 0.65 (42.7X দ্রুত)
  • বাইট ম্যানিপুলেশন 2 (CodesInChaos এর মাধ্যমে)
    • পাঠ্য: 12,967.69 (38.4X দ্রুত)
    • বাক্য: 0.73 (37.9 এক্স দ্রুত)
  • বাইট ম্যানিপুলেশন (ওয়ালেদ ঈসার মাধ্যমে)
    • পাঠ্য: 16,856.64 (২9.5 এক্স দ্রুত)
    • বাক্য: 0.70 (39.5 এক্স দ্রুত)
  • লুকান / Shift (নাথান মইনভাজিরির মাধ্যমে)
    • পাঠ্য: 23,201.23 (21.4X দ্রুত)
    • বাক্য: 1.24 (22.3 এক্স দ্রুত)
  • নিষ্ঠুর দ্বারা লুকান (ব্রায়ান ল্যাম্বার্ট মাধ্যমে)
    • পাঠ্য: 23,879.41 (20.8X দ্রুত)
    • বাক্য: 1.15 (23.9 এক্স দ্রুত)
  • BitConverter ( BitConverter মাধ্যমে)
    • পাঠ্য: 113,269.34 (4.4X দ্রুত)
    • বাক্য: 9.98 (2.8X দ্রুত)
  • {SoapHexBinary}.ToString (মিক্রফ্টের মাধ্যমে)
    • পাঠ্য: 178,601.39 (2.8X দ্রুত)
    • বাক্য: 10.68 (2.6X দ্রুত)
  • {byte}.ToString("X2") ( foreach ব্যবহার করে) (উইল ডিনের উত্তর থেকে প্রাপ্ত)
    • পাঠ্য: 308,805.38 (2.4X দ্রুত)
    • বাক্য: 16.89 (2.4X দ্রুত)
  • {byte}.ToString("X2") ( {IEnumerable}.Aggregate ব্যবহার করে {IEnumerable}.Aggregate , সিস্টেম.লিঙ্কের প্রয়োজন) (মার্কের মাধ্যমে)
    • পাঠ্য: 352,828.20 (2.1X দ্রুত)
    • বাক্য: 16.87 (2.4X দ্রুত)
  • Array.ConvertAll ( Array.ConvertAll ব্যবহার করে। string.Join ) (উইল ডিন মাধ্যমে)
    • পাঠ্য: 675,451.57 (1.1 এক্স দ্রুত)
    • বাক্য: 17.95 (2.2 এক্স দ্রুত)
  • Array.ConvertAll ( Array.ConvertAll ব্যবহার করে। string.Concat , .NET 4.0 প্রয়োজন) (উইল ডিনের মাধ্যমে)
    • পাঠ্য: 75২,078.70 (1.0 এক্স দ্রুত)
    • বাক্য: 18.28 (2.2 এক্স দ্রুত)
  • {StringBuilder}.AppendFormat ( {StringBuilder}.AppendFormat ব্যবহার করে) (টমালাকের মাধ্যমে)
    • পাঠ্য: 672,115.77 (1.1 এক্স দ্রুত)
    • বাক্য: 36.82 (1.1 এক্স দ্রুত)
  • {StringBuilder}.AppendFormat ( {IEnumerable}.Aggregate ব্যবহার করে {IEnumerable}.Aggregate , সিস্টেম.লিঙ্কের প্রয়োজন) (টোমালকের উত্তর থেকে প্রাপ্ত)
    • পাঠ্য: 718,380.63 (1.0X দ্রুত)
    • বাক্য: 39.71 (1.0 এক্স দ্রুত)

লুকান টেবিল বাইট ম্যানিপুলেশন উপর নেতৃত্ব নিয়েছে। মূলত, কোন প্রদত্ত nibble বা বাইট হেক্স হতে হবে precomputing কিছু ফর্ম আছে। তারপরে, আপনি যখন ডাটাটি দিয়ে চড়বেন তখন আপনি পরবর্তী অংশটিকে হেক্স স্ট্রিংটি দেখতে পাবেন তা দেখতে। যে মান তারপর কিছু ফ্যাশন ফলে স্ট্রিং আউটপুট যোগ করা হয়। দীর্ঘ সময় ধরে বাইট ম্যানিপুলেশন, কিছু ডেভেলপারদের দ্বারা পড়তে সম্ভবত কঠিন, শীর্ষ-পারফরমেন্স পদ্ধতি।

আপনার সেরা বাজি এখনও কিছু প্রতিনিধি তথ্য খুঁজে বের করতে এবং একটি উত্পাদন-মত পরিবেশে এটি চেষ্টা করা যাচ্ছে। আপনার যদি ভিন্ন মেমরি সীমাবদ্ধতা থাকে, তবে আপনি দ্রুত একটি পদ্ধতিতে কম বরাদ্দ সহ একটি পদ্ধতি পছন্দ করতে পারেন তবে আরো মেমরি ব্যবহার করতে পারেন।

টেস্টিং কোড

আমি ব্যবহৃত পরীক্ষার কোড সঙ্গে খেলতে মুক্ত মনে। একটি সংস্করণ এখানে অন্তর্ভুক্ত করা হয়েছে তবে রেপো ক্লোন করতে এবং আপনার নিজস্ব পদ্ধতি যোগ করতে বিনা দ্বিধায়। যদি আপনি কিছু আকর্ষণীয় খুঁজে পান অথবা এটি ব্যবহার করে এমন পরীক্ষার কাঠামো উন্নত করতে সহায়তা করতে চান তবে একটি পুল অনুরোধ জমা দিন।

  1. নতুন স্ট্যাটিক পদ্ধতি যুক্ত করুন ( Func<byte[], string> ) /Tests/ConvertByteArrayToHexString/Test.cs এ।
  2. যে পদ্ধতির নামটি একই ক্লাসে TestCandidates ফেরতের মান যুক্ত করুন।
  3. আপনি যে ইনপুট সংস্করণটি চান, বাক্য বা পাঠ্যটি সেই একই শ্রেণিতে জেনেটেটটেস্ট ইনপুটে মন্তব্যগুলি টগল করে নিশ্চিত করছেন তা নিশ্চিত করুন।
  4. F5 হিট করুন এবং আউটপুটের জন্য অপেক্ষা করুন (একটি HTML ডাম্প এছাড়াও / bin ফোল্ডারে উত্পন্ন হয়)।
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)

বিশ্লেষণ Waleed এর উত্তর যোগ করা হয়েছে। দ্রুত শেষ কর.

আপডেট (2011-10-05)

যোগ string.Concat Array.ConvertAll সম্পূর্ণতা জন্য Array.ConvertAll রূপান্তর (প্রয়োজন .NET 4.0)। string.Join সঙ্গে string.Joinstring.Join সংস্করণ।

আপডেট (2012-02-05)

টেস্ট StringBuilder.Append(b.ToString("X2")) আরো রূপান্তর রয়েছে যেমন StringBuilder.Append(b.ToString("X2")) । কেউ ফলাফল ফলাফল বিপর্যস্ত। foreach দ্রুত {IEnumerable}.Aggregate চেয়ে দ্রুত {IEnumerable}.Aggregate , উদাহরণস্বরূপ, কিন্তু BitConverter এখনও জিতেছে।

আপডেট (2012-04-03)

বিশ্লেষণ বিশ্লেষণ Mykroft এর SoapHexBinary উত্তর, যা তৃতীয় স্থান গ্রহণ।

আপডেট (2013-01-15)

সংযুক্ত কোড ইনকোসের বাইট ম্যানিপুলেশন উত্তর, যা প্রথম স্থানটি গ্রহণ করেছে (পাঠ্যের বড় ব্লকগুলিতে একটি বড় মার্জিন দ্বারা)।

আপডেট (2013-05-23)

নাথান মইনভাজিরের সন্ধান উত্তর এবং ব্রায়ান ল্যাম্বার্টের ব্লগের বৈচিত্র্য যোগ করেছেন। বরং উভয় দ্রুত, কিন্তু আমি পরীক্ষিত মেশিনে নেতৃত্ব গ্রহণ না (AMD ফেনোম 9750) ব্যবহার।

আপডেট (2014-07-31)

@ CodeInChaos এর নতুন বাইট-ভিত্তিক সন্ধান উত্তর যোগ করা হয়েছে। এটা বাক্য পরীক্ষা এবং পূর্ণ-টেক্সট পরীক্ষা উভয় সীসা গ্রহণ করা হয়েছে বলে মনে হচ্ছে।

আপডেট (2015-08-20)

এই উত্তর এর repo যোগ airbreather অপ্টিমাইজেশান এবং unsafe রূপান্তর। আপনি যদি অনিরাপদ গেমটিতে খেলতে চান, তবে আপনি ছোট স্ট্রিং এবং বড় পাঠ্য উভয় পূর্বের শীর্ষস্থানীয় বিজয়ীগুলির উপর কিছু বিশাল পারফরম্যান্স লাভ পেতে পারেন।

আপনি কিভাবে একটি বাইট অ্যারে একটি হেক্সাডেসিমেল স্ট্রিং রূপান্তর করতে পারেন, এবং বিপরীতভাবে?



আমি আজ খুব একই সমস্যা সম্মুখীন, এবং আমি এই কোড জুড়ে এসেছিলেন:

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 উপসর্গ মুছে ফেলার জন্য কোডটি একটু সংশোধন করেছি।

আমি কোডটিতে কিছু কর্মক্ষমতা পরীক্ষা করেছি এবং এটি বিটকোভার্টারটি ব্যবহার করার চেয়ে প্রায় আট গুণ দ্রুত। স্ট্রিং () (প্যাট্রিজের পোস্ট অনুসারে দ্রুততম)।


আরেকটি সন্ধান টেবিল ভিত্তিক পদ্ধতির। এটি প্রতিটি এক বাইটের জন্য কেবলমাত্র একটি অনুসন্ধান টেবিল ব্যবহার করে, প্রতি নিখুঁত একটি সন্ধানের টেবিলের পরিবর্তে।

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} ushort , ushort struct{char X1, X2} , struct{byte X1, X2} ushort , ushort struct{char 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;
}

এই সমস্যাটিকে একটি সন্ধানের টেবিল ব্যবহার করে সমাধান করা যেতে পারে। এনকোডার এবং ডিকোডার উভয়ের জন্য স্ট্যাটিক মেমরির একটি ছোট পরিমাণের প্রয়োজন হবে। তবে এই পদ্ধতি দ্রুত হবে:

  • এনকোডার টেবিল 512 বাইট বা 1024 বাইট (উচ্চ এবং নিম্ন উভয় ক্ষেত্রে প্রয়োজন হলে আকারের দ্বিগুণ)
  • ডিকোডার টেবিল 256 বাইট বা 64 KiB (হয় একটি একক গৃহস্থালি বর্ণন বা দ্বৈত গৃহস্থালি বর্ণন)

আমার সমাধান এনকোডিং টেবিলের জন্য 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)। ডি / এনকোডিং স্ট্রিম বা অ্যারেগুলির জন্য পদ্ধতিগুলি বাস্তবায়ন করা উচিত, এটি কেবল ধারণাটির একটি প্রমাণ।


এটি share (এবং পরবর্তী সম্পাদনাগুলি) পুনর্বিবেচনার একটি উত্তর।

আমি এই সম্পাদনাটি ভুল করব এবং ব্যাখ্যা করব যে এটি কেন প্রত্যাবর্তিত হতে পারে। পথের পাশাপাশি, আপনি কিছু অভ্যন্তরীণ সম্পর্কে কিছু বা দুটি জিনিস শিখতে পারেন, এবং কোনও সময়কালের অপ্টিমাইজেশান সত্যিই কী এবং এটি কীভাবে আপনাকে কামড় দিতে পারে সেটির আরেকটি উদাহরণ দেখুন।

tl; dr: শুধু String.Substring এবং String.Substring ব্যবহার করুন যদি আপনি তাড়াতাড়ি থাকেন (নীচে "মূল কোড"), আপনি যদি String.Substring পুনরায় প্রয়োগ করতে চান না তবে এটি সেরা সমন্বয়। আরও উন্নত কিছু ব্যবহার করুন (অন্যান্য উত্তর দেখুন) যা Convert.ToByte ব্যবহার করে না। যদি আপনি কর্মক্ষমতা প্রয়োজন হয় তবে। String.Substring ছাড়া অন্য কিছু ব্যবহার করবেন না String.SubstringString.Substring সাথে, যদি না কেউ এই উত্তরটির মতামত সম্পর্কে কিছু বলার আগ্রহ রাখে।

সতর্কতা: যদি 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 জন্য রেফারেন্স কোডটি String.Substring , এটি স্পষ্টভাবে "একক পাস" ইতিমধ্যেই; এবং কেন এটা করা উচিত নয়? এটি surrogate জোড়া না, বাইট-স্তরে কাজ করে।

এটি একটি নতুন স্ট্রিং বরাদ্দ করে তবে, তবে আপনি 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), সেগুলিও এড়াতে পারে , যদি আপনি যেভাবেই কার্য সম্পাদন করতে চান তবে আপনাকে অবশ্যই তা করতে হবে। যে সব বিভিন্ন পদ্ধতির আবিষ্কার অগণিত অন্যান্য উত্তর তাকান।

Disclaimer: রেফারেন্স উৎসটি আপ-টু-ডেট আছে কিনা তা যাচাই করার জন্য আমি ফ্রেমওয়ার্কের সর্বশেষ সংস্করণটি ডিকম্পাইল করেছি, আমি অনুমান করছি।

এখন, এটি সব ভাল এবং যৌক্তিক শোনাচ্ছে, এমনকি যদি আপনি এতদূর পর্যন্ত পরিচালিত হয়ে থাকেন তবে এমনকি স্পষ্ট। কিন্তু এটা কি সত্যি?

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

হ্যাঁ!

বেঞ্চ ফ্রেমওয়ার্ক জন্য Partridge Props, এটা হ্যাক করা সহজ। ব্যবহৃত ইনপুটটি নিম্নলিখিত SHA-1 হ্যাশটি 100,000 বাইট দীর্ঘ স্ট্রিং তৈরি করতে 5000 বার পুনরাবৃত্তি করেছে।

209113288F93A9AB8E474EA78D899AFDBB874355

আনন্দ কর! (কিন্তু সংযম সঙ্গে অপ্টিমাইজ।)


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

এক্সটেনশন পদ্ধতি (দাবিত্যাগ: সম্পূর্ণ অনির্বাচিত কোড, 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();
    }
}

ইত্যাদি .. টমালাকের তিনটি সমাধান ব্যবহার করুন (সর্বশেষটি স্ট্রিংয়ের এক্সটেনশন পদ্ধতি হিসাবে)।


@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)।

'A' এর জন্য 'f' আমাদের বড় সংখ্যা আছে তাই আমাদের 0ব্যবহার করে কিছু বিট করে ডিফল্ট সংস্করণ থেকে 32 বিয়োগ করতে হবে & 0x0f

65 জন্য কোড 'A'

48 জন্য কোড '0'

7 এর মধ্যে '9'এবং 'A'ASCII টেবিলের মধ্যে অক্ষর সংখ্যা ( ...456789:;<=>[email protected])।


ByteArrayToHexViaByteManipulation এর এই সংস্করণটি দ্রুত হতে পারে।

আমার রিপোর্ট থেকে:

  • ByteArrayToHexViaByteManipulation3: 1,68 গড় টিক্স (1000 রান বেশি), 17,5X
  • ByteArrayToHexViaByteManipulation2: 1,73 গড় টিক্স (1000 রান), 16,9X
  • ByteArrayToHexViaByteManipulation: 2,90 গড় টিক্স (1000 রান বেশি), 10,1X
  • ByteArrayToHexViaLookupAndShift: 3,22 গড় টিক্স (1000 রান বেশি), 9,1 এক্স
  • ...

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

এখনো বৈচিত্র্যের জন্য অন্য পার্থক্য:

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

এবং একটি এসকিউএল স্ট্রিং মধ্যে ঢোকানোর জন্য (যদি আপনি কমান্ড পরামিতি ব্যবহার করছেন না):

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

গতির জন্য অপ্টিমাইজ করা নয়, তবে বেশিরভাগ উত্তরগুলির চেয়ে বেশি 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

গতির দিক থেকে, এটি এখানে কিছু চেয়ে ভাল বলে মনে হচ্ছে:

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

মাইক্রোসফটের ডেভেলপারদের কাছ থেকে, একটি চমৎকার, সহজ রূপান্তর:

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

উপরে যখন একটি কম্প্যাক্ট পরিষ্কার করা হয়, কর্মক্ষমতা junkies enumerators ব্যবহার করে এটি সম্পর্কে চিত্কার হবে। আপনি টমোলকের মূল উত্তরের একটি উন্নত সংস্করণের সাথে শীর্ষ কর্মক্ষমতা পেতে পারেন:

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

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

   return hex.ToString();   
} 

এই পর্যন্ত আমি এখানে পোস্ট করা সব রুটিন দ্রুততম। শুধু এর জন্য আমার শব্দ গ্রহণ করবেন না ... কর্মক্ষমতা প্রতিটি রুটিন পরীক্ষা করে এবং নিজের জন্য সিআইএল কোড পরিদর্শন করে।


আমি এই বিট fiddling প্রতিযোগিতার লিখুন হিসাবে আমার একটি উত্তর আছে যে hexadecimals ডিকোড বিট-fiddling ব্যবহার করে । কলিং 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;
}

জাভা কোড থেকে রূপান্তরিত।


আরেকটি উপায় stackallocজিসি মেমরি চাপ কমাতে ব্যবহার করে হয়:

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

এখানে অনেকগুলি প্রশ্নের উত্তর দিতে হবে না, তবে হেক্স স্ট্রিং পার্সারটির সরল বাস্তবায়ন, আমি মোটামুটি অনুকূল (~ 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

বেস 64 এবং 'বিটকোনভার্টার্ড' লাইনগুলি সঠিকতা পরীক্ষা করার জন্য রয়েছে। তারা সমান যে নোট।

রুপায়ণ:

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অন্য পদ্ধতিতে (স্পষ্টভাবে অকার্যকর) চরিত্র-থেকে-নিষ্ঠুর ক্রমটি সরিয়েছিলাম , কিন্তু এটি দ্রুততম ছিল।

(আমি স্বীকার করি যে এটি অর্ধেক প্রশ্নের উত্তর দেয়। আমি অনুভব করেছি যে স্ট্রিং-> বাইট [] রূপান্তরটি পূর্বনির্ধারিত ছিল, যখন বাইট [] -> স্ট্রিং কোণটি ভালভাবে আবৃত মনে হচ্ছে। সুতরাং, এই উত্তরটি।)


এটা জটিল কেন? এই ভিজ্যুয়াল স্টুডিও 2008 সালে সহজ:

সি #:

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

ভিবি:

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

এটি একটি মহান পোস্ট। আমি ওয়ালিদের সমাধান পছন্দ করি। আমি প্যাট্রিজের পরীক্ষার মাধ্যমে এটি চালাচ্ছি না কিন্তু এটি বেশ দ্রুত বলে মনে হচ্ছে। আমি একটি বিপরীত প্রক্রিয়া প্রয়োজন, একটি হেক্স স্ট্রিং একটি বাইট অ্যারে রূপান্তর, তাই আমি 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;
}




hex