我正在尝试在 Go 中实现 PPM 解码器。PPM 是一种图像格式,由纯文本标题和一些二进制图像数据组成。标头看起来像这样(来自规范):
每个 PPM 映像包含以下内容:
- 用于识别文件类型的“幻数”。ppm 图像的幻数是两个字符“P6”。
- 空格(空格、TAB、CR、LF)。
- 宽度,格式为十进制的 ASCII 字符。
- 空白。
- 高度,同样是 ASCII 十进制。
- 空白。
- 最大颜色值 (Maxval),同样以 ASCII 十进制表示。必须小于 65536 且大于零。
- 单个空白字符(通常是换行符)。
我尝试使用该fmt.Fscanf
函数解码此标头。以下调用
fmt.Fscanf
解析标头(不解决下面解释的警告):
var magic string
var width, height, maxVal uint
fmt.Fscanf(input,"%2s %d %d %d",&magic,&width,&height,&maxVal)
国家的文件fmt
:
注意:
Fscan
etc. 可以在它们返回的输入之后读取一个字符(符文),这意味着调用扫描例程的循环可能会跳过一些输入。仅当输入值之间没有空格时,这通常是一个问题。如果 reader 提供给Fscan
implementsReadRune
,该方法将用于读取字符。如果读者也实现了UnreadRune
,该方法将用于保存字符并且连续调用不会丢失数据。要将ReadRune
和UnreadRune
方法附加到没有该功能的阅读器,请使用bufio.NewReader
.
fmt.Fscanf
由于最后一个空格之后的下一个字符已经是图像数据的开头,我必须确定读取后消耗了多少空格MaxVal
。我的代码必须在调用者提供的任何阅读器上工作,并且它的部分内容不得超过标头的末尾,因此将内容包装到缓冲阅读器中不是一种选择;缓冲阅读器从输入中读取的内容可能比我实际想要阅读的内容更多。
一些测试表明,最后解析一个虚拟字符可以解决问题:
var magic string
var width, height, maxVal uint
var dummy byte
fmt.Fscanf(input,"%2s %d %d %d%c",&magic,&width,&height,&maxVal,&dummy)
可以保证按照规范工作吗?