如何在.NET(C#)中将字符串转换为字节[]而不手动指定特定编码?

我要加密字符串。我可以在不进行转换的情况下对其进行加密,但我仍然想知道为什么编码会在这里发挥作用。

此外,为什么还要考虑编码?我不能简单地获取字符串存储的字节数吗?为什么依赖字符编码?


当前回答

对于串行通信项目,我必须将字符串转换为字节数组-我必须处理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];

其他回答

从字节[]到字符串:

        return BitConverter.ToString(bytes);

如果您真的想要一个字符串的基本字节的副本,可以使用下面这样的函数。然而,你不应该继续阅读以找出原因。

[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()

OP的问题:“如何在.NET(C#)中将字符串转换为字节数组?”

您可以使用以下代码:

static byte[] ConvertString (string s) {
    return new byte[0];
}

作为一个好处,编码无关紧要!哦,等等,这是一个ecoding。。。它只是微不足道的,而且损耗很大。

最快的方式

public static byte[] GetBytes(string text)
{
    return System.Text.ASCIIEncoding.UTF8.GetBytes(text);
}

编辑正如Makotosan所说,这是现在最好的方式:

Encoding.UTF8.GetBytes(text)

最接近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的答案。所以,如果你无论如何都要转换。。。为什么不“编码”?