在Go中读取带有BOM的文件
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Go中读取带有BOM的文件相关的知识,希望对你有一定的参考价值。
我需要读取可能包含或不包含字节顺序标记的Unicode文件。我当然可以自己检查文件的前几个字节,如果找到则丢弃BOM。但在此之前,有没有任何标准的方法可以做到这一点,无论是在核心库还是第三方?
答案
没有标准的方式,IIRC(标准库实际上是一个错误的层来实现这样的检查)所以这里有两个例子,你可以自己处理它。
一种是在数据流上方使用缓冲读取器:
import (
"bufio"
"os"
"log"
)
func main() {
fd, err := os.Open("filename")
if err != nil {
log.Fatal(err)
}
defer closeOrDie(fd)
br := bufio.NewReader(fd)
r, _, err := br.ReadRune()
if err != nil {
log.Fatal(err)
}
if r != 'uFEFF' {
br.UnreadRune() // Not a BOM -- put the rune back
}
// Now work with br as you would do with fd
// ...
}
另一种与实现io.Seeker
接口的对象一起工作的方法是读取前三个字节,如果它们不是BOM,则io.Seek()
回到开头,如:
import (
"os"
"log"
)
func main() {
fd, err := os.Open("filename")
if err != nil {
log.Fatal(err)
}
defer closeOrDie(fd)
bom := [3]byte
_, err = io.ReadFull(fd, bom[:])
if err != nil {
log.Fatal(err)
}
if bom[0] != 0xef || bom[1] != 0xbb || bom[2] != 0xbf {
_, err = fd.Seek(0, 0) // Not a BOM -- seek back to the beginning
if err != nil {
log.Fatal(err)
}
}
// The next read operation on fd will read real data
// ...
}
这是可能的,因为*os.File
(os.Open()
回归)的实例支持寻求并因此实施io.Seeker
。请注意,对于HTTP响应的Body
读者而言,情况并非如此,因为您无法“回放”它。 bufio.Buffer
通过执行一些缓冲(显然)来解决这个不可寻找的流的特征 - 这就是允许你对它进行UnreadRune()
的原因。
请注意,这两个示例都假设我们正在处理的文件是以UTF-8编码的。如果您需要处理其他(或未知)编码,事情会变得更复杂。
另一答案
在Go核心包中没有标准的方法。遵循Unicode标准。
Unicode Byte Order Mark (BOM) FAQ
另一答案
你可以使用utfbom包。它包装io.Reader
,检测并丢弃必要的BOM。它还可以返回BOM检测到的编码。
以上是关于在Go中读取带有BOM的文件的主要内容,如果未能解决你的问题,请参考以下文章