Wie konvertiere ich eine byte[]
zu einer string
? Jedes Mal, wenn ich es versuche, bekomme ich
System.Byte[]
anstelle des Wertes.
Und wie erhalte ich den Wert in Hexadezimal- statt in Dezimalwerten?
Wie konvertiere ich eine byte[]
zu einer string
? Jedes Mal, wenn ich es versuche, bekomme ich
System.Byte[]
anstelle des Wertes.
Und wie erhalte ich den Wert in Hexadezimal- statt in Dezimalwerten?
Hierfür gibt es eine eingebaute Methode:
byte[] data = { 1, 2, 4, 8, 16, 32 };
string hex = BitConverter.ToString(data);
Ergebnis: 01-02-04-08-10-20
Wenn Sie es ohne die Bindestriche wollen, entfernen Sie sie einfach:
string hex = BitConverter.ToString(data).Replace("-", string.Empty);
Ergebnis: 010204081020
Wenn Sie eine kompaktere Darstellung wünschen, können Sie Base64 verwenden:
string base64 = Convert.ToBase64String(data);
Ergebnis: AQIECBAg
Danke an @antoninkriz's Benchmark-Vergleich können wir sehen, dass Convert.ToHexString
es mit Abstand der klare Sieger heute
Es wäre töricht, etwas anderes zu verwenden als Convert.ToHexString
. Meiner Meinung nach gewinnt es eindeutig in den Bereichen: Lesbarkeit, Leistung, Sicherheit
Der Rest dieses Textes ist von vor dem 10. April 2012:
Ich dachte mir, ich vergleiche einfach mal die Geschwindigkeit der einzelnen hier aufgeführten Methoden. Der Code für die Geschwindigkeitstests basiert auf dieser Grundlage.
Das Ergebnis ist, dass BitConverter+String.Replace schneller zu sein scheint als die meisten anderen einfachen Methoden. Aber die Geschwindigkeit kann mit Algorithmen wie Nathan Moinvaziris ByteArrayToHexString oder Kurt's ToHex.
Ich fand es auch interessant, dass string.Concat und string.Join viel langsamer als StringBuilder-Implementierungen für lange Strings, aber ähnlich für kürzere Arrays sind. Wahrscheinlich aufgrund der Erweiterung des StringBuilders auf die längeren Strings, so dass die Einstellung der ursprünglichen Größe sollte diesen Unterschied zu negieren.
Convert.ToHexString
)Convert.ToHexString
)Mit:
LONG_STRING_LENGTH = 1000 * 1024;
- BitConvertRep-Berechnung Abgelaufene Zeit 27.202 ms (am schnellsten eingebaut/einfach)
- StringBuilder Berechnung Verstrichene Zeit 75,723 ms (StringBuilder no reallocate)
- LinqConcat-Berechnung Verstrichene Zeit 182,094 ms
- LinqJoin-Berechnung Verstrichene Zeit 181,142 ms
- LinqAgg-Berechnung Verstrichene Zeit 93,087 ms (StringBuilder mit Reallocating)
- ToHex-Berechnung Verstrichene Zeit 19.167 ms (am schnellsten)
Mit:
LONG_STRING_LENGTH = 100 * 1024;
, Ähnliche Ergebnisse
- BitConvertReplace-Berechnung Verstrichene Zeit 3431 ms
- StringBuilder Berechnung Verstrichene Zeit 8289 ms
- LinqConcat-Berechnung Verstrichene Zeit 21512 ms
- LinqJoin-Berechnung Verstrichene Zeit 19433 ms
- LinqAgg-Berechnung Verstrichene Zeit 9230 ms
- ToHex-Berechnung Verstrichene Zeit 1976 ms
Mit:
int MANY_STRING_COUNT = 1000;
int MANY_STRING_LENGTH = 1024;
(Gleiche Byteanzahl wie beim ersten Test, aber in verschiedenen Arrays)
- BitConvertReplace-Berechnung Verstrichene Zeit 25,680 ms
- StringBuilder Berechnung Verstrichene Zeit 78,411 ms
- LinqConcat-Berechnung Verstrichene Zeit 101,233 ms
- LinqJoin-Berechnung Verstrichene Zeit 99,311 ms
- LinqAgg-Berechnung Verstrichene Zeit 84,660 ms
- ToHex-Berechnung Verstrichene Zeit 18,221 ms
Mit:
int MANY_STRING_COUNT = 2000;
int MANY_STRING_LENGTH = 20;
- BitConvertReplace Berechnung Verstrichene Zeit 1347 ms
- StringBuilder Berechnung Verstrichene Zeit 3234 ms
- LinqConcat-Berechnung Verstrichene Zeit 5013 ms
- LinqJoin-Berechnung Verstrichene Zeit 4826 ms
- LinqAgg-Berechnung Verstrichene Zeit 3589 ms
- ToHex-Berechnung Verstrichene Zeit 772 ms
Der von mir verwendete Testcode:
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();
}
Auch eine andere Antwort mit einem ähnlichen Verfahren Ich habe unsere Ergebnisse noch nicht miteinander verglichen.
Hex, Linq-fu:
string.Concat(ba.Select(b => b.ToString("X2")).ToArray())
UPDATE mit der Zeit
Wie von @RubenBartelink angemerkt, ist der Code, der keine Umwandlung von IEnumerable<string>
zu einem Array: ba.Select(b => b.ToString("X2"))
vor 4.0 nicht funktioniert hat, funktioniert derselbe Code jetzt unter 4.0.
Dieser Code...
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);
...vor .NET 4.0, die Ausgabe ist:
System.Linq.Enumerable+<CreateSelectIterator>c__Iterator10`2[System.Byte,System.String]
010204081020
Ab .NET 4.0 hat string.Concat eine Überladung, die IEnumerable akzeptiert. Daher wird der obige Code unter 4.0 für beide Variablen s und t die gleiche Ausgabe haben
010204081020
010204081020
Vor 4.0, ba.Select(b => b.ToString("X2"))
geht auf Überlastung (object arg0)
den Weg für die IEnumerable<string>
zu einer richtigen Überlastung zu kommen, d.h. (params string[] values)
ist, müssen wir die IEnumerable<string>
in ein String-Array. Vor 4.0 hat string.Concat 10 Überladungsfunktionen, in 4.0 sind es jetzt 12
Hier ist eine andere Methode:
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;
}
Alternativ können Sie die Übersetzungstabelle auch wie folgt vorbereiten, um noch schnellere Ergebnisse zu erzielen:
Ich verwende gerne Erweiterungsmethoden für Konvertierungen wie diese, auch wenn sie nur Standardbibliotheksmethoden umhüllen. Im Fall von Hexadezimal-Konvertierungen verwende ich die folgende, von Hand angepasste (d. h., schnell ) Algorithmen:
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;
}
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.