আপনি কীভাবে বাইট অ্যারেটিকে হেক্সাডেসিমাল স্ট্রিংয়ে রূপান্তর করতে পারেন এবং বিপরীতে?
আপনি কীভাবে বাইট অ্যারেটিকে হেক্সাডেসিমাল স্ট্রিংয়ে রূপান্তর করতে পারেন এবং বিপরীতে?
উত্তর:
উভয় ক্ষেত্রেই:
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
।
দ্রষ্টব্য: 2015-08-22 হিসাবে নতুন নেতা।
আমি কিছু ক্রুড Stopwatch
পারফরম্যান্স পরীক্ষার মাধ্যমে বিভিন্ন রূপান্তর পদ্ধতির প্রত্যেকটি দৌড়েছিলাম , একটি র্যান্ডম বাক্য (এন = 61, 1000 পুনরাবৃত্তি) সহ একটি রান এবং একটি প্রকল্প গুটেনবার্গ পাঠ্য সহ একটি রান (এন = 1,238,957, 150 পুনরাবৃত্তি)। মোটামুটি দ্রুত থেকে ধীরে ধীরে ফলাফলগুলি এখানে। সমস্ত পরিমাপ টিক্সে রয়েছে ( 10,000 টিক্স = 1 এমএস ) এবং সমস্ত আপেক্ষিক নোটগুলি [ধীরতম] StringBuilder
বাস্তবায়নের সাথে তুলনা করা হয় । ব্যবহৃত কোডের জন্য, নীচে দেখুন বা টেস্ট ফ্রেমওয়ার্ক রেপো যেখানে এখন আমি এটি চালানোর জন্য কোড বজায় রেখেছি।
সতর্কতা: কোন কিছু কংক্রিটের জন্য এই পরিসংখ্যানগুলির উপর নির্ভর করবেন না; এগুলি কেবল নমুনা ডেটার একটি নমুনা রান। আপনার যদি সত্যই শীর্ষস্থানীয় পারফরম্যান্সের প্রয়োজন হয় তবে দয়া করে আপনি কী ব্যবহার করবেন তার ডেটা প্রতিনিধির সাথে আপনার উত্পাদন প্রয়োজনের পরিবেশের প্রতিনিধি হিসাবে এই পদ্ধতিগুলি পরীক্ষা করুন।
unsafe
(CodesInChaos মাধ্যমে) (দ্বারা পরীক্ষা রেপো যোগ করা airbreather )
BitConverter
(তোমালকের মাধ্যমে)
{SoapHexBinary}.ToString
(মাইক্রফ্টের মাধ্যমে)
{byte}.ToString("X2")
(ব্যবহার করে foreach
) (উইলের ডিনের উত্তর থেকে প্রাপ্ত)
{byte}.ToString("X2")
(ব্যবহার করার জন্য {IEnumerable}.Aggregate
, সিস্টেম.লিনক প্রয়োজন) (মার্কের মাধ্যমে)
Array.ConvertAll
(ব্যবহার করে string.Join
) (উইল ডিনের মাধ্যমে)
Array.ConvertAll
(ব্যবহারের string.Concat
জন্য .NET 4.0 প্রয়োজন) (উইল ডিনের মাধ্যমে)
{StringBuilder}.AppendFormat
(ব্যবহার করে foreach
) (তোমালকের মাধ্যমে)
{StringBuilder}.AppendFormat
(ব্যবহার করার জন্য {IEnumerable}.Aggregate
, সিস্টেম.লিনক প্রয়োজন) (তোমালকের উত্তর থেকে প্রাপ্ত)
লাইটআপ টেবিলগুলি বাইট ম্যানিপুলেশনকে এগিয়ে নিয়েছে। মূলত, কোনও প্রদাহী বা বাইট হেক্সে কী হবে তা প্রাক-গুণনের কিছু ফর্ম রয়েছে। তারপরে, আপনি ডেটাটি ছিঁড়ে যাওয়ার সাথে সাথে কেবল হেক্স স্ট্রিংটি কী হবে তা দেখতে আপনি পরবর্তী অংশটি সন্ধান করবেন। সেই মানটি কিছু ফ্যাশনে ফলাফলের স্ট্রিং আউটপুটটিতে যুক্ত হয়। দীর্ঘ সময়ের জন্য বাইট হেরফের, সম্ভবত কিছু বিকাশকারী দ্বারা পড়া শক্ত, এটি ছিল শীর্ষ সম্পাদনা পদ্ধতি।
আপনার সেরা বাজিটি এখনও কিছু প্রতিনিধি ডেটা সন্ধান করতে এবং উত্পাদন-মতো পরিবেশে এটি চেষ্টা করে চলেছে। আপনার যদি মেমরির বিভিন্ন বাধা থাকে তবে আপনি কম বরাদ্দের একটি পদ্ধতি পছন্দ করতে পারেন যা দ্রুত হবে তবে আরও মেমরি গ্রাস করবে।
আমি ব্যবহার করা টেস্টিং কোডটি নির্দ্বিধায় খেলুন। একটি সংস্করণ এখানে অন্তর্ভুক্ত করা হয়েছে তবে রেপো ক্লোন করতে এবং আপনার নিজস্ব পদ্ধতি যুক্ত করতে নির্দ্বিধায় । আপনি আকর্ষণীয় কিছু খুঁজে পেতে বা এটি ব্যবহার করে পরীক্ষার কাঠামো উন্নত করতে সহায়তা করতে চান দয়া করে একটি টান অনুরোধ জমা দিন।
Func<byte[], string>
টেস্টস / কনভার্টবাইটআরেট্যোহেক্সস্ট্রিং / টেস্ট.সি-তে নতুন স্ট্যাটিক পদ্ধতি ( ) যুক্ত করুন।TestCandidates
একই শ্রেণিতে রিটার্ন মানটিতে সেই পদ্ধতির নাম যুক্ত করুন ।GenerateTestInput
একই শ্রেণিতে মন্তব্যগুলিতে টগল করে আপনি যে ইনপুট সংস্করণটি চান তা বাক্য বা পাঠ্য চালিয়ে যাচ্ছেন তা নিশ্চিত করুন ।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();
}
বিশ্লেষণে ওয়ালিদের উত্তর যুক্ত হয়েছে। দ্রুত শেষ কর.
যোগ করা হয়েছে string.Concat
Array.ConvertAll
সম্পূর্ণতার জন্য বৈকল্পিক (.NET 4.0 আবশ্যক)। string.Join
সংস্করণ সমান ।
টেস্ট রেপোতে আরও রূপগুলি অন্তর্ভুক্ত করে StringBuilder.Append(b.ToString("X2"))
। কেউ ফলাফল খারাপ করে না। উদাহরণস্বরূপ foreach
তুলনায় দ্রুত {IEnumerable}.Aggregate
, কিন্তু BitConverter
এখনও জিতেছে।
মাইক্রফ্টের SoapHexBinary
বিশ্লেষণের উত্তর যুক্ত করা হয়েছে, যা তৃতীয় স্থান অধিকার করেছে।
যুক্ত হয়েছে কোডসায়োস-এর বাইট ম্যানিপুলেশন উত্তর, যা প্রথম স্থান অধিকার করেছে (পাঠ্যের বৃহত ব্লকের উপর বৃহত্তর ব্যবধানে)।
নাথন মoinনভাজিরীর লুক উত্তর এবং ব্রায়ান ল্যামবার্টের ব্লগ থেকে বৈকল্পিক যুক্ত করা হয়েছে। উভয়ই বরং দ্রুত, তবে আমি যে পরীক্ষামূলক মেশিনটি ব্যবহার করেছি তার নেতৃত্ব নিচ্ছেন না (এএমডি ফেনোম 9750)।
যোগ করেছেন @ কোডসইনচাওসের নতুন বাইট-ভিত্তিক অনুসন্ধান উত্তর। এটি বাক্য পরীক্ষা এবং পূর্ণ-পাঠ্য পরীক্ষার উভয় ক্ষেত্রেই নেতৃত্ব নিয়েছে বলে মনে হয়।
যোগ করা হয়েছে airbreather এর অপ্টিমাইজেশন এবং unsafe
বৈকল্পিক এই উত্তর এর রেপো । যদি আপনি অনিরাপদ খেলায় খেলতে চান তবে আপনি সংক্ষিপ্ত স্ট্রিং এবং বৃহত পাঠ্য উভয় ক্ষেত্রে পূর্বের শীর্ষ বিজয়ীদের যেকোনটির থেকে কিছু বিশাল পারফরম্যান্স লাভ করতে পারেন।
bytes.ToHexStringAtLudicrousSpeed()
)।
সোপহেক্সবাইনারি নামে একটি বর্গ রয়েছে যা আপনি যা চান ঠিক তা করে।
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();
}
ক্রিপ্টো কোড লেখার সময় ডেটা নির্ভরশীল শাখাগুলি এবং টেবিলের অনুসন্ধানগুলি এড়ানো সাধারণ বিষয় নিশ্চিত করার জন্য রানটাইম ডেটা নির্ভর করে না, যেহেতু ডেটা নির্ভর নির্ভর সময় পার্শ্ব-চ্যানেলের আক্রমণ হতে পারে।
এটিও বেশ দ্রুত।
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);
}
ফাংলুই মিলিগ্রা'নাফ চথুলহু রুলিহ ওয়াগাহ'নাগল ফাটাগন
তোমরা যারা এখানে প্রবেশ কর, সমস্ত আশা ত্যাগ কর
অদ্ভুত বিট ফিডিংয়ের ব্যাখ্যা:
bytes[i] >> 4
একটি বাইটের উচ্চ স্তনবৃন্ত নিষ্কাশন করে একটি বাইটের bytes[i] & 0xF
নীচু স্তবক নিষ্কাশন করেb - 10
< 0
মানের জন্য b < 10
, যা পরিণত হবে একটি দশমিক অঙ্ক >= 0
মানের জন্য b > 10
, যা থেকে একটি চিঠি হয়ে যাবে A
থেকে F
।i >> 31
একটি স্বাক্ষরিত 32 বিট পূর্ণসংখ্যার ব্যবহার করে সাইনটি এক্সট্রেনশনের জন্য ধন্যবাদ racts এটা -1
জন্য i < 0
এবং 0
জন্য হবে i >= 0
।(b-10)>>31
হবে ।0
-1
0
এবং b
এটি 10 থেকে 15 এর মধ্যে থাকে We আমরা এটি A
(65) থেকে F
(70) এ মানচিত্র করতে চাই , যা 55 ( 'A'-10
) যুক্ত করে বোঝায় ।b
0 থেকে 9 পরিসীমা 0
(48) থেকে 9
(57) পর্যন্ত মানচিত্র করে । এর অর্থ এটি -7 ( '0' - 55
) হওয়া দরকার। & -7
পরে ব্যবহার করতে পারি ।(0 & -7) == 0
(-1 & -7) == -7
আরও কিছু বিবেচনা:
c
, যেহেতু পরিমাপ দেখায় যে এ থেকে গণনা i
করা সস্তা।i < bytes.Length
লুপের ঠিক উপরের সীমানা হিসাবে ব্যবহার করা জিটটারকে সীমাবদ্ধ চেকগুলি অপসারণ করতে দেয় bytes[i]
, সুতরাং আমি সেই বৈকল্পিকটি বেছে নিয়েছি।b
কোন int তৈরি করা বাইট থেকে এবং অপ্রয়োজনীয় রূপান্তরগুলির অনুমতি দেয়।hex string
করার byte[] array
?
87 + b + (((b-10)>>31)&-39)
byte[] array
", যার আক্ষরিক অর্থ বাইট অ্যারে বা একটি অ্যারে byte[][]
। আমি মজা করছি।
আপনি যদি এর চেয়ে আরও নমনীয়তা BitConverter
চান তবে সেই 1990-এর দশকের স্টাইলের স্পষ্ট লুপগুলি না চান তবে আপনি এটি করতে পারেন:
String.Join(String.Empty, Array.ConvertAll(bytes, x => x.ToString("X2")));
অথবা, আপনি। নেট 4.0 ব্যবহার করছেন:
String.Concat(Array.ConvertAll(bytes, x => x.ToString("X2")));
(মূল পোস্টে একটি মন্তব্য থেকে পরবর্তী।)
অন্য দেখার টেবিল ভিত্তিক পদ্ধতির। এটি প্রতিটি বাইটের জন্য কেবলমাত্র এক টুকরো টেবিলের পরিবর্তে প্রতি বাইটের জন্য ব্যবহার করে।
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;
}
Span
এখনকার পরিবর্তে এখন ব্যবহার করা যায় কিনা unsafe
??
আপনি 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-মুক্তিযোদ্ধা
আরও তথ্য: বিটকনভার্টার.টস্ট্রিং পদ্ধতি (বাইট []]
আমি আজ খুব একই সমস্যার মুখোমুখি হয়েছি এবং আমি এই কোডটি পেয়েছি:
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);
}
উত্স: ফোরামের পোস্ট বাইট [] অ্যারে টু হেক্স স্ট্রিং (পিজেহরার পোস্টটি দেখুন)। 0x উপসর্গটি সরাতে আমি কোডটি কিছুটা পরিবর্তন করেছি।
আমি কোডটিতে কিছু পারফরম্যান্স টেস্টিং করেছি এবং এটি বিটকনভার্টার.টস্ট্রিং () (প্যাট্রিজের পোস্ট অনুসারে দ্রুততম) ব্যবহার করার চেয়ে প্রায় আট গুণ বেশি দ্রুত ছিল।
এই একটি উত্তর সংস্করণ 4 এর Tomalak এর অত্যন্ত জনপ্রিয় উত্তর (এবং পরবর্তী সম্পাদনাগুলি)।
আমি এই সম্পাদনাটি ভুল বলে কেস করব এবং কেন এটি আবার ফিরিয়ে দেওয়া যেতে পারে তা ব্যাখ্যা করব। পথ ধরে, আপনি কিছু ইন্টার্নাল সম্পর্কে একটি বা দুটি জিনিস শিখতে পারেন এবং অকালীন অপটিমাইজেশন আসলে কী এবং এটি আপনাকে কীভাবে কামড় দিতে পারে তার আরও একটি উদাহরণ দেখুন।
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
এড়াতে সরাসরি সেখানে ব্যবহৃত একই কোডটিকে ইনলাইন করে lines কল ওভারহেড
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
হ্যাঁ!
বেঞ্চ কাঠামোর জন্য পার্ট্রিজের প্রপস, এটি হ্যাক করা সহজ। ব্যবহৃত ইনপুটটি হ'ল 100,000 বাইট দীর্ঘ স্ট্রিং তৈরি করতে নিম্নলিখিত SHA-1 হ্যাশটি 5000 বার পুনরাবৃত্তি করা হয়েছে।
209113288F93A9AB8E474EA78D899AFDBB874355
আনন্দ কর! (তবে সংযম সহ অপ্টিমাইজ করুন))
@ কোডসআইএনচাউস (বিপরীত পদ্ধতি) দ্বারা উত্তর দেওয়ার পরিপূরক
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
ছোট হাতের অক্ষরকে সমর্থন করা support
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
)।
'একটি' .. 'চ' এর জন্য আমরা বড় সংখ্যা আছে তাই আমরা কিছু বিট করে ডিফল্ট সংস্করণ থেকে 32 বিয়োগ আবশ্যক 0
ব্যবহার করে & 0x0f
।
65 কোড জন্য 'A'
48 এর জন্য কোড '0'
7 হ'ল ASCII সারণীতে ( ) এর মধ্যে '9'
এবং এর 'A'
মধ্যে থাকা বর্ণগুলির সংখ্যা ...456789:;<=>?@ABCD...
।
এই চেহারাটি লুকে আপ টেবিল ব্যবহার করেও সমাধান করা যেতে পারে। এটির জন্য এনকোডার এবং ডিকোডার উভয়ের জন্য অল্প পরিমাণে স্থির মেমরির প্রয়োজন হবে। এই পদ্ধতিটি তবে দ্রুত হবে:
আমার দ্রবণটি এনকোডিং টেবিলের জন্য 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 *
* এই সমাধান
ডিকোডিংয়ের সময় আইওএক্সেপশন এবং ইনডেক্সআউটআউটফ্রেঞ্জএক্সসেপশন ঘটতে পারে (যদি কোনও চরিত্রের খুব বেশি মান থাকে> 256)। ডি / এনকোডিং স্ট্রিম বা অ্যারেগুলির জন্য পদ্ধতিগুলি প্রয়োগ করা উচিত, এটি কেবল ধারণার প্রমাণ।
এটি একটি মহান পোস্ট। আমি ওয়ালিদের সমাধান পছন্দ করি। আমি এটি প্যাট্রিজ পরীক্ষার মাধ্যমে চালাতে পারি নি তবে এটি বেশ দ্রুত বলে মনে হচ্ছে। আমারও বিপরীত প্রক্রিয়া দরকার ছিল, একটি হেক্স স্ট্রিংকে বাইট অ্যারেতে রূপান্তর করা, তাই আমি এটিকে ওয়ালিদের সমাধানের বিপরীত হিসাবে লিখেছি। তোমালকের মূল সমাধানের চেয়ে দ্রুততর কিনা তা নিশ্চিত নন। আবার আমিও পেট্রিজ পরীক্ষার মাধ্যমে বিপরীত প্রক্রিয়া চালাইনি।
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;
}
hexString[i] &= ~0x20;
কেন এটি জটিল? এটি ভিজ্যুয়াল স্টুডিও ২০০৮-তে সহজ:
সি #:
string hex = BitConverter.ToString(YourByteArray).Replace("-", "");
ভিবি:
Dim hex As String = BitConverter.ToString(YourByteArray).Replace("-", "")
এখানে প্রচুর উত্তরের সন্ধান করতে নয়, তবে আমি হ্যাক্স স্ট্রিং পার্সারটির সহজবোধ্য বাস্তবায়ন (মোটামুটি অনুকূল) (স্বীকৃতের চেয়ে ~ 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
অন্য পদ্ধতিতে সরিয়ে নিয়েছি , তবে এটি এটি সবচেয়ে দ্রুততম ছিল।
(আমি স্বীকার করি যে এটি অর্ধেক প্রশ্নের জবাব দিয়েছে I আমি অনুভব করেছি যে স্ট্রিং-> বাইট [] রূপান্তরটি নীচে উপস্থাপিত হয়েছে, বাইট [] -> স্ট্রিং কোণটি ভালভাবে আবৃত বলে মনে হচ্ছে Thus সুতরাং, এই উত্তরটি))
নিরাপদ সংস্করণ:
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% দ্রুত এবং fromHex থেকে 10% দ্রুত।
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 বর্ণমালার পরীক্ষার জন্য বর্ণমালা পরীক্ষার জন্য প্রতিবার রূপান্তরিত ফাংশন হিসাবে ভুল বলা হয়, বর্ণমালা অবশ্যই কনস্ট (স্ট্রিংয়ের জন্য) বা স্ট্যাটিক রিডনলি (চর [] এর জন্য) হতে হবে। তারপরে বাইটের বর্ণমালা ভিত্তিক রূপান্তর [] স্ট্রিংয়ে বাইট ম্যানিপুলেশন সংস্করণগুলির মতো দ্রুত হয়ে যায়।
এবং অবশ্যই পরীক্ষার রিলিজ (অপ্টিমাইজেশান সহ) এবং ডিবাগ অপশন সহ "জেআইটি অপ্টিমাইজেশন চাপুন" বন্ধ করা হয়েছে (কোডটি ডিবাগযোগ্য হতে হবে "" জাস্ট মাই কোড সক্ষম করুন "এর জন্য একই) comp
ওয়ালিদ আইসা কোডের জন্য বিপরীত ফাংশন (হেক্স স্ট্রিং টু বাইট অ্যারে):
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);
}
সম্প্রসারণ পদ্ধতি (দাবি অস্বীকার: সম্পূর্ণরূপে অনির্ধারিত কোড, বিটিডাব্লু ...):
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();
}
}
ইত্যাদি .. টমলকের তিনটি সমাধানের মধ্যে দুটিই ব্যবহার করুন (সর্বশেষে স্ট্রিংটিতে এক্সটেনশন পদ্ধতি হ'ল)।
মাইক্রোসফ্ট এর বিকাশকারীদের কাছ থেকে, একটি দুর্দান্ত, সাধারণ রূপান্তর:
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();
}
আমি এখন পর্যন্ত এখানে পোস্ট করা সমস্ত রুটিনগুলির মধ্যে এটি দ্রুততম। এটির জন্য কেবল আমার শব্দটি গ্রহণ করবেন না ... প্রতিটি রুটিনের পারফরম্যান্স পরীক্ষা করুন এবং এর জন্য নিজের সিআইএল কোডটি পরীক্ষা করুন।
b.ToSting("X2")
।
এবং একটি এসকিউএল স্ট্রিং serোকানোর জন্য (আপনি যদি কমান্ড প্যারামিটার ব্যবহার না করেন):
public static String ByteArrayToSQLHexString(byte[] Source)
{
return = "0x" + BitConverter.ToString(Source).Replace("-", "");
}
Source == null
বা Source.Length == 0
আমরা একটি সমস্যা স্যার!
গতির দিক থেকে এটি এখানে যে কোনও কিছুর চেয়ে ভাল বলে মনে হচ্ছে:
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);
}
আপনি যে কোডটি কাজ করার পরামর্শ দিয়েছিলেন তা আমি পাইনি, অলিপ্রো। hex[i] + hex[i+1]
স্পষ্টতই একটি ফিরে int
।
তবে আমি ওয়ালিডস কোড থেকে কিছু ইঙ্গিত নিয়ে এবং এটি এক সাথে হাতুড়ি করে কিছু সাফল্য পেয়েছি। এটি জাহান্নামের মতো কুৎসিত তবে এটি আমার পরীক্ষাগুলি অনুসারে অন্যদের তুলনায় (প্যাট্রিজ টেস্টিং মেকানিজম ব্যবহার করে) 1/3 সময় কাজ করে বলে মনে হয়। ইনপুট আকারের উপর নির্ভর করে। প্রথমে 0-9 আলাদা করতে?: S এর চারপাশে স্যুইচিংয়ের ফলে সম্ভবত কিছুটা দ্রুত ফলাফল পাওয়া যাবে যেহেতু অক্ষরের চেয়ে বেশি সংখ্যা রয়েছে।
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;
}
বাইটআরারিটোহেক্সভিয়াবাাইটমেনিপুলেশনের এই সংস্করণটি আরও দ্রুত হতে পারে।
আমার রিপোর্ট থেকে:
...
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);
}
আমি এই বিট ফিডলিং প্রতিযোগিতায় প্রবেশ করবো কারণ আমার কাছে একটি উত্তর রয়েছে যা হেক্সাডেসিমালগুলি ডিকোড করতে বিট-ফিডলিং ব্যবহার করে । নোট করুন যে ক্যারেক্টার অ্যারেগুলি ব্যবহার করা আরও ত্বরান্বিত হতে পারে কারণ কলিং 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
পারফরম্যান্সের জন্য আমি ড্রফ্রোজেন সলিউশন সহ যাব। ডিকোডারটির জন্য একটি ক্ষুদ্রতর অপ্টিমাইজেশন হ'ল "<< 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]));
}
এটি আমার মাথার উপরের অংশের বাইরে এবং পরীক্ষা বা বেঞ্চমার্ক করা হয়নি।
বৈচিত্র্যের জন্য আরও একটি ভিন্নতা:
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;
}
গতির জন্য অপ্টিমাইজড নয়, তবে বেশিরভাগ উত্তরের চেয়ে লিনকুই (। নেট 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 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;
}
অন্য উপায় হ'ল 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);
}
এটি আমার শট এখানে। স্ট্রিং এবং বাইট বাড়ানোর জন্য আমি একজোড়া এক্সটেনশন ক্লাস তৈরি করেছি। বড় ফাইল পরীক্ষায়, সম্পাদনাটি বাইট ম্যানিপুলেশন 2 এর সাথে তুলনীয়।
ToHexString এর জন্য নীচের কোডটি লুকিং এবং শিফট অ্যালগরিদমের একটি অনুকূলিত বাস্তবায়ন। এটা তোলে Behrooz পর এক প্রায় অভিন্ন, কিন্তু এটা একটা ব্যবহার সক্রিয় আউট foreach
পুনরুক্তি করতে এবং একটি পাল্টা দ্রুত একটি স্পষ্টভাবে ইন্ডেক্স চেয়ে for
।
এটি আমার মেশিনে বাইট ম্যানিপুলেশন 2 এর পিছনে ২ য় স্থানে আসে এবং এটি খুব পঠনযোগ্য কোড। নিম্নলিখিত পরীক্ষার ফলাফলগুলিও আগ্রহের বিষয়:
টোহেক্সস্ট্রিংচরআরেউইথচরআর্রলুকআপ: ৪১,৫৯.6..6৯ গড় টিক্স (১০০০ রানেরও বেশি), 1.5X টোহেক্সস্ট্রিংচরআরে উইথস্ট্রিংলুকআপ: ৫০,764.0.০6 গড় টিক্স (১০০০ রানেরও বেশি), ১.২ এক্স টুহেক্সস্ট্রিং স্ট্রিংবিল্ডারথিক্র্যাচআরচিক্সিয়াস ৮০০, ৮০০, ৮০০, ৮০০, ৮০০, ৪০০, ৪০০, ওভারক্লুকআপ: tic২,
উপরের ফলাফলগুলির উপর ভিত্তি করে এই সিদ্ধান্তে পৌঁছানো নিরাপদ বলে মনে হচ্ছে:
কোডটি এখানে:
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;
}
}
}
নীচে আমি পরীক্ষার ফলাফলগুলি পেয়েছি যা যখন আমি আমার মেশিনে @ প্যাট্রিজের পরীক্ষামূলক প্রকল্পে আমার কোডটি রাখি। আমি হেক্সাডেসিমাল থেকে বাইট অ্যারে রূপান্তর করার জন্য একটি পরীক্ষাও যুক্ত করেছি। আমার কোডটি ব্যবহার করে এমন পরীক্ষাগুলি হ'ল বাইটআর্রেটিওহেক্সভিয়াঅপটিমাইজডলুকআপঅ্যান্ডশিফ্ট এবং হেক্সটোবাইটআরাইভিয়াবাাইটমনিপুলেশন। HexToByteArrayViaConvertToByte XXXXX থেকে নেওয়া হয়েছিল। @ মাইক্রফ্টের উত্তর থেকে হেক্সটোবাইটআরাইভিয়াসোপাএইচএক্সএক্সইবাইনারিটিই এটি।
ইন্টেল পেন্টিয়াম তৃতীয় জিওন প্রসেসর
Cores: 4 <br/> Current Clock Speed: 1576 <br/> Max Clock Speed: 3092 <br/>
বাইটের অ্যারেকে হেক্সাডেসিমাল স্ট্রিং উপস্থাপনায় রূপান্তর করা
বাইটআর্রেটিওহেক্সভিয়াবাাইটমনিপুলেশন 2: 39,366.64 গড় টিক্স (1000 রানেরও বেশি), 22.4X
বাইটআরারিটোহেক্সভিয়াঅ্যাপ্টিমাইজড লকআপঅ্যান্ড শিফট: 41,588.64 গড় টিক্স (1000 রানের বেশি), 21.2X
বাইটআরারিটোহেক্সভিয়া লুকআপ: 55,509.56 গড় টিক্স (1000 রানের বেশি), 15.9X
বাইটআর্রেটিওহেক্সভায়া বাইটমনিপুলেশন: 65,349.12 গড় টিক্স (1000 রানের বেশি), 13.5X
বাইটআরারিটোহেক্সভিয়া লাকআপঅ্যান্ড শিফট: 86,926.87 গড় টিক্স (1000 রানেরও বেশি), 10.2X
বাইটআর্রেটিওহেক্স স্ট্রিংভিয়াবিটকনভার্টার: 139,353.73 গড় টিক্স (1000 রানেরও বেশি), 6.3X
বাইটআর্রেটিওহেক্সভিয়াসোপএইচএইচবাইনারি: 314,598.77 গড় টিক্স (1000 রানেরও বেশি), 2.8X
বাইটআর্রেটিওহেক্স স্ট্রিংভিয়া স্ট্রিং বিল্ডার ফরএচবিটাইটোস্ট্রিং: 344,264.63 গড় টিক্স (1000 রানেরও বেশি), 2.6X
বাইটআর্রেটিওহেক্স স্ট্রিংভিয়া স্ট্রিংবিল্ডার অগ্রিগ্রেটবাইটটোস্ট্রিং: 382,623.44 গড় টিক্স (1000 রানেরও বেশি), 2.3X
বাইটআর্রেটিওহেক্স স্ট্রিংভিয়া স্ট্রিংবিল্ডারফোচ এপ অ্যাপেন্ডফর্ম্যাট: 818,111.95 গড় টিক্স (1000 রানেরও বেশি), 1.1 এক্স
বাইটআর্রেটিওহেক্স স্ট্রিংভিয়া স্ট্রিংকনক্যাটআরাই কনভার্টএল: 839,244.84 গড় টিক্স (1000 রানেরও বেশি), 1.1 এক্স
বাইটআর্রেটিওহেক্স স্ট্রিংভিয়া স্ট্রিংবিল্ডার অগ্রিগেট অ্যাপেন্ডেন্ট ফর্ম্যাট: 867,303.98 গড় টিক্স (1000 রানেরও বেশি), 1.0X
বাইটআর্রেটিওহেক্স স্ট্রিংভিয়া স্ট্রিংজইনআরাই কনভার্টএল: 882,710.28 গড় টিক্স (1000 রানেরও বেশি), 1.0X
আর একটি দ্রুত কাজ ...
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;
}