如何将字节[]转换为字符串?每次我尝试,我都
系统。Byte []
而不是数值。
另外,我如何得到十六进制而不是小数的值?
如何将字节[]转换为字符串?每次我尝试,我都
系统。Byte []
而不是数值。
另外,我如何得到十六进制而不是小数的值?
当前回答
.Net5.0更新
感谢@antoninkriz的基准比较,我们可以看到Convert。到目前为止,ToHexString是明显的赢家
使用Convert.ToHexString以外的任何方法都是愚蠢的。在我看来,它在可读性、性能和安全性方面明显更胜一筹
剩下的是2012年4月10日之前的数据:
我想我应该尝试比较这里列出的每个方法的速度。我基于这个编写了速度测试代码。
结果是BitConverter+String。替换似乎比大多数其他简单的方法更快。但是可以通过像Nathan Moinvaziri的ByteArrayToHexString或Kurt的ToHex这样的算法来提高速度。
我还发现了一个有趣的字符串。连接和串。对于长字符串,Join比StringBuilder实现慢得多,但对于较短的数组也类似。可能是由于在较长的字符串上扩展StringBuilder,所以设置初始大小应该消除这种差异。
Took each bit of code from an answer here: BitConvertRep = Answer by Guffa, BitConverter and String.Replace (I'd recommend for most cases, [edit:] where you can't use Convert.ToHexString) StringBuilder = Answer by Quintin Robinson, foreach char StringBuilder.Append LinqConcat = Answer by Michael Buen, string.Concat of Linq built array LinqJoin = Answer by mloskot, string.Join of Linq built array LinqAgg = Answer by Matthew Whited, IEnumerable.Aggregate with StringBuilder ToHex = Answer by Kurt, sets chars in an array, using byte values to get hex ByteArrayToHexString = Answer by Nathan Moinvaziri, approx same speed as the ToHex above, and is probably easier to read (I'd recommend for speed, [edit:] where you can't use Convert.ToHexString) ToHexFromTable = Linked in answer by Nathan Moinvaziri, for me this is near the same speed as the above 2 but requires an array of 256 strings to always exist
With: LONG_STRING_LENGTH = 1000 * 1024; BitConvertRep calculation Time Elapsed 27,202 ms (fastest built in/simple) StringBuilder calculation Time Elapsed 75,723 ms (StringBuilder no reallocate) LinqConcat calculation Time Elapsed 182,094 ms LinqJoin calculation Time Elapsed 181,142 ms LinqAgg calculation Time Elapsed 93,087 ms (StringBuilder with reallocating) ToHex calculation Time Elapsed 19,167 ms (fastest) With: LONG_STRING_LENGTH = 100 * 1024;, Similar results BitConvertReplace calculation Time Elapsed 3431 ms StringBuilder calculation Time Elapsed 8289 ms LinqConcat calculation Time Elapsed 21512 ms LinqJoin calculation Time Elapsed 19433 ms LinqAgg calculation Time Elapsed 9230 ms ToHex calculation Time Elapsed 1976 ms With: int MANY_STRING_COUNT = 1000; int MANY_STRING_LENGTH = 1024; (Same byte count as first test but in different arrays) BitConvertReplace calculation Time Elapsed 25,680 ms StringBuilder calculation Time Elapsed 78,411 ms LinqConcat calculation Time Elapsed 101,233 ms LinqJoin calculation Time Elapsed 99,311 ms LinqAgg calculation Time Elapsed 84,660 ms ToHex calculation Time Elapsed 18,221 ms With: int MANY_STRING_COUNT = 2000; int MANY_STRING_LENGTH = 20; BitConvertReplace calculation Time Elapsed 1347 ms StringBuilder calculation Time Elapsed 3234 ms LinqConcat calculation Time Elapsed 5013 ms LinqJoin calculation Time Elapsed 4826 ms LinqAgg calculation Time Elapsed 3589 ms ToHex calculation Time Elapsed 772 ms
我使用的测试代码:
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();
}
还有一个类似过程的答案,我还没有比较我们的结果。
其他回答
十六进制,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以后,字符串。Concat有一个接受IEnumerable的重载。因此,在4.0版本中,上述代码对于变量s和t将有相同的输出
010204081020
010204081020
4.0之前,ba。Select(b => b.ToString("X2"))将重载(对象arg0), IEnumerable<string>进入适当重载的方式,即(params string[] values),是我们需要将IEnumerable<string>转换为字符串数组。4.0之前,字符串。Concat有10个过载功能,在4.0现在是12个
你把LINQ和字符串方法结合起来:
string hex = string.Join("",
bin.Select(
bin => bin.ToString("X2")
).ToArray());
下面是另一种方法:
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;
}
或者,你可以像这样预先构建翻译表,以获得更快的结果:
http://blogs.msdn.com/b/blambert/archive/2009/02/22/blambert-codesnip-fast-byte-array-to-hex-string-conversion.aspx
再向这个堆中添加一个答案,有一个System.Runtime.Remoting.Metadata.W3cXsd2001。SoapHexBinary类,我已经使用它可以转换字节和十六进制:
string hex = new SoapHexBinary(bytes).ToString();
byte[] bytes = SoapHexBinary.Parse(hex).Value;
不确定它与其他实现(基准)相比如何,但在我看来,它非常简单——特别是从十六进制转换回字节。
:
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);
结果:0102030 d0e0f