Go语言中从文件中读取可变行结束符的行

kyks70gy  于 2022-12-30  发布在  Go
关注(0)|答案(2)|浏览(141)

如何从一个行结束符为回车符(CR)、换行符(NL)或两者都有的文件中读取行?
PDF规范允许行以CR、LF或CRLF结尾。

  • bufio.Reader.ReadString()bufio.Reader.ReadBytes()允许单个定界符字节。
  • bufio.Scanner.Scan()处理可选地在\r之前的\n,而不是单独的\r

行尾标记是一个可选的回车符,后跟一个强制的换行符。
我是否需要编写自己的使用bufio.Reader.ReadByte()的函数?

shyt4zoc

shyt4zoc1#

您可以为bufio.Scanner编写自定义bufio.SplitFunc。例如:

// Mostly bufio.ScanLines code:
func ScanPDFLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
    if atEOF && len(data) == 0 {
        return 0, nil, nil
    }
    if i := bytes.IndexAny(data, "\r\n"); i >= 0 {
        if data[i] == '\n' {
            // We have a line terminated by single newline.
            return i + 1, data[0:i], nil
        }
        advance = i + 1
        if len(data) > i+1 && data[i+1] == '\n' {
            advance += 1
        }
        return advance, data[0:i], nil
    }
    // If we're at EOF, we have a final, non-terminated line. Return it.
    if atEOF {
        return len(data), data, nil
    }
    // Request more data.
    return 0, nil, nil
}

像这样使用它:

scan := bufio.NewScanner(r)
scan.Split(ScanPDFLines)
vdgimpew

vdgimpew2#

当我阅读一个旧的Mac生成的文件,只有CR行结束时,我遇到了一个边缘情况,如果CRLF被分割到缓冲区边界,可接受的答案会将它们视为单独的行结束符。如果缓冲区以CR结尾,你基本上需要提前退出并请求更多的数据。

func scanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
    if atEOF && len(data) == 0 {
        return 0, nil, nil
    }
    if i := bytes.IndexAny(data, "\r\n"); i >= 0 {
        if data[i] == '\n' {
            // We have a line terminated by single newline.
            return i + 1, data[0:i], nil
        }
        // We have a line terminated by carriage return at the end of the buffer.
        if !atEOF && len(data) == i+1 {
            return 0, nil, nil
        }
        advance = i + 1
        if len(data) > i+1 && data[i+1] == '\n' {
            advance += 1
        }
        return advance, data[0:i], nil
    }
    // If we're at EOF, we have a final, non-terminated line. Return it.
    if atEOF {
        return len(data), data, nil
    }
    // Request more data.
    return 0, nil, nil
}

相关问题