为什么't byte[] to string和back不能按预期工作?

本文关键字:不能按 back 工作 string to byte 为什么 | 更新日期: 2023-09-27 17:50:41

我有这样的代码:

Int32 i1 = 14000000;
byte[] b = BitConverter.GetBytes(i1);
string s = System.Text.Encoding.UTF8.GetString(b);
byte[] b2 = System.Text.Encoding.UTF8.GetBytes(s);
Int32 i2 = BitConverter.ToInt32(b2,0);;

i2等于-272777233。为什么它不是输入值?(14000000) ?

EDIT:我要做的是将其附加到另一个字符串,然后使用WriteAllText

为什么't byte[] to string和back不能按预期工作?

写入文件

因为Encoding类不会对任何事情都起作用。如果"字符"(在UTF-8的情况下可能是几个字节)在特定字符集(在您的情况下是UTF-8)中不是有效字符,它将使用替换字符

一个问号(U+003F)

(来源:http://msdn.microsoft.com/en-us/library/ms404377.aspx # FallbackStrategy)

在某些情况下,它只是一个?,例如在ASCII/CP437/ISO 8859-1中,但是有一种方法可以让您选择如何处理它。(见上面的链接)

例如,如果您尝试将(byte)128转换为ASCII:

string s = System.Text.Encoding.ASCII.GetString(new byte[] { 48, 128 }); // s = "0?"

然后转换回来:

byte[] b = System.Text.Encoding.ASCII.GetBytes(s); // b = new byte[] { 48, 63 }

您将而不是获得原始字节数组。

可以是引用:检查encoding

是否存在character

我无法想象为什么你需要将字节数组转换为字符串。这显然没有任何意义。假设你要写一个流,你可以直接写byte[]。如果您需要在某些文本表示中使用它,那么通过yourIntegerVar.ToString()将其转换为字符串并使用int.TryParse将其返回是完全有意义的。


编辑:

可以将字节数组写入文件,但您不打算将字节数组"连接"到字符串并使用惰性方法File.WriteAllText,因为它将处理编码转换,并且您可能最终在文件中出现问号?。相反,打开FileStream并使用FileStream.Write直接写入字节数组。或者,您可以使用BinaryWriter直接以二进制形式写入整数(也可以是字符串),并使用其对应的BinaryReader将其读取回来。

的例子:

FileStream fs;
fs = File.OpenWrite(@"C:'blah.dat");
BinaryWriter bw = new BinaryWriter(fs, Encoding.UTF8);
bw.Write((int)12345678);
bw.Write("This is a string in UTF-8 :)"); // Note that the binaryWriter also prefix the string with its length...
bw.Close();
fs = File.OpenRead(@"C:'blah.dat");
BinaryReader br = new BinaryReader(fs, Encoding.UTF8);
int myInt = br.ReadInt32();
string blah = br.ReadString(); // ...so that it can read it back.
br.Close();

这个示例代码将生成一个匹配以下hexdump的文件:

00  4e 61 bc 00 1c 54 68 69 73 20 69 73 20 61 20 73  Na¼..This is a s  
10  74 72 69 6e 67 20 69 6e 20 55 54 46 2d 38 20 3a  tring in UTF-8 :  
20  29                                               )   

请注意,BinaryWriter.Write(string)还将其长度作为字符串的前缀,并且在回读时取决于它的长度,因此不适合使用文本编辑器来编辑结果文件。(你写的是二进制形式的整数,所以我想这是可以接受的?)

您不应该使用Encoding.GetString任意二进制数据转换为字符串。该方法仅适用于使用特定编码编码为二进制数据的文本。

相反,您希望使用能够可逆地表示任意二进制数据的文本表示。最常见的两种方法是base64和十六进制。Base64是。net中最简单的:

string base64 = Convert.ToBase64String(originalBytes);
...
byte[] recoveredBytes = Convert.FromBase64String(base64);

需要注意的是:

  • 如果你想使用这个字符串作为URL参数,你应该使用一个web安全版本的base64;我不知道。net中是否直接支持这个,但是你可以很容易地找到解决方案
  • 如果你真的需要字符串格式的数据,你应该只做。如果您只是试图将其写入文件或类似的文件,最简单的方法是将其保存为二进制数据
  • Base64不是很容易读懂;如果您希望人们能够在没有额外工具的情况下读取文本形式的数据,请使用十六进制。(有各种各样的问题,特别是关于转换二进制数据十六进制和返回。)

无法工作,因为您使用的是反向编码。

编码用于将文本转换为字节,然后再转换回文本。你不能把任意字节转换成文本。每个字符都有对应的字节模式,但是每个字节模式并不能转换成字符。

如果你想用一种简洁的方式将字节表示为文本,请使用base-64编码:

Int32 i1 = 14000000;
byte[] b = BitConverter.GetBytes(i1);
string s = Convert.ToBase64String(b);
byte[] b2 = Convert.FromBase64String(s);
Int32 i2 = BitConverter.ToInt32(b2, 0);

如果您的目标是将整数存储为字符串,然后返回到整数,除非我遗漏了一些东西,否则以下内容不会足够:

int32 i1 = 1400000;
string s = il.ToString();
Int32 i2 = Int32.Parse(s);

长话短说:

您需要一个编码将每个字节值映射到一个唯一的字符,反之亦然。UTF8字符可以从1到4字节长,所以你不会存档映射,你需要一个更基本的编码,如ASCII。不幸的是,原来的ASCII没有这样做,它只是一个7位编码,只定义了较低的128个代码,上半部分(扩展代码)是特定的代码页。要获得全范围翻译,您只需要一个完整的8位编码,如代码页437或850或其他:

Int32 i1 = 14000000;
byte[] b = BitConverter.GetBytes(i1);
string s = System.Text.Encoding.GetEncoding(437).GetString(b);
byte[] b2 = System.Text.Encoding.GetEncoding(437).GetBytes(s);
Int32 i2 = BitConverter.ToInt32(b2,0);