【问题标题】:Converting String to Byte Array and vice versa将字符串转换为字节数组,反之亦然
【发布时间】:2019-01-09 14:00:23
【问题描述】:

将字符串转换为字节数组然后再改回来有时不会返回相同的字符串:

RandomNumberGenerator gen = new RNGCryptoServiceProvider();
byte[] randomBytes = new byte[32];
gen.GetBytes(randomBytes);

在某些情况下(或除 unicode 之外的任何类型的编码):

randomBytes != Encoding.Unicode.GetBytes(Encoding.Unicode.GetString(randomBytes));

我想知道如何执行此方法并获得相同的结果肯定。 提前致谢

【问题讨论】:

  • 真的使用!=比较字节数组吗?

标签: c# encoding


【解决方案1】:

您可能不是在寻找文本编码,而是在寻找序列化格式。文本编码适用于文本。您正在处理的字节是随机字节。

Base64 (Convert.ToBase64String) 是否适合您?

您也可以将字节塞入字符 (new string(myBytes.Select(b => (char)b).ToArray()))。这将产生容易被其他系统破坏的不可读字符串。可能不是正确的道路。

【讨论】:

  • Convert.ToBase64String 返回一个字符串。我需要将字符串转换为 byte[] 并返回。我正在使用NetworkStream 类来传输字符串,它需要一个字节[]。
  • @idotalker 为什么要使用字符串?你有字节,你想要字节。直接发送字节。如果您的协议是基于文本的,那么您可能需要使用 bas64 转到字符串,然后使用 UTF8 等编码转到字节。这将适用于随机数据。没有 base64 就不会。
  • 我想我可能有点不清楚。这篇文章中的示例不是我正在使用的代码,我编写它是为了表明Encoding.Unicode.GetBytes(Encoding.Unicode.GetString(randomBytes)) 有时会与randomBytes 不同。我不想使用随机数据。我的输入是一个字符串,我需要用NetworkStream 发送。是这样的:input(string) => encryption => Send (NetworkStream),然后是Recieve (NetworkStream) => decryption => put string to use。 byte[] 运行良好,但由于Encoding 对其进行了更改,因此解密不起作用。
  • 为什么不能完全用字节操作?根本没有字符串。无论如何,加密不会对文本进行操作。它对字节进行操作。 @idotalker 我的观点不依赖于随机数据。我的观点是,如果您有任意字节,则无法使用编码从它们中生成文本。
【解决方案2】:

任意字节数组不必编码 有效 Unicode 字符串(详见https://en.wikipedia.org/wiki/UTF-16),例如

  byte[] before = new byte[] { 0xA6, 0xDD };
  byte[] after = Encoding.Unicode.GetBytes(Encoding.Unicode.GetString(before));

  if (!before.SequenceEqual(after))
    Console.Write(string.Join(Environment.NewLine,
      $"before: {string.Join(" ", before.Select(b => b.ToString("x2")))}",
      $"after:  {string.Join(" ", after.Select(b => b.ToString("x2")))}"));

结果:

before: a6 dd
after:  fd ff

如果你想生成这些字符串,你可以将你的代码修改成

while (true) {
  using (RandomNumberGenerator gen = new RNGCryptoServiceProvider()) {
    byte[] randomBytes = new byte[32];
    gen.GetBytes(randomBytes);

    byte[] after = Encoding.Unicode.GetBytes(Encoding.Unicode.GetString(randomBytes));

    if (!randomBytes.SequenceEqual(after)) {
      Console.Write(string.Join(" ", randomBytes) + 
                    Environment.NewLine + 
                    string.Join(" ", after));

      break;
    }
  }
}

可能的结果:

166 8 99 175 188 233 240 219 64 143 26 87 157 209 205 219 27 169 239 67 99 170 172 226 254 56 168 168 64 222 178 15
166 8 99 175 188 233 253 255 64 143 26 87 157 209 253 255 27 169 239 67 99 170 172 226 254 56 168 168 253 255 178 15
                     ^
                     Difference

请注意,我们应该将数组与SequenceEqual 进行比较。

如果你想编码一个数组,你可以在string.Join的帮助下完成:

byte[] array = ...

// Something like "166 8 99 175 188 233 240 219 ... 64 222 178 15"
string encoded = string.Join(" ", array);

byte[] back = encoded
  .Split(' ')
  .Select(item => byte.Parse(item))
  .ToArray();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多