【发布时间】:2012-09-25 06:10:27
【问题描述】:
如何将byte[] 转换为string?每次我尝试它,我都会得到
System.Byte[]
而不是值。
另外,如何获得十六进制而不是十进制的值?
【问题讨论】:
-
“每次我尝试它”你听起来像一段时间它可能真的有效。
-
有理由假设提问者尝试了不同的方法
如何将byte[] 转换为string?每次我尝试它,我都会得到
System.Byte[]
而不是值。
另外,如何获得十六进制而不是十进制的值?
【问题讨论】:
这是另一种方法:
public static string ByteArrayToHexString(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();
}
public static byte[] HexStringToByteArray(string Hex)
{
byte[] Bytes = new byte[Hex.Length / 2];
int[] HexValue = new int[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
for (int x = 0, i = 0; i < Hex.Length; i += 2, x += 1)
{
Bytes[x] = (byte)(HexValue[Char.ToUpper(Hex[i + 0]) - '0'] << 4 |
HexValue[Char.ToUpper(Hex[i + 1]) - '0']);
}
return Bytes;
}
或者,您可以像这样预先构建转换表以获得更快的结果:
【讨论】:
StringBuilder Result = new StringBuilder(Bytes.Length * 2); 在我的测试中稍微加快了速度
有一个内置的方法:
byte[] data = { 1, 2, 4, 8, 16, 32 };
string hex = BitConverter.ToString(data);
结果:01-02-04-08-10-20
如果你想要它没有破折号,只需删除它们:
string hex = BitConverter.ToString(data).Replace("-", string.Empty);
结果:010204081020
如果你想要更紧凑的表示,可以使用 Base64:
string base64 = Convert.ToBase64String(data);
结果:AQIECBAg
【讨论】:
+= 将字符串连接在一起,是吗?
+=,它适用于非常短的循环,但它的扩展性非常差。每次额外的迭代大约会使执行时间加倍,因此在大约 20 次迭代时,您会遇到性能问题。每增加 10 次迭代将使循环花费大约 1000 倍。
非常快速的扩展方法(带反转):
public static class ExtensionMethods {
public static string ToHex(this byte[] data) {
return ToHex(data, "");
}
public static string ToHex(this byte[] data, string prefix) {
char[] lookup = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
int i = 0, p = prefix.Length, l = data.Length;
char[] c = new char[l * 2 + p];
byte d;
for(; i < p; ++i) c[i] = prefix[i];
i = -1;
--l;
--p;
while(i < l) {
d = data[++i];
c[++p] = lookup[d >> 4];
c[++p] = lookup[d & 0xF];
}
return new string(c, 0, c.Length);
}
public static byte[] FromHex(this string str) {
return FromHex(str, 0, 0, 0);
}
public static byte[] FromHex(this string str, int offset, int step) {
return FromHex(str, offset, step, 0);
}
public static byte[] FromHex(this string str, int offset, int step, int tail) {
byte[] b = new byte[(str.Length - offset - tail + step) / (2 + step)];
byte c1, c2;
int l = str.Length - tail;
int s = step + 1;
for(int y = 0, x = offset; x < l; ++y, x += s) {
c1 = (byte)str[x];
if(c1 > 0x60) c1 -= 0x57;
else if(c1 > 0x40) c1 -= 0x37;
else c1 -= 0x30;
c2 = (byte)str[++x];
if(c2 > 0x60) c2 -= 0x57;
else if(c2 > 0x40) c2 -= 0x37;
else c2 -= 0x30;
b[y] = (byte)((c1 << 4) + c2);
}
return b;
}
}
在上述速度测试中击败所有其他人:
=== 长字符串测试
BitConvertReplace 计算耗时 2415 毫秒
StringBuilder 计算耗时 5668 毫秒
LinqConcat 计算耗时 11826 ms
LinqJoin 计算耗时 9323 毫秒
LinqAgg 计算耗时 7444 毫秒
ToHexTable 计算耗时 1028 毫秒
ToHexAcidzombie 计算耗时 1035 毫秒
ToHexPatrick 计算耗时 814 毫秒
ToHexKurt 计算耗时 1604 毫秒
ByteArrayToHexString 计算耗时 1330 ms=== 多串测试
BitConvertReplace 计算耗时 2238 毫秒
StringBuilder 计算耗时 5393 毫秒
LinqConcat 计算耗时 9043 毫秒
LinqJoin 计算耗时 9131 毫秒
LinqAgg 计算耗时 7324 毫秒
ToHexTable 计算耗时 968 毫秒
ToHexAcidzombie 计算耗时 969 毫秒
ToHexPatrick 计算耗时 956 毫秒
ToHexKurt 计算耗时 1547 毫秒
ByteArrayToHexString 计算耗时 1277 ms
【讨论】:
我不确定您是否需要执行此操作,但这是我能想到的将 byte[] 转换为十六进制字符串的最快方法:
static readonly char[] hexchar = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
public static string HexStr(byte[] data, int offset, int len, bool space = false)
{
int i = 0, k = 2;
if (space) k++;
var c = new char[len * k];
while (i < len)
{
byte d = data[offset + i];
c[i * k] = hexchar[d / 0x10];
c[i * k + 1] = hexchar[d % 0x10];
if (space && i < len - 1) c[i * k + 2] = ' ';
i++;
}
return new string(c, 0, c.Length);
}
【讨论】:
我想我应该提供一个答案。根据我的测试,这种方法是最快的
public static class Helper
{
public static string[] HexTbl = Enumerable.Range(0, 256).Select(v => v.ToString("X2")).ToArray();
public static string ToHex(this IEnumerable<byte> array)
{
StringBuilder s = new StringBuilder();
foreach (var v in array)
s.Append(HexTbl[v]);
return s.ToString();
}
public static string ToHex(this byte[] array)
{
StringBuilder s = new StringBuilder(array.Length*2);
foreach (var v in array)
s.Append(HexTbl[v]);
return s.ToString();
}
}
【讨论】:
这里没有人提到你得到“System.Byte[]”字符串而不是值的原因,所以我会。
当一个对象被隐式转换为字符串时,程序将默认使用该对象的public String ToString()方法,该方法继承自System.Object:
public virtual string ToString()
{
return this.GetType().ToString();
}
如果你发现你经常进行这种转换,你可以简单地创建一个包装类并像这样覆盖这个方法:
public override string ToString()
{
// do the processing here
// return the nicely formatted string
}
现在每次打印此包装对象时,您都会得到您的值,而不是来自this.GetType().ToString() 的值。
【讨论】:
为了再添加一个答案,我使用了一个 System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary 类,它可以将字节转换为十六进制:
string hex = new SoapHexBinary(bytes).ToString();
byte[] bytes = SoapHexBinary.Parse(hex).Value;
不确定它如何与其他实现进行比较(基准测试),但 IMO 它非常简单——尤其是从十六进制转换回字节。
【讨论】:
Hex,Linq-fu:
string.Concat(ba.Select(b => b.ToString("X2")).ToArray())
与时俱进
正如@RubenBartelink 所指出的,没有将IEnumerable<string> 转换为数组的代码:ba.Select(b => b.ToString("X2")) 在4.0 之前不起作用,相同的代码现在在4.0 上起作用。
这段代码...
byte[] ba = { 1, 2, 4, 8, 16, 32 };
string s = string.Concat(ba.Select(b => b.ToString("X2")));
string t = string.Concat(ba.Select(b => b.ToString("X2")).ToArray());
Console.WriteLine (s);
Console.WriteLine (t);
...在 .NET 4.0 之前,输出为:
System.Linq.Enumerable+<CreateSelectIterator>c__Iterator10`2[System.Byte,System.String]
010204081020
从 .NET 4.0 开始,string.Concat 有一个接受 IEnumerable 的重载。因此,在 4.0 上,上述代码对于变量 s 和 t 将具有相同的输出
010204081020
010204081020
在 4.0 之前,ba.Select(b => b.ToString("X2")) 去重载(object arg0),IEnumerable<string> 去适当的重载,即(params string[] values),我们需要将IEnumerable<string> 转换为字符串数组。在 4.0 之前,string.Concat 有 10 个重载函数,在 4.0 上现在是 12 个
【讨论】:
string.Concat(from b in ba select b.ToString("X2")) 更漂亮 - 是否有机会将其作为第二行进行编辑,前提是它依赖于 .NET 4.0 String.Concat(IEnumerable<string>) 过载?
我想我做了一个更快的字节数组到字符串转换器:
public static class HexTable
{
private static readonly string[] table = BitConverter.ToString(Enumerable.Range(0, 256).Select(x => (byte)x).ToArray()).Split('-');
public static string ToHexTable(byte[] value)
{
StringBuilder sb = new StringBuilder(2 * value.Length);
for (int i = 0; i < value.Length; i++)
sb.Append(table[value[i]]);
return sb.ToString();
}
测试设置:
static void Main(string[] args)
{
const int TEST_COUNT = 10000;
const int BUFFER_LENGTH = 100000;
Random random = new Random();
Stopwatch sw = new Stopwatch();
Stopwatch sw2 = new Stopwatch();
byte[] buffer = new byte[BUFFER_LENGTH];
random.NextBytes(buffer);
sw.Start();
for (int j = 0; j < TEST_COUNT; j++)
HexTable.ToHexTable(buffer);
sw.Stop();
sw2.Start();
for (int j = 0; j < TEST_COUNT; j++)
ToHexChar.ToHex(buffer);
sw2.Stop();
Console.WriteLine("Hex Table Elapsed Milliseconds: {0}", sw.ElapsedMilliseconds);
Console.WriteLine("ToHex Elapsed Milliseconds: {0}", sw2.ElapsedMilliseconds);
}
ToHexChar.ToHEx() 方法是前面显示的 ToHex() 方法。
结果如下:
HexTable = 11808 毫秒 ToHEx = 12168ms
看起来可能没有太大区别,但它仍然更快:)
【讨论】:
private static string GuidToRaw(Guid guid)
{
byte[] bytes = guid.ToByteArray();
int сharCount = bytes.Length * 2;
char[] chars = new char[сharCount];
int index = 0;
for (int i = 0; i < сharCount; i += 2)
{
byte b = bytes[index++];
chars[i] = GetHexValue((int)(b / 16));
chars[i + 1] = GetHexValue((int)(b % 16));
}
return new string(chars, 0, chars.Length);
}
private static char GetHexValue(int i)
{
return (char)(i < 10 ? i + 48 : i + 55);
}
【讨论】:
我想我会尝试比较一下这里列出的每种方法的速度。 I based the speed testing code off this.
结果是 BitConverter+String.Replace 似乎比大多数其他简单方法更快。但是可以使用 Nathan Moinvaziri's ByteArrayToHexString 或 Kurt 的 ToHex 等算法来提高速度。
我还发现有趣的是 string.Concat 和 string.Join 对于长字符串比 StringBuilder 实现慢得多,但对于较短的数组则类似。可能是由于在较长的字符串上扩展了 StringBuilder,所以设置初始大小应该可以抵消这种差异。
与:
LONG_STRING_LENGTH = 1000 * 1024;
- BitConvertRep 计算时间 27,202 毫秒(最快的内置/简单)
- StringBuilder 计算耗时 75,723 毫秒(StringBuilder 没有重新分配)
- LinqConcat 计算耗时 182,094 毫秒
- LinqJoin 计算耗时 181,142 毫秒
- LinqAgg 计算耗时 93,087 毫秒(带重新分配的 StringBuilder)
- ToHex 计算耗时19,167 ms(最快)
使用:
LONG_STRING_LENGTH = 100 * 1024;,结果相似
- BitConvertReplace 计算耗时 3431 毫秒
- StringBuilder 计算耗时 8289 毫秒
- LinqConcat 计算耗时 21512 毫秒
- LinqJoin 计算耗时 19433 毫秒
- LinqAgg 计算耗时 9230 毫秒
- ToHex 计算耗时 1976 毫秒
与:
int MANY_STRING_COUNT = 1000;int MANY_STRING_LENGTH = 1024;(与第一次测试相同的字节数,但在不同的数组中)
- BitConvertReplace 计算耗时 25,680 毫秒
- StringBuilder 计算耗时 78,411 毫秒
- LinqConcat 计算耗时 101,233 毫秒
- LinqJoin 计算耗时 99,311 毫秒
- LinqAgg 计算耗时 84,660 毫秒
- ToHex 计算耗时 18,221 毫秒
与:
int MANY_STRING_COUNT = 2000;int MANY_STRING_LENGTH = 20;
- BitConvertReplace 计算耗时 1347 毫秒
- StringBuilder 计算耗时 3234 毫秒
- LinqConcat 计算耗时 5013 毫秒
- LinqJoin 计算耗时 4826 毫秒
- LinqAgg 计算耗时 3589 毫秒
- ToHex 计算耗时 772 毫秒
我使用的测试代码:
void Main()
{
int LONG_STRING_LENGTH = 100 * 1024;
int MANY_STRING_COUNT = 1024;
int MANY_STRING_LENGTH = 100;
var source = GetRandomBytes(LONG_STRING_LENGTH);
List<byte[]> manyString = new List<byte[]>(MANY_STRING_COUNT);
for (int i = 0; i < MANY_STRING_COUNT; ++i)
{
manyString.Add(GetRandomBytes(MANY_STRING_LENGTH));
}
var algorithms = new Dictionary<string,Func<byte[], string>>();
algorithms["BitConvertReplace"] = BitConv;
algorithms["StringBuilder"] = StringBuilderTest;
algorithms["LinqConcat"] = LinqConcat;
algorithms["LinqJoin"] = LinqJoin;
algorithms["LinqAgg"] = LinqAgg;
algorithms["ToHex"] = ToHex;
algorithms["ByteArrayToHexString"] = ByteArrayToHexString;
Console.WriteLine(" === Long string test");
foreach (var pair in algorithms) {
TimeAction(pair.Key + " calculation", 500, () =>
{
pair.Value(source);
});
}
Console.WriteLine(" === Many string test");
foreach (var pair in algorithms) {
TimeAction(pair.Key + " calculation", 500, () =>
{
foreach (var str in manyString)
{
pair.Value(str);
}
});
}
}
// Define other methods and classes here
static void TimeAction(string description, int iterations, Action func) {
var watch = new Stopwatch();
watch.Start();
for (int i = 0; i < iterations; i++) {
func();
}
watch.Stop();
Console.Write(description);
Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds);
}
//static byte[] GetRandomBytes(int count) {
// var bytes = new byte[count];
// (new Random()).NextBytes(bytes);
// return bytes;
//}
static Random rand = new Random();
static byte[] GetRandomBytes(int count) {
var bytes = new byte[count];
rand.NextBytes(bytes);
return bytes;
}
static string BitConv(byte[] data)
{
return BitConverter.ToString(data).Replace("-", string.Empty);
}
static string StringBuilderTest(byte[] data)
{
StringBuilder sb = new StringBuilder(data.Length*2);
foreach (byte b in data)
sb.Append(b.ToString("X2"));
return sb.ToString();
}
static string LinqConcat(byte[] data)
{
return string.Concat(data.Select(b => b.ToString("X2")).ToArray());
}
static string LinqJoin(byte[] data)
{
return string.Join("",
data.Select(
bin => bin.ToString("X2")
).ToArray());
}
static string LinqAgg(byte[] data)
{
return data.Aggregate(new StringBuilder(),
(sb,v)=>sb.Append(v.ToString("X2"))
).ToString();
}
static string ToHex(byte[] bytes)
{
char[] c = new char[bytes.Length * 2];
byte b;
for(int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx)
{
b = ((byte)(bytes[bx] >> 4));
c[cx] = (char)(b > 9 ? b - 10 + 'A' : b + '0');
b = ((byte)(bytes[bx] & 0x0F));
c[++cx] = (char)(b > 9 ? b - 10 + 'A' : b + '0');
}
return new string(c);
}
public static string ByteArrayToHexString(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();
}
Also another answer with a similar process,我还没有比较我们的结果。
【讨论】:
(char)(b > 9 ? b - 10 + 'A' : b + '0');
"0123456789ABCDEF"[b]
ByteArrayToHexString 的不完整版本,我的总结建议速度
与:
byte[] data = new byte[] { 0x01, 0x02, 0x03, 0x0D, 0x0E, 0x0F };
string hex = string.Empty;
data.ToList().ForEach(b => hex += b.ToString("x2"));
// use "X2" for uppercase hex letters
Console.WriteLine(hex);
结果:0102030d0e0f
【讨论】:
这里是字节数组(byte[])的扩展方法,例如,
var b = new byte[] { 15, 22, 255, 84, 45, 65, 7, 28, 59, 10 };
Console.WriteLine(b.ToHexString());
public static class HexByteArrayExtensionMethods
{
private const int AllocateThreshold = 256;
private const string UpperHexChars = "0123456789ABCDEF";
private const string LowerhexChars = "0123456789abcdef";
private static string[] upperHexBytes;
private static string[] lowerHexBytes;
public static string ToHexString(this byte[] value)
{
return ToHexString(value, false);
}
public static string ToHexString(this byte[] value, bool upperCase)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
if (value.Length == 0)
{
return string.Empty;
}
if (upperCase)
{
if (upperHexBytes != null)
{
return ToHexStringFast(value, upperHexBytes);
}
if (value.Length > AllocateThreshold)
{
return ToHexStringFast(value, UpperHexBytes);
}
return ToHexStringSlow(value, UpperHexChars);
}
if (lowerHexBytes != null)
{
return ToHexStringFast(value, lowerHexBytes);
}
if (value.Length > AllocateThreshold)
{
return ToHexStringFast(value, LowerHexBytes);
}
return ToHexStringSlow(value, LowerhexChars);
}
private static string ToHexStringSlow(byte[] value, string hexChars)
{
var hex = new char[value.Length * 2];
int j = 0;
for (var i = 0; i < value.Length; i++)
{
var b = value[i];
hex[j++] = hexChars[b >> 4];
hex[j++] = hexChars[b & 15];
}
return new string(hex);
}
private static string ToHexStringFast(byte[] value, string[] hexBytes)
{
var hex = new char[value.Length * 2];
int j = 0;
for (var i = 0; i < value.Length; i++)
{
var s = hexBytes[value[i]];
hex[j++] = s[0];
hex[j++] = s[1];
}
return new string(hex);
}
private static string[] UpperHexBytes
{
get
{
return (upperHexBytes ?? (upperHexBytes = new[] {
"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" }));
}
}
private static string[] LowerHexBytes
{
get
{
return (lowerHexBytes ?? (lowerHexBytes = new[] {
"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" }));
}
}
}
【讨论】:
使用 LINQ 的好方法...
var data = new byte[] { 1, 2, 4, 8, 16, 32 };
var hexString = data.Aggregate(new StringBuilder(),
(sb,v)=>sb.Append(v.ToString("X2"))
).ToString();
【讨论】:
我喜欢使用扩展方法进行这样的转换,即使它们只是包装标准库方法。在十六进制转换的情况下,我使用以下手动调整(即快速)算法:
public static string ToHex(this byte[] bytes)
{
char[] c = new char[bytes.Length * 2];
byte b;
for(int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx)
{
b = ((byte)(bytes[bx] >> 4));
c[cx] = (char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30);
b = ((byte)(bytes[bx] & 0x0F));
c[++cx]=(char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30);
}
return new string(c);
}
public static byte[] HexToBytes(this string str)
{
if (str.Length == 0 || str.Length % 2 != 0)
return new byte[0];
byte[] buffer = new byte[str.Length / 2];
char c;
for (int bx = 0, sx = 0; bx < buffer.Length; ++bx, ++sx)
{
// Convert first half of byte
c = str[sx];
buffer[bx] = (byte)((c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0')) << 4);
// Convert second half of byte
c = str[++sx];
buffer[bx] |= (byte)(c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0'));
}
return buffer;
}
【讨论】:
你将 LINQ 与字符串方法结合起来:
string hex = string.Join("",
bin.Select(
bin => bin.ToString("X2")
).ToArray());
【讨论】:
string.Concat()和删除.ToArray()来简化
$"{bin:X2}" :)
正如其他人所说,这取决于字节数组中值的编码。尽管如此,您需要非常小心这种事情,否则您可能会尝试转换未由所选编码处理的字节。
Jon Skeet 有一个关于 .NET 中的编码和 unicode 的good article。推荐阅读。
【讨论】:
好吧,我不经常将字节转换为十六进制,所以我不得不说我不知道是否有比这更好的方法,但这里有一种方法。
StringBuilder sb = new StringBuilder();
foreach (byte b in myByteArray)
sb.Append(b.ToString("X2"));
string hexString = sb.ToString();
【讨论】:
您必须知道以字节表示的字符串的编码,但您可以说System.Text.UTF8Encoding.GetString(bytes) 或System.Text.ASCIIEncoding.GetString(bytes)。 (我是凭记忆做的,所以 API 可能不完全正确,但非常接近。)
关于第二个问题的答案,请参阅this question。
【讨论】: