如何在.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);
}
只要你的程序(或其他程序)不试图以某种方式解释字节,而你显然没有提到你打算这样做,那么这种方法就没有错!担心编码只会让你的生活变得更加复杂,没有真正的原因。
这种方法的额外好处:字符串是否包含无效字符无关紧要,因为您仍然可以获取数据并重建原始字符串!
它将以相同的方式进行编码和解码,因为您只是在查看字节。
但是,如果您使用特定的编码,则会给您带来编码/解码无效字符的麻烦。
其他回答
对于串行通信项目,我必须将字符串转换为字节数组-我必须处理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];
与这里的答案相反,如果不需要解释字节,则不需要担心编码!
正如您提到的,您的目标很简单,就是“获取字符串存储的字节数”。(当然,还要能够根据字节重新构造字符串。)
对于这些目标,我真的不明白为什么人们总是告诉你你需要编码。你当然不需要担心编码。
只需执行以下操作:
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);
}
只要你的程序(或其他程序)不试图以某种方式解释字节,而你显然没有提到你打算这样做,那么这种方法就没有错!担心编码只会让你的生活变得更加复杂,没有真正的原因。
这种方法的额外好处:字符串是否包含无效字符无关紧要,因为您仍然可以获取数据并重建原始字符串!
它将以相同的方式进行编码和解码,因为您只是在查看字节。
但是,如果您使用特定的编码,则会给您带来编码/解码无效字符的麻烦。
如果您真的想要一个字符串的基本字节的副本,可以使用下面这样的函数。然而,你不应该继续阅读以找出原因。
[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()
代码如下:
// Input string.
const string input = "Dot Net Perls";
// Invoke GetBytes method.
// ... You can store this array as a field!
byte[] array = Encoding.ASCII.GetBytes(input);
// Loop through contents of the array.
foreach (byte element in array)
{
Console.WriteLine("{0} = {1}", element, (char)element);
}
为了证明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ツ
谢谢!