如何在.NET(C#)中将字符串转换为字节[]而不手动指定特定编码?
我要加密字符串。我可以在不进行转换的情况下对其进行加密,但我仍然想知道为什么编码会在这里发挥作用。
此外,为什么还要考虑编码?我不能简单地获取字符串存储的字节数吗?为什么依赖字符编码?
如何在.NET(C#)中将字符串转换为字节[]而不手动指定特定编码?
我要加密字符串。我可以在不进行转换的情况下对其进行加密,但我仍然想知道为什么编码会在这里发挥作用。
此外,为什么还要考虑编码?我不能简单地获取字符串存储的字节数吗?为什么依赖字符编码?
当前回答
以下是我的String-to-Byte[]转换的不安全实现:
public static unsafe Byte[] GetBytes(String s)
{
Int32 length = s.Length * sizeof(Char);
Byte[] bytes = new Byte[length];
fixed (Char* pInput = s)
fixed (Byte* pBytes = bytes)
{
Byte* source = (Byte*)pInput;
Byte* destination = pBytes;
if (length >= 16)
{
do
{
*((Int64*)destination) = *((Int64*)source);
*((Int64*)(destination + 8)) = *((Int64*)(source + 8));
source += 16;
destination += 16;
}
while ((length -= 16) >= 16);
}
if (length > 0)
{
if ((length & 8) != 0)
{
*((Int64*)destination) = *((Int64*)source);
source += 8;
destination += 8;
}
if ((length & 4) != 0)
{
*((Int32*)destination) = *((Int32*)source);
source += 4;
destination += 4;
}
if ((length & 2) != 0)
{
*((Int16*)destination) = *((Int16*)source);
source += 2;
destination += 2;
}
if ((length & 1) != 0)
{
++source;
++destination;
destination[0] = source[0];
}
}
}
return bytes;
}
它比公认的anwser要快得多,即使没有它那么优雅。以下是我在10000000次迭代中的秒表基准:
[Second String: Length 20]
Buffer.BlockCopy: 746ms
Unsafe: 557ms
[Second String: Length 50]
Buffer.BlockCopy: 861ms
Unsafe: 753ms
[Third String: Length 100]
Buffer.BlockCopy: 1250ms
Unsafe: 1063ms
为了使用它,您必须在项目构建财产中勾选“允许不安全代码”。根据.NET Framework 3.5,此方法也可以用作字符串扩展:
public static unsafe class StringExtensions
{
public static Byte[] ToByteArray(this String s)
{
// Method Code
}
}
其他回答
// C# to convert a string to a byte array.
public static byte[] StrToByteArray(string str)
{
System.Text.ASCIIEncoding encoding=new System.Text.ASCIIEncoding();
return encoding.GetBytes(str);
}
// C# to convert a byte array to a string.
byte [] dBytes = ...
string str;
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
str = enc.GetString(dBytes);
最接近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的答案。所以,如果你无论如何都要转换。。。为什么不“编码”?
OP的问题:“如何在.NET(C#)中将字符串转换为字节数组?”
您可以使用以下代码:
static byte[] ConvertString (string s) {
return new byte[0];
}
作为一个好处,编码无关紧要!哦,等等,这是一个ecoding。。。它只是微不足道的,而且损耗很大。
bytes[] buffer = UnicodeEncoding.UTF8.GetBytes(string something); //for converting to UTF then get its bytes
bytes[] buffer = ASCIIEncoding.ASCII.GetBytes(string something); //for converting to ascii then get its bytes
可以使用以下代码将字符串转换为.NET中的字节数组
string s_unicode = "abcéabc";
byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(s_unicode);