将字符串转换为 byte[] 创建零字符

Posted

技术标签:

【中文标题】将字符串转换为 byte[] 创建零字符【英文标题】:Converting string to byte[] creates zero character 【发布时间】:2012-12-20 08:25:24 【问题描述】:

在这个转换函数中

public 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;


byte[] test = GetBytes("abc");

结果数组包含零个字符

test = [97, 0, 98, 0, 99, 0]

当我们将 byte[] 转换回字符串时,结果是

string test = "a b c "

我们如何使它不会产生那些零

【问题讨论】:

当您将字符复制到字节数组中时,您似乎故意创建了这些零。您想要哪种编码? ASCII? UTF-8? Return file download from byte[]的可能重复 ToCharArray,顾名思义,返回 char[]。一个 char 是 16 位,即 2 个字节。因此,即使对于简单的 ASCII 文本,您也会得到一个值为 0 的附加字节。 @strike_noir 看看我更新的答案。 【参考方案1】:

首先让我们看看你的代码做错了什么。 char 是 .NET 框架中的 16 位(2 字节)。这意味着当您编写sizeof(char) 时,它会返回2str.Length1,所以实际上你的代码将是 byte[] bytes = new byte[2] 是相同的 byte[2]。因此,当您使用Buffer.BlockCopy() 方法时,实际上是将2 字节从源数组复制到目标数组。这意味着如果您的字符串为" ",您的GetBytes() 方法将返回bytes[0] = 32bytes[1] = 0

尝试改用Encoding.ASCII.GetBytes()

当在派生类中被覆盖时,对所有字符进行编码 将指定的字符串转换成字节序列。

const string input = "Soner Gonul";

byte[] array = Encoding.ASCII.GetBytes(input);

foreach ( byte element in array )

     Console.WriteLine("0 = 1", element, (char)element);

输出:

83 = S
111 = o
110 = n
101 = e
114 = r
32 =
71 = G
111 = o
110 = n
117 = u
108 = l

【讨论】:

【参考方案2】:

为了消除您对答案的困惑,C# 中的 char 类型需要 2 个字节。因此,string.toCharArray() 返回一个数组,其中每个项目占用 2 个字节的存储空间。在复制到每个项目占用 1 个字节存储空间的字节数组时,会发生数据丢失。因此,结果中出现零。 正如建议的那样,Encoding.ASCII.GetBytes 是一个更安全的选择。

【讨论】:

没有数据丢失,它实际上和Encoding.Unicode.GetBytes一样,编码为UTF16 Little Endian。【参考方案3】:

实际上.net(至少对于 4.0)在使用 BinaryWriter 序列化时会自动更改 char 的大小

UTF-8 字符有可变长度(可能不是 1 个字节),ASCII 字符有 1 个字节

'ē' = 2 个字节

'e' = 1 字节

使用时一定要牢记

BinaryReader.ReadChars(stream)

如果单词 "ēvalds" = 7 字节大小将不同于 "evalds" = 6 字节

【讨论】:

"UTF-8 字符有 2 个字节"... 什么? UTF-8 是一种可变长度编码。【参考方案4】:

(97,0) 是 'a' 的 Unicode 表示。 Unicode 以两个字节表示每个字符。所以你不能删除零。但是您可以将编码更改为 ASCII。尝试以下将字符串转换为字节[]。

byte[] array = Encoding.ASCII.GetBytes(input);

【讨论】:

【参考方案5】:

尝试明确指定Encoding。您可以使用下一个代码将字符串转换为具有指定编码的字节

byte[] bytes = System.Text.Encoding.ASCII.GetBytes("abc");

如果您打印字节的内容,您将得到不包含零的 97, 98, 99 ,如您的示例所示 在您的示例中,每个符号使用 16 位的默认编码。可以通过打印

的结果来成为观察者
System.Text.Encoding.Unicode.GetBytes("abc"); //  97, 0, 98, 0, 99, 0 

然后在转换回来的时候,你应该选择合适的编码:

string str = System.Text.Encoding.ASCII.GetString(bytes);
Console.WriteLine (str);

如您预期的那样打印"abc"

【讨论】:

或者使用 Unicode 编码从他从 GetBytes 获得的内容转换回来:string str = System.Text.Encoding.Unicode.GetString(bytes); 然后它也应该适用于非 Ascii。尽管如此,您仍应始终指定编码方式:byte[] bytes = System.Text.Encoding.Unicode.GetBytes("abc"); 请注意,如果您打算进行网络和切换字节序或使用 C# 以外的其他语言,则默认的 UnicodeEncoding 是小端。

以上是关于将字符串转换为 byte[] 创建零字符的主要内容,如果未能解决你的问题,请参考以下文章

java文件转码后,每行后面多了很多零字符

byte怎么转换为char

c#怎么把byte数组转换成图像

c#怎么把byte数组转换为字符串

java怎么将string转换成byte数组

如何把一个byte数组的数字转换成int