bytes.Buffer.Read în Go

Citește din buffer octeți (Read, ReadByte) sau caractere (ReadRune); UnreadByte și UnreadRune pun înapoi ultima citire.

Sintaxă
func (b *Buffer) Read(p []byte) (n int, err error)
func (b *Buffer) ReadByte() (byte, error)
func (b *Buffer) ReadRune() (r rune, size int, err error)
func (b *Buffer) UnreadByte() error
func (b *Buffer) UnreadRune() error

Ce face bytes.Buffer.Read

buf.Read(p) copiază în p cel mult len(p) octeți din partea necitită și returnează câți a copiat. Când bufferul este gol, returnează 0, io.EOF. ReadByte citește un singur octet, iar ReadRune un caracter UTF-8 întreg, împreună cu numărul lui de octeți.

UnreadByte pune înapoi ultimul octet citit, iar UnreadRune ultimul caracter citit cu ReadRune. Sunt utile când citești „cu un pas înainte”: te uiți la următorul caracter și, dacă nu este al tău, îl pui la loc. UnreadRune merge doar imediat după ReadRune; altfel returnează eroare.

Parametri

Parametru Descriere
p La Read: slice-ul în care se copiază octeții.

Ce returnează

Read: octeții citiți și eroarea. ReadByte: octetul și eroarea. ReadRune: caracterul, mărimea lui și eroarea. Unread*: o eroare dacă revenirea nu este posibilă.

Exemple

Exemplul 1: Citire în bucăți cu Read

package main

import (
	"bytes"
	"fmt"
	"io"
)

func main() {
	buf := bytes.NewBufferString("Ana are mere")
	bucata := make([]byte, 5)
	for {
		n, err := buf.Read(bucata)
		if err == io.EOF {
			break
		}
		fmt.Printf("%d octeți: %q\n", n, bucata[:n])
	}
}

Rezultat

5 octeți: "Ana a"
5 octeți: "re me"
2 octeți: "re"

Exemplul 2: ReadRune și UnreadRune: citirea unui număr dintr-un text

Citim cifre până dăm de altceva; caracterul care nu este cifră (aici ș) este pus înapoi cu UnreadRune.

package main

import (
	"bytes"
	"fmt"
	"unicode"
)

func main() {
	buf := bytes.NewBufferString("42ș rest")
	numar := 0
	for {
		r, _, err := buf.ReadRune()
		if err != nil {
			break
		}
		if !unicode.IsDigit(r) {
			buf.UnreadRune()
			break
		}
		numar = numar*10 + int(r-'0')
	}
	fmt.Println("număr:", numar, "| rămas:", buf.String())
}

Rezultat

număr: 42 | rămas: ș rest

Exemplul 3: ReadByte și UnreadByte

package main

import (
	"bytes"
	"fmt"
)

func main() {
	buf := bytes.NewBufferString("#titlu")
	c, _ := buf.ReadByte()
	fmt.Printf("primul octet: %c\n", c)
	buf.UnreadByte()
	fmt.Println("după UnreadByte:", buf.String())
	buf.ReadByte()
	buf.ReadByte()
	fmt.Println("UnreadRune după ReadByte:", buf.UnreadRune())
}

Rezultat

primul octet: #
după UnreadByte: #titlu
UnreadRune după ReadByte: bytes.Buffer: UnreadRune: previous operation was not a successful ReadRune

Greșeli frecvente

  • Folosești tot slice-ul p după Read, nu doar p[:n]. Ultima citire poate fi mai scurtă, iar restul slice-ului are date vechi.
  • Citești caractere cu diacritice octet cu octet (ReadByte): ș vine în două bucăți fără sens. Pentru text folosește ReadRune.

Comenzi înrudite

  • bytes.Buffer: Un buffer de octeți care crește singur: scrii în el cu Write/WriteString/WriteByte/WriteRune și citești cu String() sau Bytes().
  • bytes.Buffer.ReadString: Citește din buffer până la un caracter-delimitator (inclusiv), ca text (ReadString) sau octeți (ReadBytes).
  • bytes.Buffer.Next: Next returnează următorii n octeți și îi consumă; Peek îi returnează fără să-i consume.
  • strings.Reader: Face dintr-un text o sursă de citire (io.Reader), ca să-l dai funcțiilor care citesc din fișiere sau rețea.