golang标准库学习——buffio包

前端之家收集整理的这篇文章主要介绍了golang标准库学习——buffio包前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。


@H_301_5@@H_301_5@@H_301_5@

import "bufio"@H_301_5@
@H_301_5@@H_301_5@

bufio包实现了有缓冲的I/O。它包装一个io.Reader或io.Writer接口对象,创建另一个也实现了该接口,且同时还提供了缓冲和一些文本I/O的帮助函数的对象。@H_301_5@@H_301_5@@H_301_5@


@H_301_5@@H_301_5@@H_301_5@


@H_301_5@

一、常量@H_301_5@@H_301_5@@H_301_5@

@H_301_5@@H_301_5@@H_301_5@

const (
    // 用于缓冲一个token,实际需要的最大token尺寸可能小一些,例如缓冲中需要保存一整行内容@H_301_5@@H_301_5@
    MaxScanTokenSize@H_301_5@ = 64 * 1024
)@H_301_5@

@H_301_5@

二、变量@H_301_5@@H_301_5@@H_301_5@

var ( ErrInvalidUnreadByte@H_301_5@ = errors.New("bufio: invalid use of UnreadByte") ErrInvalidUnreadRune@H_301_5@ = New("bufio: invalid use of UnreadRune") ErrBufferFull@H_301_5@ = New("bufio: buffer full") ErrNegativeCount@H_301_5@ = New("bufio: negative count") )@H_301_5@

会被Reader或Writer返回的错误类型@H_301_5@@H_301_5@@H_301_5@

var ( ErrTooLong@H_301_5@ = New("bufio.Scanner: token too long") ErrNegativeAdvance@H_301_5@ = New("bufio.Scanner: SplitFunc returns negative advance count") ErrAdvanceTooFar@H_301_5@ = New("bufio.Scanner: SplitFunc returns advance count beyond input") )@H_301_5@ 会被Scanner类型返回的错误。@H_301_5@
@H_301_5@


@H_301_5@@H_301_5@@H_301_5@@H_301_5@

三、类型和对应方法@H_301_5@@H_301_5@@H_301_5@


@H_301_5@
@H_301_5@@H_301_5@

1、Reader类型@H_301_5@@H_301_5@@H_301_5@

@H_301_5@@H_301_5@@H_301_5@@H_301_5@

type Reader struct {
    		buf          []byte
    		rd           io.Reader // reader provided by the client
    		r,w         int       // buf read and write positions
    		err          error
    		lastByte     int
    		lastRuneSize int
}

@H_301_5@

1.1 Reader类型对应的方法@H_301_5@@H_301_5@@H_301_5@@H_301_5@


@H_301_5@
@H_301_5@@H_301_5@@H_301_5@

// NewReaderSize 将 rd 封装成一个拥有 size 大小缓存的 bufio.Reader 对象
// 如果 rd 的基类型就是 bufio.Reader 类型,而且拥有足够的缓存@H_301_5@
// 则直接将 rd 转换为基类型并返回@H_301_5@
@H_301_5@@H_301_5@
func NewReaderSize(rd io.Reader,size int) *Reader@H_301_5@

// NewReader 相当于 NewReaderSize(rd,4096)@H_301_5@
func NewReader(rd Reader) *Reader@H_301_5@

@H_301_5@@H_301_5@@H_301_5@@H_301_5@

func (*Reader)Reset@H_301_5@

func (b *Reader) Reset(r Reader)@H_301_5@

Reset丢弃缓冲中的数据,清除任何错误,将b重设为其下层从r读取数据。@H_301_5@


@H_301_5@

func (*Reader)Buffered@H_301_5@

Reader) Buffered() int@H_301_5@

Buffered返回缓冲中现有的可读取的字节数。@H_301_5@


@H_301_5@

func (*Reader)Peek@H_301_5@

Reader) Peek(n int) ([]byte,error)@H_301_5@

Peek返回输入流的下n个字节,而不会移动读取位置。返回的[]byte只在下一次调用读取操作前合法。如果Peek返回的切片长度比n小,它也会返会一个错误说明原因。如果n比缓冲尺寸还大,返回的错误将是ErrBufferFull。@H_301_5@


@H_301_5@

func (*Reader)Read@H_301_5@

Reader) Read(p []byte) (n int,err  Read读取数据写入p。本方法返回写入p的字节数。本方法一次调用最多会调用下层Reader接口一次Read方法,因此返回值n可能小于len(p)。读取到达结尾时,返回值n将为0而err将为io.EOF。


func (*Reader)ReadByte@H_301_5@

Reader) ReadByte() (c  ReadByte读取并返回一个字节。如果没有可用的数据,会返回错误。


func (*Reader)UnreadByte@H_301_5@

Reader) UnreadByte() error@H_301_5@

UnreadByte吐出最近一次读取操作读取的最后一个字节。(只能吐出最后一个,多次调用会出问题)@H_301_5@


@H_301_5@

func (*Reader)ReadRune@H_301_5@

Reader) ReadRune() (r rune,sans-serif; line-height:20px"> ReadRune读取一个utf-8编码的unicode码值,返回该码值、其编码长度和可能的错误。如果utf-8编码非法,读取位置只移动1字节,返回U+FFFD,返回值size为1而err为nil。如果没有可用的数据,会返回错误。@H_301_5@


@H_301_5@

func (*Reader)UnreadRune@H_301_5@

Reader) UnreadRune()  UnreadRune吐出最近一次ReadRune调用读取的unicode码值。如果最近一次读取不是调用的ReadRune,会返回错误。(从这点看,UnreadRune比UnreadByte严格很多)


func (*Reader)ReadLine@H_301_5@

func (b *Reader) ReadLine() (line []bool,171); text-decoration:none" rel="nofollow">error)@H_301_5@

ReadLine是一个低水平的行数据读取原语。大多数调用者应使用ReadBytes('\n')或ReadString('\n')代替,或者使用Scanner。@H_301_5@

ReadLine尝试返回一行数据,不包括行尾标志的字节。如果行太长超过了缓冲,返回值isPrefix会被设为true,并返回行的前面一部分。该行剩下的部分将在之后的调用中返回。返回值isPrefix会在返回该行最后一个片段时才设为false。返回切片是缓冲的子切片,只在下一次读取操作之前有效。ReadLine要么返回一个非nil的line,要么返回一个非nil的err,两个返回值至少一个非nil。@H_301_5@

返回的文本不包含行尾的标志字节("\r\n"或"\n")。如果输入流结束时没有行尾标志字节,方法不会出错,也不会指出这一情况。在调用ReadLine之后调用UnreadByte会总是吐出最后一个读取的字节(很可能是该行的行尾标志字节),即使该字节不是ReadLine返回值的一部分。@H_301_5@


@H_301_5@

func (*Reader)ReadSlice@H_301_5@

Reader) ReadSlice(delim byte) (line [] ReadSlice读取直到第一次遇到delim字节,返回缓冲里的包含已读取的数据和delim字节的切片。该返回值只在下一次读取操作之前合法。如果ReadSlice放在在读取到delim之前遇到了错误,它会返回在错误之前读取的数据在缓冲中的切片以及该错误(一般是io.EOF)。如果在读取到delim之前缓冲就被写满了,ReadSlice失败并返回ErrBufferFull。因为ReadSlice的返回值会被下一次I/O操作重写,调用者应尽量使用ReadBytes或ReadString替代本法功法。当且仅当ReadBytes方法返回的切片不以delim结尾时,会返回一个非nil的错误。


func (*Reader)ReadBytes@H_301_5@

Reader) ReadBytes(delim  ReadBytes读取直到第一次遇到delim字节,返回一个包含已读取的数据和delim字节的切片。如果ReadBytes方法在读取到delim之前遇到了错误,它会返回在错误之前读取的数据以及该错误(一般是io.EOF)。当且仅当ReadBytes方法返回的切片不以delim结尾时,会返回一个非nil的错误。


func (*Reader)ReadString@H_301_5@

Reader) ReadString(delim byte) (line string,sans-serif; line-height:20px"> ReadString读取直到第一次遇到delim字节,返回一个包含已读取的数据和delim字节的字符串。如果ReadString方法在读取到delim之前遇到了错误,它会返回在错误之前读取的数据以及该错误(一般是io.EOF)。当且仅当ReadString方法返回的切片不以delim结尾时,会返回一个非nil的错误。@H_301_5@


@H_301_5@

func (*Reader)WriteTo@H_301_5@

Reader) WriteTo(w io.Writer) (n int64,sans-serif; line-height:20px"> WriteTo方法实现了io.WriterTo接口。@H_301_5@


@H_301_5@

2、Writer类型@H_301_5@@H_301_5@@H_301_5@

@H_301_5@@H_301_5@@H_301_5@


// Writer 实现了带缓存的 io.Writer 对象
// 如果在向 Writer 中写入数据的过程中遇到错误
// 则 Writer 不会再接受任何数据
// 而且后续的写入操作都将返回错误信息@H_301_5@


type Writer struct {
@H_301_5@

 err error  @H_301_5@buf []byte  @H_301_5@n int  @H_301_5@wr io.Writer@H_301_5@@H_301_5@

}@H_301_5@@H_301_5@


@H_301_5@@H_301_5@

example:@H_301_5@@H_301_5@@H_301_5@@H_301_5@

w := bufio.NewWriter(os.Stdout)
fmt.Fprint(w,"Hello,")
fmt.Fprint(w,"world!")
w.Flush() // Don't forget to flush!@H_301_5@@H_301_5@

@H_301_5@

2.1、Writer类型对应的方法@H_301_5@@H_301_5@@H_301_5@

@H_301_5@@H_301_5@@H_301_5@

funcNewWriter@H_301_5@

func NewWriter(w Writer) *Writer@H_301_5@

NewWriter创建一个具有默认大小缓冲、写入w的*Writer。@H_301_5@


@H_301_5@

funcNewWriterSize@H_301_5@

func NewWriterSize(w Writer,171); text-decoration:none" rel="nofollow">int) *Writer@H_301_5@

NewWriterSize创建一个具有最少有size尺寸的缓冲、写入w的*Writer。如果参数w已经是一个具有足够大缓冲的*Writer类型值,会返回w。@H_301_5@


@H_301_5@

func (*Writer)func (b *Writer) Reset(w Writer)@H_301_5@

Reset丢弃缓冲中的数据,清除任何错误,将b重设为将其输出写入w。@H_301_5@


@H_301_5@

func (*Writer)Writer) Buffered() Buffered返回缓冲中已使用的字节数。


func (*Writer)Available@H_301_5@

Writer) Available()  Available返回缓冲中还有多少字节未使用。


func (*Writer)Write@H_301_5@

Writer) Write(p []byte) (nn  Write将p的内容写入缓冲。返回写入的字节数。如果返回值nn < len(p),还会返回一个错误说明原因。


func (*Writer)WriteString@H_301_5@

Writer) WriteString(s string) ( WriteString写入一个字符串。返回写入的字节数。如果返回值nn < len(s),还会返回一个错误说明原因。


func (*Writer)WriteByte@H_301_5@

Writer) WriteByte(c byte)  WriteByte写入单个字节。


func (*Writer)WriteRune@H_301_5@

Writer) WriteRune(r rune) (size  WriteRune写入一个unicode码值(的utf-8编码),返回写入的字节数和可能的错误。


func (*Writer)Flush@H_301_5@

Writer) Flush()  Flush方法将缓冲中的数据写入下层的io.Writer接口。


func (*Writer)ReadFrom@H_301_5@

Writer) ReadFrom(r Reader) (n  ReadFrom实现了io.ReaderFrom接口。


3、ReadWriter类型

typeReadWriter@H_301_5@

type ReadWriter struct {
    *Reader
    *Writer
}@H_301_5@

ReadWriter类型保管了指向Reader和Writer类型的指针,(因此)实现了io.ReadWriter接口。@H_301_5@

funcNewReadWriter@H_301_5@

func NewReadWriter(r *Writer) *ReadWriter@H_301_5@

NewReadWriter申请创建一个新的、将读写操作分派给r和w的ReadWriter。@H_301_5@


@H_301_5@@H_301_5@@H_301_5@

4、SplitFunc类型@H_301_5@@H_301_5@@H_301_5@

type SplitFunc func(data []bool) (advance error)@H_301_5@

SplitFunc类型代表用于对输出作词法分析的分割函数。@H_301_5@

参数data是尚未处理的数据的一个开始部分的切片,参数atEOF表示是否Reader接口不能提供更多的数据。返回值是解析位置前进的字节数,将要返回给调用者的token切片,以及可能遇到的错误。如果数据不足以(保证)生成一个完整的token,例如需要一整行数据但data里没有换行符,SplitFunc可以返回(0,nil,nil)来告诉Scanner读取更多的数据写入切片然后用从同一位置起始、长度更长的切片再试一次(调用SplitFunc类型函数)。@H_301_5@

如果返回值err非nil,扫描将终止并将该错误返回给Scanner的调用者。@H_301_5@

除非atEOF为真,永远不会使用空切片data调用SplitFunc类型函数。然而,如果atEOF为真,data却可能是非空的、且包含着未处理的文本。@H_301_5@


@H_301_5@

4.1、SplitFunc类型的函数@H_301_5@@H_301_5@@H_301_5@

@H_301_5@@H_301_5@@H_301_5@

funcScanBytes@H_301_5@

func ScanBytes(data []error)@H_301_5@

ScanBytes是用于Scanner类型的分割函数(符合SplitFunc),本函数会将每个字节作为一个token返回。@H_301_5@

funcScanRunes@H_301_5@

func ScanRunes(data [] ScanRunes是用于Scanner类型的分割函数(符合SplitFunc),本函数会将每个utf-8编码的unicode码值作为一个token返回。本函数返回的rune序列和range一个字符串的输出rune序列相同。错误的utf-8编码会翻译为U+FFFD = "\xef\xbf\xbd",但只会消耗一个字节。调用者无法区分正确编码的rune和错误编码的rune。

funcScanWords@H_301_5@

func ScanWords(data [] ScanRunes是用于Scanner类型的分割函数(符合SplitFunc),本函数会将空白(参见unicode.IsSpace)分隔的片段(去掉前后空白后)作为一个token返回。本函数永远不会返回空字符串。

funcScanLines@H_301_5@

func ScanLines(data [] ScanRunes是用于Scanner类型的分割函数(符合SplitFunc),本函数会将每一行文本去掉末尾的换行标记作为一个token返回。返回的行可以是空字符串。换行标记为一个可选的回车后跟一个必选的换行符。最后一行即使没有换行符也会作为一个token返回。


5、Scanner类型


// Scanner 提供了一个方便的接口来读取数据,例如读取一个多行文本
// 连续调用 Scan 方法将扫描数据中的“指定部分”,跳过各个“指定部分”之间的数据
// Scanner 使用了缓存,所以“指定部分”的长度不能超出缓存的长度
// Scanner 需要一个 SplitFunc 类型的“切分函数”来确定“指定部分”的格式
// 本包中提供的“切分
函数@H_301_5@”有@H_301_5@“行切分函数”、“字节切分函数”、“UTF8字符编码切分函数
// 和“单词@H_301_5@切分函数”,用户也可以自定义“切分函数
// 默认的“切分函数@H_301_5@”为“行切分函数”,用于获取数据中的一行数据(不包括行尾符)@H_301_5@
//@H_301_5@
// 扫描在遇到下面的情况时会停止:@H_301_5@
// 1、数据扫描完毕,遇到 io.EOF@H_301_5@
// 2、遇到读写错误@H_301_5@
// 3、“指定部分”的长度超过了缓存的长度@H_301_5@
// 如果要对数据进行更多的控制,比如的错误处理或扫描更大的“指定部分”或顺序扫描@H_301_5@
// 则应该使用 bufio.Reader@H_301_5@
@H_301_5@@H_301_5@@H_301_5@

@H_301_5@@H_301_5@@H_301_5@@H_301_5@

type Scanner struct {
	r            io.Reader // The reader provided by the client.
	split        SplitFunc // The function to split the tokens.
	maxTokenSize int       // Maximum size of a token; modified by tests.
	token        []byte    // Last token returned by split.
	buf          []byte    // Buffer used as argument to split.
	start        int       // First non-processed byte in buf.
	end          int       // End of data@H_301_5@ in buf.
	err          error     // Sticky error.
}@H_301_5@

@H_301_5@

5.1、Scanner类型对应方法@H_301_5@@H_301_5@@H_301_5@@H_301_5@

@H_301_5@@H_301_5@@H_301_5@@H_301_5@

funcNewScanner@H_301_5@

func NewScanner(r Reader) *Scanner@H_301_5@

NewScanner创建并返回一个从r读取数据的Scanner,默认的分割函数是ScanLines。@H_301_5@

func (*Scanner)Split@H_301_5@

func (s *Scanner) Split(split SplitFunc)@H_301_5@

Split设置该Scanner的分割函数。本方法必须在Scan之前调用。@H_301_5@

func (*Scanner)Scan@H_301_5@

Scanner) Scan() bool@H_301_5@

Scan方法获取当前位置的token(该token可以通过Bytes或Text方法获得),并让Scanner的扫描位置移动到下一个token。当扫描因为抵达输入流结尾或者遇到错误而停止时,本方法会返回false。在Scan方法返回false后,Err方法将返回扫描时遇到的任何错误;除非是io.EOF,此时Err会返回nil。@H_301_5@

func (*Scanner)Bytes@H_301_5@

Scanner) Bytes() []byte@H_301_5@

Bytes方法返回最近一次Scan调用生成的token。底层数组指向的数据可能会被下一次Scan的调用重写。@H_301_5@

func (*Scanner)Text@H_301_5@

Scanner) Text() string@H_301_5@

Bytes方法返回最近一次Scan调用生成的token,会申请创建一个字符串保存token并返回该字符串。@H_301_5@

func (*Scanner)Err@H_301_5@

Scanner) Err()  Err返回Scanner遇到的第一个非EOF的错误。@H_301_5@


@H_301_5@

5.2、使用例子@H_301_5@@H_301_5@@H_301_5@@H_301_5@

@H_301_5@@H_301_5@@H_301_5@@H_301_5@

// An artificial input source.@H_301_5@
const input = "1234 5678 1234567901234567890"
scanner := bufio.NewScanner(strings.NewReader(input))
// Create a custom split function by wrapping the existing ScanWords function.@H_301_5@
split := func(data []byte,atEOF bool) (advance int,token []byte,err error) {
    advance,token,err = bufio.ScanWords(data,atEOF)
    if err == nil && token != nil {
        _,err = strconv.ParseInt(string(token),10,32)
    }
    return
}
// Set the split function for the scanning operation.@H_301_5@
scanner.Split(split)
// Validate the input@H_301_5@
for scanner.Scan() {
    fmt.Printf("%s\n",scanner.Text())
}
if err := scanner.Err(); err != nil {
    fmt.Printf("Invalid input: %s",err)
}@H_301_5@

Output:@H_301_5@

1234
5678
Invalid input: strconv.ParseInt: parsing "1234567901234567890": value out of range@H_301_5@

@H_301_5@

@H_301_5@@H_301_5@@H_301_5@@H_301_5@

Example (Lines)@H_301_5@
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
    fmt.Println(scanner.Text()) // Println will add back the final '\n'@H_301_5@
}
if err := scanner.Err(); err != nil {
    fmt.Fprintln(os.Stderr,"reading standard input:",err)
}@H_301_5@
Example (Words)@H_301_5@
// An artificial input source.@H_301_5@ const input = "Now is the winter of our discontent,\nMade glorIoUs summer by this sun of York.\n" scanner := bufio.NewScanner(strings.NewReader(input)) // Set the split function for the scanning operation.@H_301_5@ scanner.Split(bufio.ScanWords) // Count the words.@H_301_5@ count := 0 for scanner.Scan() { count++ } if err := scanner.Err(); err != nil { fmt.Fprintln(os.Stderr,"reading input:",err) } fmt.Printf("%d\n",count)@H_301_5@

Output:@H_301_5@

15@H_301_5@


@H_301_5@

参考@H_301_5@@H_301_5@@H_301_5@@H_301_5@

http://studygolang.com/pkgdoc
@H_301_5@@H_301_5@@H_301_5@@H_301_5@

http://studygolang.com/articles/4367
@H_301_5@@H_301_5@@H_301_5@@H_301_5@

http://www.cnblogs.com/golove/p/3282667.html @H_301_5@@H_301_5@@H_301_5@@H_301_5@

原文链接:https://www.f2er.com/go/190063.html

猜你在找的Go相关文章