如何在.NET(C#)中将字符串转换为字节[]而不手动指定特定编码?
我要加密字符串。我可以在不进行转换的情况下对其进行加密,但我仍然想知道为什么编码会在这里发挥作用。
此外,为什么还要考虑编码?我不能简单地获取字符串存储的字节数吗?为什么依赖字符编码?
如何在.NET(C#)中将字符串转换为字节[]而不手动指定特定编码?
我要加密字符串。我可以在不进行转换的情况下对其进行加密,但我仍然想知道为什么编码会在这里发挥作用。
此外,为什么还要考虑编码?我不能简单地获取字符串存储的字节数吗?为什么依赖字符编码?
当前回答
byte[] strToByteArray(string str)
{
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
return enc.GetBytes(str);
}
其他回答
byte[] strToByteArray(string str)
{
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
return enc.GetBytes(str);
}
我不确定,但我认为字符串将其信息存储为一个Chars数组,这对字节来说效率很低。具体来说,Char的定义是“表示Unicode字符”。
以以下示例为例:
String str = "asdf éß";
String str2 = "asdf gh";
EncodingInfo[] info = Encoding.GetEncodings();
foreach (EncodingInfo enc in info)
{
System.Console.WriteLine(enc.Name + " - "
+ enc.GetEncoding().GetByteCount(str)
+ enc.GetEncoding().GetByteCount(str2));
}
请注意,在这两种情况下,Unicode答案都是14个字节,而UTF-8答案第一种只有9个字节,第二种只有7个字节。
因此,如果您只想要字符串所使用的字节,只需使用Encoding.Unicode,但存储空间会很低。
由于以下事实,字符串可以通过几种不同的方式转换为字节数组:.NET支持Unicode,Unicode标准化了几种称为UTF的不同编码。它们具有不同长度的字节表示,但在这个意义上是等价的,即当字符串被编码时,它可以被编码回字符串,但如果字符串用一个UTF编码,并且在不同UTF的假设下解码,如果可能会出错。
此外,.NET支持非Unicode编码,但它们在一般情况下无效(只有在实际字符串(如ASCII)中使用有限的Unicode代码点子集时才有效)。在内部,.NET支持UTF-16,但对于流表示,通常使用UTF-8。它也是互联网的事实标准。
毫不奇怪,System.Text.Encoding类是一个抽象类,它支持将字符串序列化为字节数组和反序列化;它的派生类支持具体编码:ASCIIEncoding和四个UTF(System.Text.UnicodeEncoding支持UTF-16)
参考此链接。
对于使用System.Text.Encoding.GetBytes对字节数组进行序列化。对于反向操作,使用System.Text.Encoding.GGetChars。此函数返回字符数组,因此要获取字符串,请使用字符串构造函数System.string(char[])。请参阅本页。
例子:
string myString = //... some string
System.Text.Encoding encoding = System.Text.Encoding.UTF8; //or some other, but prefer some UTF is Unicode is used
byte[] bytes = encoding.GetBytes(myString);
//next lines are written in response to a follow-up questions:
myString = new string(encoding.GetChars(bytes));
byte[] bytes = encoding.GetBytes(myString);
myString = new string(encoding.GetChars(bytes));
byte[] bytes = encoding.GetBytes(myString);
//how many times shall I repeat it to show there is a round-trip? :-)
最接近OP问题的方法是Tom Blodget的,它实际上进入对象并提取字节。我说最接近,因为它取决于String对象的实现。
"Can't I simply get what bytes the string has been stored in?"
当然,但这就是问题的根本错误所在。String是一个可能具有有趣数据结构的对象。我们已经知道它确实存在,因为它允许存储未配对的代孕对象。它可能会存储长度。它可能会保持一个指针指向每一个“配对”的代孕者,以便快速计数。所有这些额外的字节都不是字符数据的一部分。
您需要的是数组中每个字符的字节。这就是“编码”的含义。默认情况下,您将获得UTF-16LE。如果您不关心字节本身,除了往返之外,那么您可以选择任何编码,包括“默认”,然后稍后将其转换回(假设相同的参数,例如默认编码、代码点、错误修复、允许的事情,例如未配对的代理等)。
但为什么要让“编码”变魔术呢?为什么不指定编码,以便知道将获得哪些字节?
"Why is there a dependency on character encodings?"
编码(在此上下文中)只是表示字符串的字节。不是字符串对象的字节。您需要字符串存储的字节——这是天真地问这个问题的地方。您希望字符串的字节位于表示字符串的连续数组中,而不是字符串对象可能包含的所有其他二进制数据。
这意味着字符串的存储方式无关紧要。您需要将字符串“编码”为字节数组中的字节。
我喜欢Tom Bloget的回答,因为他把你引向了“字符串对象的字节”的方向。但它依赖于实现,而且因为他在窥探内部,所以很难重建字符串的副本。
迈赫达德的回应是错误的,因为它在概念层面上具有误导性。您仍然有一个字节列表,已编码。他的特定解决方案允许保留未配对的代孕对象——这取决于实现。如果GetBytes默认以UTF-8格式返回字符串,他的特定解决方案将无法准确生成字符串的字节。
我已经改变了主意(Mehrad的解决方案)——这不是获取字符串的字节数;而是获取从字符串创建的字符数组的字节。无论编码如何,c#中的char数据类型都是固定大小。这允许生成一致长度的字节数组,并且允许基于字节数组的大小来再现字符数组。因此,如果编码是UTF-8,但每个字符都是6字节以容纳最大的utf8值,那么它仍然可以工作。所以事实上,字符的编码并不重要。
但是使用了转换——每个字符都放在一个固定大小的框中(c#的字符类型)。然而,这个表示是什么并不重要,从技术上来说,这是OP的答案。所以,如果你无论如何都要转换。。。为什么不“编码”?
要将字符串转换为字节[],请使用以下解决方案:
string s = "abcdefghijklmnopqrstuvwxyz";
byte[] b = System.Text.UTF32Encoding.GetBytes(s);
我希望这有帮助。