Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 从读卡器读取,直到到达字符串为止_String_Go - Fatal编程技术网

String 从读卡器读取,直到到达字符串为止

String 从读卡器读取,直到到达字符串为止,string,go,String,Go,我正试图编写一个函数,以保持从缓冲读取器读取数据,直到命中某个字符串,然后停止读取并返回该字符串之前读取的所有内容 换句话说,我想做与reader.ReadString()相同的事情,不同的是使用字符串而不是单个字节 例如: mydata, err := reader.ReadString("\r\n.\r\n") //obviously will not compile 我该怎么做 提前感谢, 特维奇 修正案1:以前的尝试 这是我以前的尝试;它写得很糟糕,不起作用,但希望

我正试图编写一个函数,以保持从缓冲读取器读取数据,直到命中某个字符串,然后停止读取并返回该字符串之前读取的所有内容

换句话说,我想做与
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")
}
比如说,

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
"123deli456elim789"
"ABC"
2009/11/10 23:00:00 EOF


因为字符串中有相同的字节,所以可以按如下方式执行:

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
}

这个示例可以识别TCP连接中的
“#\t#”

很好的答案。我还没有发现append变量的用法。它真的很有用。(对于其他还不知道这一点的人)只需指出,这个答案不是很有效,因为您正在将所有内容读入内存
p:=b.Bytes()
。内存方面,它只是在某种程度上比同样的操作、转换为字符串和执行字符串查找更有效。我喜欢您实现scanner接口的方式,并从中开始。我相信很多其他人会发现这很有用,因为这是一件让我困惑的事情:)如果要做成千上万的定界操作,这绝对是一个很好的选择。我喜欢你把它作为一个界面绑定在一起,这样我就可以轻松地对读卡器进行操作;它非常有用。谢谢肯定比公认的答案要好。这将产生更少的垃圾
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)...)

    }
}
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
}