首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scodec -用固定长度的字符串读取

Scodec -用固定长度的字符串读取
EN

Stack Overflow用户
提问于 2021-07-02 13:21:50
回答 1查看 81关注 0票数 0

我正在编写一个文件解析器,它读取包含固定长度、0填充字符串的现有文件格式。

因此,例如,我在我需要解析的文件中有两个二进制结构的case类。第一个包含一个4个字符的字符串,可以是两个值中的一个,后者包括一个8个字符串(其中值长度小于8个字符是NUL填充的)。

代码语言:javascript
复制
case class WadHeader( magic : String, items : Int, dirOffset : Int)
case class LumpIndex( offset : Int, size : Int, lumpName : String)

我尝试编写一个简单的编解码器来解析第一个代码:

代码语言:javascript
复制
  implicit val headerCodec : Codec[WadHeader] = {
    ("magic" | bytes(4)) ::
      ("items" | uint32) ::
      ("dirOffset" | uint32)
  }.as[WadHeader]

但是,我发现它无法成功地将其转换为WadHeader (大概是因为神奇的值与案例类定义不完全匹配)。我希望能够摄取一个固定大小的字节字符串,并将其解码为string对象。

不幸的是,浏览文档只会出现“贪婪”字符串或大小前缀字符串选项。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-07-03 03:56:07

好的-所以我想出了一个可行的解决方案。也许有一种更简单、更干净的方法可以做到这一点,但效果很好。

首先,当我预先知道长度时,我定义了一个用于字符串读取的新的fixedString编解码器:

代码语言:javascript
复制
  def fixedString(size: Int): Codec[String] = new Codec[String] {
    private val codec = fixedSizeBytes(size, ascii)
    def sizeBound: SizeBound = SizeBound.exact(size * 8L)
    def encode(b: String): Attempt[BitVector] = codec.encode(b)
    def decode(b: BitVector): Attempt[DecodeResult[String]] = {
      codec.decode(b) match {
        case Successful(DecodeResult(value, remainder)) =>
          val decoded = value.toSeq.takeWhile(_>0).mkString

          Attempt.successful(DecodeResult(decoded, remainder))
        case fail : scodec.Attempt.Failure => fail
      }
    }
    override def toString = s"fixedString($size)"
  }

这对绳子有用。第二个错误只是我自己犯的一个愚蠢的错误(uint32解码为一个长的,而不是Int),它要求我相应地更新我的案例类定义:

代码语言:javascript
复制
case class WadHeader( magic : String, items : Long, dirOffset : Long)

object WadHeader {
  implicit val codec : Codec[WadHeader] = {
    ("magic" | fixedString(4)) ::
      ("items" | uint32) ::
      ("dirOffset" | uint32)
  }.as[WadHeader]
}

编辑: 5/7 -指出我可以包装fixedSizeCodec(size, ascii)而不是bytes,它完成了我想要的大部分工作,并相应地更新了解决方案。根据需求的不同,fixedSizeCodec(size, cstring)也可能是一个很好的解决方案--但是对于使用完整字段长度的字符串,我的用例失败了,因为没有终止nul的空间。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68225957

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档