从读取器中读取,直到达到一个字符串。

huangapple go评论76阅读模式
英文:

Reading from reader until a string is reached

问题

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

换句话说,我想做的与reader.ReadString()相同,只是接受一个字符串而不是单个字节。

例如:

mydata, err := reader.ReadString("\r\n.\r\n") //显然无法编译

我该如何做到这一点?

提前感谢,

Twichy

修正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")
}
英文:

I am trying to write a function to keep reading from a buffered reader until I hit a certain string, then to stop reading and return everything read prior to that string.

In other words, I want to do the same thing as reader.ReadString() does, except taking a string instead of a single byte.

For instance:

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

How can I do this?

Thanks in advance,

Twichy

Amendment 1: Previous attempt

Here is my previous attempt; its badly written and doesnt work but hopefully it demonstrates what I am trying to do.

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

答案1

得分: 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)
}

}

英文:
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)
        }
}

Playground


Output:

"123deli456elim789"
"ABC"
2009/11/10 23:00:00 EOF

答案2

得分: 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
英文:

For example,

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

Output:

1234
5678
1234567901234567890

答案3

得分: 2

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

英文:

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)...)

	}
}

答案4

得分: 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
}

这是一个可以在TCP连接中识别"#\t#"的示例。

英文:

Because you have the same byte in the string, you can do it as below:

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
}

This is the sample that can recognize the "#\t#" in TCP connection

huangapple
  • 本文由 发表于 2013年7月29日 13:54:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/17916912.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定