如何在.NET(C#)中将字符串转换为字节[]而不手动指定特定编码?
我要加密字符串。我可以在不进行转换的情况下对其进行加密,但我仍然想知道为什么编码会在这里发挥作用。
此外,为什么还要考虑编码?我不能简单地获取字符串存储的字节数吗?为什么依赖字符编码?
如何在.NET(C#)中将字符串转换为字节[]而不手动指定特定编码?
我要加密字符串。我可以在不进行转换的情况下对其进行加密,但我仍然想知道为什么编码会在这里发挥作用。
此外,为什么还要考虑编码?我不能简单地获取字符串存储的字节数吗?为什么依赖字符编码?
当前回答
与这里的答案相反,如果不需要解释字节,则不需要担心编码!
正如您提到的,您的目标很简单,就是“获取字符串存储的字节数”。(当然,还要能够根据字节重新构造字符串。)
对于这些目标,我真的不明白为什么人们总是告诉你你需要编码。你当然不需要担心编码。
只需执行以下操作:
static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
// Do NOT use on arbitrary bytes; only use on GetBytes's output on the SAME system
static string GetString(byte[] bytes)
{
char[] chars = new char[bytes.Length / sizeof(char)];
System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
return new string(chars);
}
只要你的程序(或其他程序)不试图以某种方式解释字节,而你显然没有提到你打算这样做,那么这种方法就没有错!担心编码只会让你的生活变得更加复杂,没有真正的原因。
这种方法的额外好处:字符串是否包含无效字符无关紧要,因为您仍然可以获取数据并重建原始字符串!
它将以相同的方式进行编码和解码,因为您只是在查看字节。
但是,如果您使用特定的编码,则会给您带来编码/解码无效字符的麻烦。
其他回答
由于以下事实,字符串可以通过几种不同的方式转换为字节数组:.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? :-)
如果您真的想要一个字符串的基本字节的副本,可以使用下面这样的函数。然而,你不应该继续阅读以找出原因。
[DllImport(
"msvcrt.dll",
EntryPoint = "memcpy",
CallingConvention = CallingConvention.Cdecl,
SetLastError = false)]
private static extern unsafe void* UnsafeMemoryCopy(
void* destination,
void* source,
uint count);
public static byte[] GetUnderlyingBytes(string source)
{
var length = source.Length * sizeof(char);
var result = new byte[length];
unsafe
{
fixed (char* firstSourceChar = source)
fixed (byte* firstDestination = result)
{
var firstSource = (byte*)firstSourceChar;
UnsafeMemoryCopy(
firstDestination,
firstSource,
(uint)length);
}
}
return result;
}
这个函数会很快地得到字符串下面的字节的副本。您将以任何方式在系统上编码这些字节。这种编码几乎可以肯定是UTF-16LE,但这是一个您不必关心的实现细节。
打电话会更安全、更简单、更可靠,
System.Text.Encoding.Unicode.GetBytes()
这很可能会产生相同的结果,更容易键入,字节将往返,Unicode中的字节表示也可以,调用
System.Text.Encoding.Unicode.GetString()
// 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);
BinaryFormatter bf = new BinaryFormatter();
byte[] bytes;
MemoryStream ms = new MemoryStream();
string orig = "喂 Hello 谢谢 Thank You";
bf.Serialize(ms, orig);
ms.Seek(0, 0);
bytes = ms.ToArray();
MessageBox.Show("Original bytes Length: " + bytes.Length.ToString());
MessageBox.Show("Original string Length: " + orig.Length.ToString());
for (int i = 0; i < bytes.Length; ++i) bytes[i] ^= 168; // pseudo encrypt
for (int i = 0; i < bytes.Length; ++i) bytes[i] ^= 168; // pseudo decrypt
BinaryFormatter bfx = new BinaryFormatter();
MemoryStream msx = new MemoryStream();
msx.Write(bytes, 0, bytes.Length);
msx.Seek(0, 0);
string sx = (string)bfx.Deserialize(msx);
MessageBox.Show("Still intact :" + sx);
MessageBox.Show("Deserialize string Length(still intact): "
+ sx.Length.ToString());
BinaryFormatter bfy = new BinaryFormatter();
MemoryStream msy = new MemoryStream();
bfy.Serialize(msy, sx);
msy.Seek(0, 0);
byte[] bytesy = msy.ToArray();
MessageBox.Show("Deserialize bytes Length(still intact): "
+ bytesy.Length.ToString());
最快的方式
public static byte[] GetBytes(string text)
{
return System.Text.ASCIIEncoding.UTF8.GetBytes(text);
}
编辑正如Makotosan所说,这是现在最好的方式:
Encoding.UTF8.GetBytes(text)