【问题标题】:How to convert a base64 string of bytes to Float32 or Float64?如何将 base64 字节字符串转换为 Float32 或 Float64?
【发布时间】:2019-06-07 20:15:23
【问题描述】:

我正在尝试将 VTK (vtu) XML 格式文件从 base64 二进制字符串转换为 ASCII 字符串。文件看起来有点像这样:

<Points>
    <DataArray type="Float32" NumberOfComponents="3" format="binary">
`gJQGAGp7+sJTMbPCVWiWv4RP+8LbKrTCj0yDv1kC+8J5w7PCUe0xv34YAMNqprTCtsRDv7yw/8IgdLTCUE0lv/8 (etc...)
    </DataArray>
</Points>

您也可以将这些文件保存为 ASCII 格式,因此在 ASCII 中看起来是这样的:

<Points>
    <DataArray type="Float32" Name="Points" NumberOfComponents="3" format="ascii" RangeMin="9.6120050431" RangeMax="280.36424584">
      -125.24104309 -89.596336365 -1.1750589609 -125.65530396 -90.083702087 -1.0257738829
      -125.50458527 -89.881782532 -0.69502741098 -128.09567261 -90.325027466 -0.7647203207
      -127.84518433 -90.226806641 -0.64571094513 -128.24607849 -90.475311279 -0.61999017
      (etc...)
    </DataArray>
</Points>

我需要我的代码在文件以 ASCII 或二进制形式出现时工作,因此我需要能够将第一种情况下的 base64 字符串转换为第二种情况下的 ASCII 格式。

现在我有:

string pointString = nodeList[0].ChildNodes.Item(0).InnerText.Trim();
if(format.Equals("binary", StringComparison.InvariantCultureIgnoreCase))
{
    byte[] bytes = Convert.FromBase64String(pointString);
    pointString = Encoding.ASCII.GetString(bytes);
}

aa而且我的字符串全错了:

pointString: ?$

我觉得我在这里遗漏了一些简单的东西。我哪里错了?

【问题讨论】:

  • 您的“二进制”字节数组包含构成float 数字的字节(float 又名System.Single = 32 位浮点数;字节数组中每4 个字节构成一个@ 987654327@ 值)。如果所有这些字节只是float 数字的组成部分,是什么让你认为你必须将此字节数组解码为 ASCII 字符串?显然 32 位浮点数的 4 个字节与任何 ASCII 字符都没有关系。你是从哪里得到这个想法的?
  • 这很有趣。你能发布一个完整的base64字符串吗?答案可能是专有的。这可能与 .NET 二进制序列化完全无关。 VTK 有一些 nuget 包。

标签: c# .net base64 ascii bitconverter


【解决方案1】:

尝试将字节直接转换为浮点数并检查是否产生有效结果:

byte[] bytes = Convert.FromBase64String(pointString);
float[] dataArray = Enumerable.Range(0, bytes.length / 4).Select(i => BitConverter.ToSingle(bytes, i * 4)).ToArray();

【讨论】:

  • 您可以用一个 Buffer.BlockCopy 调用替换 Enumerable.Range.Select 混乱。它也会更快。
  • @BenVoigt 这似乎不是一个改进 - 您需要预先分配 dataArray 并沿一些索引复制。不那么凌乱。
  • @NetMage:预分配比从一个可枚举的流式传输要好得多,它会多次扩展缓冲区。仅仅因为代码.ToArray() 很短并不意味着它是有效的。即使它检查 Range 是否具有预先已知的 Length 并进行预分配,它仍然会使用 lambda 计算索引并调用 BitConverter 数百次,这也没有效率。
  • @BenVoigt ToArrayToList 相比效率低下,但数百次似乎有些夸张。即使没有,时间也很难与从 Base64 转换为二进制读取 XML 文件相比。对我来说,这一切似乎都是过早的优化。
  • @NetMage:您可能会注意到,在我最初的评论中,改进的性能只是一个脚注。主要优点是Buffer.BlockCopy 使代码更简单。这不是“计算结束索引,生成索引,在源数组中找到相应的字节,转换它们,然后流到一个新数组中”,而只是“计算项数,分配新数组,复制数据”。 var dataArray = new float[bytes.Length / sizeof(float)]; Buffer.BlockCopy(bytes, 0, dataArray, 0, bytes.Length); 更短的代码,概念上更简单,操作更少。
猜你喜欢
  • 2016-10-21
  • 1970-01-01
  • 1970-01-01
  • 2016-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-02
  • 2012-07-21
相关资源
最近更新 更多