如何在.NET(C#)中将字符串转换为字节[]而不手动指定特定编码?
我要加密字符串。我可以在不进行转换的情况下对其进行加密,但我仍然想知道为什么编码会在这里发挥作用。
此外,为什么还要考虑编码?我不能简单地获取字符串存储的字节数吗?为什么依赖字符编码?
如何在.NET(C#)中将字符串转换为字节[]而不手动指定特定编码?
我要加密字符串。我可以在不进行转换的情况下对其进行加密,但我仍然想知道为什么编码会在这里发挥作用。
此外,为什么还要考虑编码?我不能简单地获取字符串存储的字节数吗?为什么依赖字符编码?
当前回答
为了证明Mehrrad的声音回答有效,他的方法甚至可以持久化未配对的代理字符(其中许多人对我的答案持反对态度,但每个人都有同样的错误,例如System.Text.Encoding.UTF8.GetBytes、System.Text.Encding.Unicode.GetBytes;例如,这些编码方法不能持久化高代理字符d800,而这些方法只是用值fffd替换高代理字符):
using System;
class Program
{
static void Main(string[] args)
{
string t = "爱虫";
string s = "Test\ud800Test";
byte[] dumpToBytes = GetBytes(s);
string getItBack = GetString(dumpToBytes);
foreach (char item in getItBack)
{
Console.WriteLine("{0} {1}", item, ((ushort)item).ToString("x"));
}
}
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;
}
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);
}
}
输出:
T 54
e 65
s 73
t 74
? d800
T 54
e 65
s 73
t 74
尝试使用System.Text.Encoding.UTF8.GetBytes或System.Text.Encding.Unicode.GetBytes,它们只会用值fffd替换高代理项字符
每当这个问题发生变化时,我仍然在想一个序列化程序(无论是来自Microsoft还是来自第三方组件),它可以持久化字符串,即使它包含不成对的代理字符;我时不时地在谷歌上搜索这个:序列化不成对的代理角色.NET。这不会让我失眠,但偶尔有人评论我的答案,说它有缺陷,但他们的答案在不成对的替代角色方面同样有缺陷,这让我很烦。
Darn,Microsoft应该在BinaryFormatter中使用System.Buffer.BlockCopyツ
谢谢!
其他回答
byte[] strToByteArray(string str)
{
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
return enc.GetBytes(str);
}
对于串行通信项目,我必须将字符串转换为字节数组-我必须处理8位字符,而且我无法找到使用框架转换器的方法,这样既不会添加两个字节条目,也不会错误地转换具有第八位集的字节。所以我做了以下工作:
string message = "This is a message.";
byte[] bytes = new byte[message.Length];
for (int i = 0; i < message.Length; i++)
bytes[i] = (byte)message[i];
试试这个,代码更少:
System.Text.Encoding.UTF8.GetBytes("TEST String");
其他人已经回答了您问题的第一部分(如何获取字节):查看System.Text.Encoding命名空间。
我将回答您的后续问题:为什么需要选择编码?为什么不能从字符串类本身获得这些信息?
答案分为两部分。
首先,字符串类内部使用的字节并不重要,只要假设它们存在,就可能引入错误。
如果您的程序完全在.Net世界中,那么您根本不需要担心获取字符串的字节数组,即使您正在通过网络发送数据。相反,请使用.Net Serialization来担心数据传输问题。您不再担心实际的字节数:Serialization格式化程序会为您提供。
另一方面,如果您将这些字节发送到某个无法保证将从.Net序列化流中提取数据的地方,该怎么办?在这种情况下,您确实需要担心编码问题,因为显然,这个外部系统关心编码问题。同样,字符串使用的内部字节无关紧要:您需要选择一种编码,以便在接收端明确该编码,即使它与.Net内部使用的编码相同。
我理解,在这种情况下,您可能更希望在可能的情况下使用字符串变量存储在内存中的实际字节,这样可以节省创建字节流的工作量。然而,我告诉你,与确保输出在另一端被理解,并保证编码必须明确相比,这并不重要。此外,如果您真的想匹配内部字节,您可以只选择Unicode编码,从而节省性能。
这让我进入第二部分。。。选择Unicode编码就是告诉.Net使用底层字节。您确实需要选择这种编码,因为当一些新的Unicode Plus问世时,.Net运行时需要自由使用这种更新、更好的编码模型,而不会破坏您的程序。但是,目前(以及可预见的未来),只要选择Unicode编码就可以满足您的需要。
理解字符串必须重写为线也是很重要的,即使使用匹配的编码,也至少需要对位模式进行一些转换。计算机需要考虑诸如Big vs Little Endian、网络字节顺序、分组化、会话信息等。
公认的答案非常非常复杂。为此,请使用包含的.NET类:
const string data = "A string with international characters: Norwegian: ÆØÅæøå, Chinese: 喂 谢谢";
var bytes = System.Text.Encoding.UTF8.GetBytes(data);
var decoded = System.Text.Encoding.UTF8.GetString(bytes);
如果你不需要。。。