Unicode 读取BOM处于Go状态的文件

Unicode 读取BOM处于Go状态的文件,unicode,go,byte-order-mark,Unicode,Go,Byte Order Mark,我需要读取可能包含或不包含字节顺序标记的Unicode文件。当然,我可以自己检查文件的前几个字节,如果找到BOM表,就丢弃它。但在此之前,在核心库或第三方中是否有任何标准方法可以做到这一点?在Go core软件包中没有标准方法可以做到这一点。遵循Unicode标准 没有标准的方法,IIRC(而标准库对于实现这样的检入来说确实是一个错误的层),所以这里有两个例子说明您可以自己处理它 一种是在数据流上方使用缓冲读取器: import ( "bufio" "os" "log"

我需要读取可能包含或不包含字节顺序标记的Unicode文件。当然,我可以自己检查文件的前几个字节,如果找到BOM表,就丢弃它。但在此之前,在核心库或第三方中是否有任何标准方法可以做到这一点?

在Go core软件包中没有标准方法可以做到这一点。遵循Unicode标准

没有标准的方法,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.Seek
接口的对象,即读取前三个字节,如果它们不是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
reader不是这样,因为您不能“倒带”它
bufio.Buffer
通过执行一些缓冲(显然)来解决不可查找流的这一特性,这就是允许您对其执行
UnreadRune()


请注意,这两个示例都假设我们正在处理的文件是用UTF-8编码的。如果您需要处理其他(或未知)编码,事情会变得更加复杂。

您可以使用软件包。它包装io.Reader,根据需要检测并丢弃BOM。它还可以返回BOM检测到的编码。

我想在这里添加从字符串中剥离字节顺序标记的方法,而不是直接处理字节(如上所示)

其他“字符串”函数也应该起作用

这是打印出来的:

before: ' is a string that starts with a Byte Order Mark (len=50)'
Found leading Byte Order Mark sequence!
after: ' is a string that starts with a Byte Order Mark (len=47)'

干杯

如果我自己生成所有文件和流,我当然会严格遵循Unicode标准。但和世界上的许多人一样,我一直在使用其他人生成的数据。bufio方法奏效了,我喜欢它将BOM视为单个符文而不是一组字节。@kostix cloud您解释了如何在第二种方法中推导条件吗?。Thanks@Anuruddha,对不起,我没有分析你的问题,特别是“导出条件”部分,这似乎是必要的。想详细说明一下吗?可能在几句话中。@kostix您使用bom[0]的条件!=0xef | |物料清单[1]!=0xbb | |物料清单[1]!=0xbf@Anuruddha不,UTF-8编码的BOM是具有特定顺序的特定值的三个字节,因此逻辑是“如果序列中的任何字节在该位置具有其不得具有的值,则这不是BOM”。
before: ' is a string that starts with a Byte Order Mark (len=50)'
Found leading Byte Order Mark sequence!
after: ' is a string that starts with a Byte Order Mark (len=47)'