【问题标题】:Javascript Equvivalant to BinaryReader.ReadString() from C#Javascript 等效于 C# 中的 BinaryReader.ReadString()
【发布时间】:2022-10-23 22:55:06
【问题描述】:

我正在将一些 C# 代码转换为 JavaScript 代码,虽然此文件具有多种数据类型,并且我在跨库的 Javascrip 中找到了匹配的功能,但我无法在 JS 中找到一个特定的功能。

那个函数是https://learn.microsoft.com/en-us/dotnet/api/system.io.binaryreader.readstring?view=net-7.0

我有几个问题:

  1. 首先让我感到困惑的是,字符串本身不是可变长度变量吗?如果是这样,这个函数怎么能不接受长度参数?
  2. 让我们假设字符串的长度有一些上限。如果有,JS/TS 有没有类似的功能?或者我可以下载以模仿 C# 功能的任何包?

    先感谢您。

【问题讨论】:

  • 它看起来就像一个readable stream 和一个DataView 在一起?这是在浏览器中还是在 Node.js 中?
  • “从当前流中读取字符串。字符串以长度为前缀,编码为整数,一次七位。”
  • 从链接:“从当前流中读取一个字符串。该字符串以长度为前缀,一次编码为一个整数七位。"
  • @caTS 它是一个浏览器。
  • 看着@OliverWeichhold 和poul 的答案,我知道可变长度不是问题,只要JS 可以完成这项工作。现在的问题是 JS 能做到这一点吗?

标签: javascript c# typescript


【解决方案1】:

BinaryReader 期望字符串以特定格式编码 - 格式 BinaryWriter 写入它们。如文档中所述:

从当前流中读取一个字符串。字符串前缀为 长度,编码为整数,一次七位

所以字符串的长度存储在字符串本身之前,编码为“一次七位整数”。我们可以从BinaryWriter.Write7BitEncodedInt获得更多信息:

value 参数的整数在 a 处写出 7 位 时间,从七个最低有效位开始。高位 一个字节表示在此之后是否还有更多字节要写入 一。

如果值适合七位,则只占用一个字节的空间。如果 值不适合七位,高位设置在第一个 字节并写出。然后将值移动七位,然后下一个 字节被写入。重复这个过程,直到整个整数 被写了。

所以它是可变长度编码:不像通常的方法总是使用 4 个字节作为 Int32 值,这种方法使用可变字节数。这样,短字符串的长度可以少于 4 个字节(例如,长度小于 128 个字节的字符串只需要 1 个字节)。

您可以在 javascript 中重现此逻辑 - 一次只读取一个字节,最低 7 位存储(部分)长度信息,最高位指示下一个字节是否也存储长度信息。

然后当你得到长度时 - 使用TextDecoder 将字节数组解码为给定编码的字符串。这是打字稿中的相同功能。它接受缓冲区(Uint8Array),偏移到该缓冲区和编码(默认为 UTF-8,检查 TextDecoder 的文档以获取其他可用编码):

class BinaryReader {
  getString(buffer: Uint8Array, offset: number, encoding: string = "utf-8") {
      let length = 0; // length of following string
      let cursor = 0;
      let nextByte: number;
      do {
          // just grab next byte
          nextByte = buffer[offset + cursor];          
          // grab 7 bits of current byte, then shift them according to this byte position
          // that is if that's first byte - do not shift, second byte - shift by 7, etc
          // then merge into length with or.
          length = length | (nextByte & 0x7F) << (cursor * 7);          
          cursor++;
      }
      while (nextByte >= 0x80); // do this while most significant bit is 1

      // get a slice of the length we got
      let sliceWithString = buffer.slice(offset + cursor, length);      
      let decoder = new TextDecoder(encoding);      
      return decoder.decode(sliceWithString);
  }
}

如果将在生产中使用,则值得在上面的代码中添加各种健全性检查(我们不会读取太多字节的读取长度,计算的长度实际上是在缓冲区的范围内等)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-27
    • 2018-01-02
    • 2013-10-30
    • 2016-05-10
    • 1970-01-01
    • 1970-01-01
    • 2013-07-10
    • 1970-01-01
    相关资源
    最近更新 更多