5

我正在尝试编写一个函数来继续从缓冲读取器读取,直到我遇到某个字符串,然后停止读取并返回在该字符串之前读取的所有内容。

换句话说,我想做和做一样的事情reader.ReadString(),除了用一个字符串而不是一个字节。

例如:

mydata, err := reader.ReadString("\r\n.\r\n") //obviously will not compile

我怎样才能做到这一点?

提前致谢,

特威奇

修正 1:先前的尝试

这是我之前的尝试;它写得不好并且不起作用,但希望它证明了我正在尝试做的事情。

func readDotData(reader *bufio.Reader)(string, error){
delims := []byte{ '\r', '\n', '.', '\r', '\n'}
curpos := 0
var buffer []byte
for {
    curpos = 0
    data, err := reader.ReadSlice(delims[0])
    if err!=nil{ return "", err }
    buffer = append(buffer, data...)
    for {
        curpos++
        b, err := reader.ReadByte()
        if err!=nil{ return "", err }
        if b!=delims[curpos]{
            for curpos >= 0{
                buffer = append(buffer, delims[curpos])
                curpos--
            }
            break
        }
        if curpos == len(delims){
            return string(buffer[len(buffer)-1:]), nil
        }
    }
}
panic("unreachable")
}
4

4 回答 4

11
package main

import (
        "bytes"
        "fmt"
        "log"
)

type reader interface {
        ReadString(delim byte) (line string, err error)
}

func read(r reader, delim []byte) (line []byte, err error) {
        for {
                s := ""
                s, err = r.ReadString(delim[len(delim)-1])
                if err != nil {
                        return
                }

                line = append(line, []byte(s)...)
                if bytes.HasSuffix(line, delim) {
                        return line[:len(line)-len(delim)], nil
                }
        }
}

func main() {
        src := bytes.NewBufferString("123deli456elim789delimABCdelimDEF")
        for {
                b, err := read(src, []byte("delim"))
                if err != nil {
                        log.Fatal(err)
                }

                fmt.Printf("%q\n", b)
        }
}

操场


输出:

"123deli456elim789"
"ABC"
2009/11/10 23:00:00 EOF
于 2013-07-29T08:23:25.830 回答
3

http://play.golang.org/p/BpA5pOc-Rn

package main

import (
    "bytes"
    "fmt"
)

func main() {
    b := bytes.NewBuffer([]byte("Hello, playground!\r\n.\r\nIrrelevant trailer."))
    c := make([]byte, 0, b.Len())
    for {
        p := b.Bytes()
        if bytes.Equal(p[:5], []byte("\r\n.\r\n")) {
            fmt.Println(string(c))
            return
        }
        c = append(c, b.Next(1)...)

    }
}
于 2013-07-29T08:42:50.310 回答
2

例如,

package main

import (
    "bufio"
    "bytes"
    "fmt"
    "strings"
)

var delim = []byte{'\r', '\n', '.', '\r', '\n'}

func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
    if atEOF && len(data) == 0 {
        return 0, nil, nil
    }
    for i := 0; i+len(delim) <= len(data); {
        j := i + bytes.IndexByte(data[i:], delim[0])
        if j < i {
            break
        }
        if bytes.Equal(data[j+1:j+len(delim)], delim[1:]) {
            // We have a full delim-terminated line.
            return j + len(delim), data[0:j], nil
        }
        i = j + 1
    }
    // 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
}

func main() {
    delims := string(delim)
    input := "1234" + delims + "5678" + delims + "1234567901234567890" + delims
    scanner := bufio.NewScanner(strings.NewReader(input))
    scanner.Split(ScanLines)
    for scanner.Scan() {
        fmt.Printf("%s\n", scanner.Text())
    }
    if err := scanner.Err(); err != nil {
        fmt.Printf("Invalid input: %s", err)
    }
}

输出:

1234
5678
1234567901234567890
于 2013-07-29T06:54:31.033 回答
0

因为你在字符串中有相同的字节,你可以这样做:

func readWithEnd(reader *bufio.Reader) ([]byte, error) {
    message, err := reader.ReadBytes('#')
    if err != nil {
        return nil, err
    }

    a1, err := reader.ReadByte()
    if err != nil {
        return nil, err
    }
    message = append(message, a1)
    if a1 != '\t' {
        message2, err := readWithEnd(reader)
        if err != nil {
            return nil, err
        }
        ret := append(message, message2...)
        return ret, nil
    }

    a2, err := reader.ReadByte()
    if err != nil {
        return nil, err
    }
    message = append(message, a2)
    if a2 != '#' {
        message2, err := readWithEnd(reader)
        if err != nil {
            return nil, err
        }
        ret := append(message, message2...)
        return ret, nil
    }
    return message, nil
}

这是可以识别"#\t#"TCP 连接的示例

于 2017-07-28T09:30:13.693 回答