如何在C#中获得字符串的一致字节表示,而无需手动指定编码?

2364

在.NET (C#)中,如何将string转换为byte[]而不手动指定特定的编码?

我要对这个字符串进行加密。我可以不进行转换就进行加密,但我仍然想知道为什么编码在这里起作用。

此外,为什么需要考虑编码?我不能简单地获取字符串存储在哪些字节中吗?为什么存在字符编码的依赖关系?


30
每个字符串都是以字节数组的形式存储的,对吗?那我为什么不能直接拿到这些字节呢? - Agnel Kurian
149
编码是将字符映射到字节的过程。例如,在ASCII编码中,字母'A'映射到数字65。在不同的编码中可能会有所不同。不过,在.NET框架中采用的字符串高级处理方法使这个问题基本上不重要,除了这种情况。 - Lucas Jones
23
作为一名“魔鬼的代言人”,假设您想要获取一个存在内存中的字符串的字节(就像.NET使用它们一样),并对它们进行某些操作(例如CRC32),而且永远不需要将其解码回原始字符串...那么您为什么要关心编码以及如何选择使用哪种编码方式,这并不是一件简单的事情。 - Greg
88
很惊讶还没有人给出这个链接: http://www.joelonsoftware.com/articles/Unicode.html(注:该链接为一篇关于Unicode编码的文章) - Bevan
36
一个字符不等于一个字节,一个字节也不等于一个字符。字符既是字体表中的关键,也是语法传统中的一部分。字符串是字符序列。(词语、段落、句子和标题也有自己的语法传统,需要定义相应的类型--但我偏离了主题)。像整数、浮点数和其他所有数据类型一样,字符被编码成字节。曾经有一段时间,字符的编码是简单的一对一映射:ASCII码。然而,为了包含人类所有符号,一个字节的256种排列组合是不足够的,所以设计了多种编码方式以有选择地使用更多的字节。 - George
显示剩余23条评论
41个回答

1949

与此处的答案相反,如果字节不需要被解释,你就无需担心编码!

就像您提到的那样,您的目标很简单,就是“获取字符串存储在哪些字节中”,
(当然,也要能够从这些字节重新构建字符串。)

对于这些目标,我真的不明白为什么人们一直告诉您需要使用编码。对于这一点,您确实不需要担心编码。

只需执行以下操作即可:

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);
}
只要您的程序(或其他程序)不尝试以某种方式“解释”这些字节,而您显然没有提到您打算这样做,那么这种方法就是完全正确的!担心编码只会为您增加更多不必要的复杂性。

此方法的另一个好处是:无论字符串是否包含无效字符,都不会有问题,因为您仍然可以获取数据并重新构建原始字符串!

它将被编码和解码,因为您只是查看字节。

如果使用了特定的编码,则在对无效字符进行编码/解码时将会出现问题。


277
这个代码的问题在于,GetStringGetBytes 需要在相同字节顺序(endianness)的系统上执行才能正常工作。所以你不能使用它来获取想要转换为字符串的字节,然后在其他地方使用。因此,我很难想出什么情况下会想要使用它。 - CodesInChaos
73
就像我之前所说的,这个方法的重点是,如果你想在同样类型的系统上使用它,并且使用相同的功能集合。如果不是这种情况,那么你就不应该使用它。 - user541686
219
我保证会有一些人(他们不理解字节和字符的区别)想要将他们的字符串转换成字节数组,他们会搜索并阅读这个答案,然后他们会做错事情,因为在几乎所有情况下,编码是相关的。 - artbristol
437
如果他们懒得读答案(或其他答案……),那我很抱歉,我就没有更好的方式与他们沟通了。通常我选择回答提问者而不是猜测其他人可能会如何使用我的答案——提问者有权知道,仅仅因为某人可能会滥用刀子并不意味着我们需要为自己隐藏全世界的刀子。不过如果你持不同意见也没关系。 - user541686
205
这个答案在很多层面上都是错误的,但最主要的错误在于它声明了“你不需要担心编码!”。GetBytes 和 GetString 这两种方法是多余的,因为它们只是重新实现了 Encoding.Unicode.GetBytes() 和 Encoding.Unicode.GetString() 已经实现的功能。而且声明“只要你的程序(或其他程序)不尝试解释这些字节”也基本上是错误的,因为这暗示着这些字节应该被解释为 Unicode。 - David
显示剩余106条评论

1144

这取决于您的字符串编码(ASCIIUTF-8等)。

例如:

byte[] b1 = System.Text.Encoding.UTF8.GetBytes (myString);
byte[] b2 = System.Text.Encoding.ASCII.GetBytes (myString);

一个小例子说明为什么编码很重要:

string pi = "\u03a0";
byte[] ascii = System.Text.Encoding.ASCII.GetBytes (pi);
byte[] utf8 = System.Text.Encoding.UTF8.GetBytes (pi);

Console.WriteLine (ascii.Length); //Will print 1
Console.WriteLine (utf8.Length); //Will print 2
Console.WriteLine (System.Text.Encoding.ASCII.GetString (ascii)); //Will print '?'

ASCII无法处理特殊字符。

在内部,.NET框架使用UTF-16表示字符串,因此如果您只想获取.NET使用的确切字节,请使用System.Text.Encoding.Unicode.GetBytes(...)

有关更多信息,请参见.NET Framework中的字符编码(MSDN)。


16
为什么需要考虑编码?我不能只获取字节而不必关注所使用的编码吗?即使需要关注,字符串对象本身难道不应该知道正在使用的编码并简单地转储内存中的内容吗? - Agnel Kurian
67
.NET的字符串始终以Unicode编码。因此,使用System.Text.Encoding.Unicode.GetBytes();获取一组字节,这是.NET用于表示字符的方式。但是,你为什么需要它呢?我建议使用UTF-8,特别是在大多数字符都属于西方拉丁字符集时。 - AnthonyWJones
9
另外,如果检索这些字节的系统不处理该编码或将其处理为错误的编码,则字符串内部使用的确切字节实际上并不重要。如果所有操作都在 .Net 内部进行,那么根本不需要将其转换为字节数组。否则,最好明确指定编码。 - Joel Coehoorn
13
@Joel,小心使用System.Text.Encoding.Default,因为它在每台计算机上的运行可能不同。这就是为什么建议始终指定一个编码,比如UTF-8。 - Ash
27
除非你(或其他人)打算实际“解释”数据而不是将其视为通用的“字节块”,否则你不需要编码。对于像压缩、加密等的操作,担心编码是没有意义的。参见我的回答中的一种方法,可以在不担心编码的情况下完成此操作。(如果我说了你不需要担心编码并且你还是这样做了,也许我会给你一个负分,但今天我不想这么刻薄 :P) - user541686
显示剩余13条评论

305

接受的答案非常复杂。使用包含的.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);

如果不必要,就不要重复造轮子...


17
如若被采纳的答案发生变化,为了记录目的,目前接受的答案是Mehrdad在当前时间和日期给出的答案。希望问题提出者能够重新查看,并接受更好的解决方案。 - Thomas Eding
9
原则上不错,但编码应该是 System.Text.Encoding.Unicode 才能与 Mehrdad 的答案等效。 - Jodrell
7
原问题被编辑了无数次,所以我的答案可能有点过时。我从未打算提供Mehrdad答案的完全等价,而是提供一种明智的方式来解决问题。但是,你可能是对的。然而,在原始问题中,“获取字符串存储在哪些字节中”这个短语非常不准确。存储在哪里?在内存中?在磁盘上?如果在内存中,System.Text.Encoding.Unicode.GetBytes可能会更精确。 - Erik A. Brandstadmoen
8
@AMissico,你的建议有缺陷,除非你确定你的字符串与你的系统默认编码兼容(即在你的系统默认遗留字符集中只包含ASCII字符的字符串)。但是没有地方提到这一点。 - Frédéric
6
它可能导致程序在不同的系统上产生不同的结果,这是绝对不好的。即使是用于生成哈希值或其他加密操作(我猜这就是“encrypt”所指的意思),相同的字符串应该始终生成相同的哈希值。 - Nyerguds
显示剩余4条评论

121
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());

2
你可以使用同一个 BinaryFormatter 实例来执行所有这些操作。 - Joel Coehoorn
3
非常有趣。显然,它将删除任何高代理项Unicode字符。请参阅[BinaryFormatter]的文档。 - user334911

105

这是一个常见的问题。重要的是要理解问题作者所询问的内容,它与最常见的需求不同。为了防止在不需要的情况下滥用代码,我首先回答了后者。

最常见的需求

每个字符串都有字符集和编码。当您将System.String对象转换为System.Byte数组时,仍然会存在字符集和编码。对于大多数用途,您应该知道需要哪种字符集和编码,并且.NET使得“带转换复制”变得简单。只需选择适当的Encoding类即可。

// using System.Text;
Encoding.UTF8.GetBytes(".NET String to byte array")

转换可能需要处理这样的情况:目标字符集或编码不支持源中存在的某个字符。你有几种选择:异常、替换或跳过。默认策略是用问号'?'替换。

// using System.Text;
var text = Encoding.ASCII.GetString(Encoding.ASCII.GetBytes("You win €100")); 
                                                      // -> "You win ?100"

显然,转换不一定是无损的!

注意:对于System.String,源字符集是Unicode。

唯一令人困惑的是,.NET使用字符集的名称来命名该字符集的一个特定编码。应将Encoding.Unicode称为Encoding.UTF16

对于大多数用途,就是这样了。如果您需要的是这个,请停止阅读。如果您不理解编码是什么,请参见有趣的Joel Spolsky文章

特殊需求

现在,问题的作者问道:“每个字符串都存储为字节数组,对吧?我为什么不能简单地获取这些字节?”

他不想进行任何转换。

根据C#规范

C#中的字符和字符串处理使用Unicode编码。char类型表示UTF-16代码单元,string类型表示UTF-16代码单元序列。

因此,我们知道如果我们请求空转换(即从UTF-16到UTF-16),我们将得到所需的结果:

Encoding.Unicode.GetBytes(".NET String to byte array")

但是为了避免提及编码,我们必须另寻他法。如果可以接受中间数据类型,那么有一个概念上的捷径:

".NET String to byte array".ToCharArray()

这不能得到我们想要的数据类型,但是Mehrdad's answer显示了如何使用BlockCopy将此Char数组转换为Byte数组。但是,这将字符串复制两次!而且,它还显式使用编码特定代码:数据类型System.Char

获取String存储的实际字节的唯一方法是使用指针。 fixed语句允许取地址。来自C#规范:

对于string类型的表达式,...初始值计算字符串中第一个字符的地址。

为此,编译器编写了代码,跳过字符串对象的其他部分,使用RuntimeHelpers.OffsetToStringData。因此,要获得原始字节,只需创建指向字符串的指针并复制所需字节数。

// using System.Runtime.InteropServices
unsafe byte[] GetRawBytes(String s)
{
    if (s == null) return null;
    var codeunitCount = s.Length;
    /* We know that String is a sequence of UTF-16 code units 
       and such code units are 2 bytes */
    var byteCount = codeunitCount * 2; 
    var bytes = new byte[byteCount];
    fixed(void* pRaw = s)
    {
        Marshal.Copy((IntPtr)pRaw, bytes, 0, byteCount);
    }
    return bytes;
}

正如 @CodesInChaos 指出的那样,结果取决于机器的字节序。但问题作者并不关心这个。


4
没问题,但是字符串长度已经给出了码元数量(而不是码点)。 - Tom Blodget
1
感谢您指出问题!来自MSDN的内容:“Length属性[的String]返回该实例中Char对象的数量,而不是Unicode字符的数量。”因此,您的示例代码编写正确。 - Jan Hettich
2
唉,正确的答案虽然晚了几年,但永远不会像被接受的那样得到那么多的投票。由于太长不看,人们会认为被接受的答案很棒。只需复制粘贴并点赞即可。 - Martin Capodici
1
@GerardONeill 感谢反馈。根据C#规范,.NET字符串是UTF-16代码单元的计数序列。一个码点由一个或多个代码单元编码。在UTF-16的情况下,这是一个或两个。当有两个时,它们是“高”代理和“低”代理。因此,codeunitcount * 2是代码单元的正确字节数。该代码根本不计算码点。 - Tom Blodget
1
@TomBlodget:你不需要使用 fixedunsafe 代码,也可以这样做:var gch = GCHandle.Alloc("foo", GCHandleType.Pinned); var arr = new byte[sizeof(char) * ((string)gch.Target).Length]; Marshal.Copy(gch.AddrOfPinnedObject(), arr, 0, arr.Length); gch.Free(); - user541686
显示剩余8条评论

100

7
“1个字符可以由1个或多个字节表示”。 我同意。我只想获取那些字节,无论字符串使用什么编码方式。字符串在内存中的唯一存储方式就是以字节为单位。即使字符本身也会以1个或多个字节的形式存储。我只是想获得这些字节。 - Agnel Kurian
17
除非您(或其他人)实际上打算解释数据,而不是将其视为通用“字节块”,否则您不需要编码。 对于像压缩,加密等这样的事情,担心编码是没有意义的。请参阅[我的答案](https://dev59.com/mXRB5IYBdhLWcg3w6LR2#10380166),以了解如何在不担心编码的情况下执行此操作。 - user541686
10
@Mehrdad - 完全正确,但原始问题在我最初回答时并没有限定OP在将这些字节转换后会发生什么,对于未来的搜索者,围绕这一点的信息是相关的 - 这在Joel's answer中得到很好的涵盖,正如你在你的答案中所述:只要你坚持使用.NET世界,并使用你的方法进行转换,你就会很满意。一旦你走出这个范围,编码就会很重要。 - Zhaph - Ben Duguid
1
一个 代码点 最多可以由 4 个字节表示。(一个UTF-32代码单元,一个UTF-16代理对或4个UTF-8字节。)需要超过4个字节的UTF-8值超出了Unicode的0x0..0x10FFFF范围。;-) - DevSolar

53
你的问题的第一部分(如何获取字节)已经被其他人回答了:查看 System.Text.Encoding 命名空间。
我将回答你的后续问题:为什么需要选择编码?为什么不能从字符串类本身获取?
答案有两个部分。
首先,字符串类内部使用的字节并不重要,每当你假设它们很重要时,你都可能会引入一个 bug。
如果你的程序完全在 .Net 世界中,则根本不需要担心获取字符串的字节数组,即使你正在通过网络发送数据。相反,使用 .Net 序列化来处理传输数据。你不再需要关心实际的字节:序列化格式化程序会替你完成这项工作。
另一方面,如果你正在将这些字节发送到某个地方,而你无法保证该地方会从 .Net 序列化流中提取数据,那么你肯定需要关心编码,因为显然,这个外部系统会关心。所以,字符串使用的内部字节并不重要:你需要选择一个编码,以便在接收端明确指定此编码,即使它是 .Net 内部使用的相同编码。
我知道在这种情况下,你可能更愿意在可能的情况下使用存储在内存中的字符串变量的实际字节,以便节省创建字节流的一些工作。然而,我告诉你,与确保你的输出在另一端被理解相比,这并不重要,要保证这一点,你必须明确地使用编码。此外,如果你真的想匹配你的内部字节,你已经可以选择 Unicode 编码,并获得那些性能上的优势。

这使我想到了第二部分...选择Unicode编码就是告诉 .Net 使用底层的字节。你确实需要选择这个编码,因为当某种新奇的 Unicode-Plus 出现时,.Net 运行时需要自由地使用这种更新、更好的编码模型而不会破坏您的程序。但是,目前(和可预见的未来),只需选择 Unicode 编码即可获得所需的结果。

另外,重要的是要理解,即使您使用匹配的编码,您的字符串也必须被重新编写成二进制数据,并且这至少涉及一些位模式的转换。计算机需要考虑到一些问题,如大端和小端、网络字节顺序、数据封装、会话信息等。


11
在.NET中,有些地方需要将字符串转换为字节数组。许多.NET加密类包含像ComputeHash()这样的方法,接受字节数组或数据流。您必须首先将字符串转换为字节数组(选择编码方式),然后可以选择将其包装在数据流中。但是,只要选择了一个编码方式(如UTF8)并坚持使用它,就不会出现问题。 - Ash
2
当我不知道编码是什么并因懒惰而拒绝学习时,我和OP的心情一模一样(只要给我字节就好了...)。你的答案是第一个(在顶部之中)关心给出清晰警告的。我只是高兴地在我的电脑上写和读二进制文件......直到我不得不处理MAC/Linux用户、网络、将应用程序升级到最新的操作系统、更好地理解字节序,以及自定义编码(电子ROM和数据)。当.Net使用4个字节对Unicode进行编码,UTF8最多使用8个字节的那一天,我通过艰难的方式学会了尽可能避免绕过本机方法。 - Karl Stephen
@Luaan:我不认为这是愚蠢的,只是以忽略其他人为代价的高效。我说过,为什么不使用更多标准化字符的Unicode64(可能包括一个covid字符)? 我仍然相信选择是关键:提供Unicode扩展更新,但也要保持编码的活力。 不幸的是,最近的操作系统倾向于减少对编码的支持,特别是在移动设备上。出于这个原因,我支持这个答案:对你的字符串数据进行编码并指定所使用的编码方式,这是安全和高效的方法。这确实意味着每个开发者都应该学习编码...但现在还没有到达那一步。 - Karl Stephen

47

仅为证明Mehrdrad的声音answer有效,他的方法甚至可以持久化unpaired surrogate characters(许多人曾对我的回答提出过反对意见,但所有人都同样有罪,例如System.Text.Encoding.UTF8.GetBytesSystem.Text.Encoding.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.GetBytesSystem.Text.Encoding.Unicode.GetBytes,它们仅会用值为 fffd 的字符替换高代理项字符。
每次这个问题有所变化时,我仍然在考虑一个序列化器(无论是来自 Microsoft 还是第三方组件),它可以持久化字符串,即使它包含未成对的代理项字符;我经常搜索此内容:serialization unpaired surrogate character .NET。这并没有让我失眠,但每隔一段时间就有人评论我的答案有缺陷,然而当涉及到未成对的代理项字符时,他们的答案同样存在缺陷。
该死的,Microsoft 应该在其 BinaryFormatter 中使用 System.Buffer.BlockCopy
谢谢!

4
代理对不是必须成对出现才能组成有效的代码点吗?如果是这样的话,我可以理解为什么数据会变得混乱。 - dtanders
2
@dtanders 是的,这也是我的想法,它们必须成对出现,如果你故意将它们放在字符串上并使它们不成对,那么就会发生不成对代理字符。我不知道的是为什么其他开发人员一直强调我们应该使用编码感知方法,因为他们认为序列化方法(我的答案,已经被接受超过3年)不能保持不成对代理字符的完整性。但他们忘记了检查他们的编码感知解决方案也无法保持不成对代理字符的完整性,这真是讽刺啊 ツ - Michael Buen
1
如果有一个序列化库内部使用 System.Buffer.BlockCopy,那么所有编码倡导者的争论都将毫无意义。 - Michael Buen
3
@MichaelBuen 我认为主要问题在于你用大而粗的字体说某些事情不重要,而不是说在他们的情况下这并不重要。结果,你鼓励那些查看你答案的人犯基本的编程错误,这将会给未来的其他人带来困扰。在字符串中,未配对的代理项是无效的。它不是一个字符数组,因此将字符串转换为另一种格式会导致该字符上出现错误“FFFD”。如果你想进行手动字符串操作,请使用char[],这是推荐的方法。 - Trisped
4
一个System.String是由不可变的字符序列组成;.NET一直允许从任何Char[]构造一个String对象,并将其内容导出到一个包含相同值的Char[]中,即使原始的Char[]中包含不配对的代理项。 - supercat
显示剩余3条评论

42

试试这个,代码更少:

System.Text.Encoding.UTF8.GetBytes("TEST String");

1
然后尝试这个 System.Text.Encoding.UTF8.GetBytes("Árvíztűrő tükörfúrógép");,并且哭泣!它会工作,但是 System.Text.Encoding.UTF8.GetBytes("Árvíztűrő tükörfúrógép").Length != System.Text.Encoding.UTF8.GetBytes("Arvizturo tukorfurogep").Length"Árvíztűrő tükörfúrógép".Length == "Arvizturo tukorfurogep".Length - mg30rg
9
为什么你认为你的例子很奇怪?在变宽编码中,不是所有字符都具有相同的字节长度。有什么问题吗? - Vlad

26

我已经阅读了所有答案,它们都是关于使用编码或者一个关于序列化删除无法配对的代理项。

当字符串来自存储例如密码哈希的字节数组的地方(比如来自SQL Server),如果我们删除任何内容,它将会存储一个无效的哈希值。如果我们想要将其存储在XML中,我们需要将其保持完整(因为XML writer在发现任何未配对的代理项时都会抛出异常)。

因此,在这种情况下,我使用字节数组的Base64编码。但是在互联网上,只有一种C#的解决方案,并且其中存在错误,并且只有一种方法,所以我修复了该错误并编写了回传过程。这里是给未来的Googlers:

public static byte[] StringToBytes(string str)
{
    byte[] data = new byte[str.Length * 2];
    for (int i = 0; i < str.Length; ++i)
    {
        char ch = str[i];
        data[i * 2] = (byte)(ch & 0xFF);
        data[i * 2 + 1] = (byte)((ch & 0xFF00) >> 8);
    }

    return data;
}

public static string StringFromBytes(byte[] arr)
{
    char[] ch = new char[arr.Length / 2];
    for (int i = 0; i < ch.Length; ++i)
    {
        ch[i] = (char)((int)arr[i * 2] + (((int)arr[i * 2 + 1]) << 8));
    }
    return new String(ch);
}

不必使用自定义方法将字节数组转换为base64,您只需要使用内置的转换器即可:Convert.ToBase64String(arr); - Makotosan
@Makotosan 谢谢你,但是我已经使用了 Convert.ToBase64String(arr); 来进行 base64 转换 byte[] (data) <-> string (serialized data to store in XML file)。但是为了获取初始的 byte[] (data),我需要对包含二进制数据的 String 进行一些操作(这是 MSSQL 返回给我的方式)。因此,上面的函数是用于 String (binary data) <-> byte[] (easy accessible binary data) - Gman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接