GO_strings.Reader


type Reader struct {s        stringi        int64 // 当前读取的下标prevRune int   // 记录读取中文时候的下标,除了ReadRune会赋值,其他赋值-1
}
  • Len():返回未读的字串长度,在下面的例子会讲到怎么变的
  • Size(): 返回len(s),永远不变

NewReader

// NewReader returns a new Reader reading from s.
// It is similar to bytes.NewBufferString but more efficient and read-only.
func NewReader(s string) *Reader { return &Reader{s, 0, -1} }

Read

strings.Reader实现的Read方法,如果当前读取下标大于等于s的长度,表示已经读完了。反之,把i下标之后的内容拷贝给b,拷贝的长度为n。当前读取下标更新,加上n的长度。

func (r *Reader) Read(b []byte) (n int, err error) {if r.i >= int64(len(r.s)) {return 0, io.EOF}r.prevRune = -1n = copy(b, r.s[r.i:])r.i += int64(n)return
}

ReadAt

strings.ReadAt是实现io包里面的另一个方法,指定从一个位置读取,和Read一样只不过把r.i改成off,由请求方决定。
和Read不同的是,如果读取的长度n < 长度b,则表示r.s已经读取完了,需要返回EOF这个错误,在Read里面是没有的。

另外,注意ReadAt不会修改r.i的位置。

func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) {// cannot modify state - see io.ReaderAtif off < 0 {return 0, errors.New("strings.Reader.ReadAt: negative offset")}if off >= int64(len(r.s)) {return 0, io.EOF}n = copy(b, r.s[off:])if n < len(b) {err = io.EOF}return
}

ReadByte&UnReadByte

ReadByte返回(byte, error)

UnReadByte把r.i–


ReadRune

读取中文字时候用

第6行,r.prevRune记录读取中文字的下标,不是加上这个中文字的大小

第7行判断读取的字节是不是中文字,如果不是,就只会读取1个byte,然后返回;反之,会把这个中文字节转换成可读文字返回。

r.i加上读取字节的大小。

func (r *Reader) ReadRune() (ch rune, size int, err error) {if r.i >= int64(len(r.s)) {r.prevRune = -1return 0, 0, io.EOF}r.prevRune = int(r.i)if c := r.s[r.i]; c < utf8.RuneSelf {r.i++return rune(c), 1, nil}ch, size = utf8.DecodeRuneInString(r.s[r.i:])r.i += int64(size)return
}

UnreadRune

UnreadRune退回到上一次ReadRune的位置,上一次的位置记在r.prevRune,所以r.i直接赋值为r.prevRune。这个方法必须配合ReadRune使用,如果上一次不是ReadRune,这个方法会报错。

func (r *Reader) UnreadRune() error {if r.i <= 0 {return errors.New("strings.Reader.UnreadRune: at beginning of string")}if r.prevRune < 0 {return errors.New("strings.Reader.UnreadRune: previous operation was not ReadRune")}r.i = int64(r.prevRune)r.prevRune = -1return nil
}

Seek

strings.Reader实现io.Seeker,指定下一次读取或者写的起始位置,直接修改r.i

func (r *Reader) Seek(offset int64, whence int) (int64, error) {r.prevRune = -1var abs int64switch whence {case io.SeekStart:abs = offsetcase io.SeekCurrent:abs = r.i + offsetcase io.SeekEnd:abs = int64(len(r.s)) + offsetdefault:return 0, errors.New("strings.Reader.Seek: invalid whence")}if abs < 0 {return 0, errors.New("strings.Reader.Seek: negative position")}r.i = absreturn abs, nil
}

WriteTo

strings.Reader实现io.WriterTo,写入一个io.Writer,写入的内容,取决于r.i的位置。

如果r.i已经是r.s的长度表示已经读取完,没有字节可以用于写入,会回传size 0,但是不报错,nil。

func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {r.prevRune = -1if r.i >= int64(len(r.s)) {return 0, nil}s := r.s[r.i:]m, err := io.WriteString(w, s)if m > len(s) {panic("strings.Reader.WriteTo: invalid WriteString count")}r.i += int64(m)n = int64(m)if m != len(s) && err == nil {err = io.ErrShortWrite}return
}

例子

s := strings.NewReader("abcdeabcdghij")// a  b  c  d  e  f  g  h  i  j// 1  2  3  4  5  6  7  8  9  10// Len作用: 返回未读的字符串长度// Size的作用:返回字符串的长度fmt.Printf("len : %d\n", s.Len()) //还未被读的string的长度 ===> 10fmt.Printf("size : %d\n", s.Size()) // 原始string长度,不会被改变的,每次调用都是一样的 ===> 10// Read会影响未读长度的数值,为r.i+n,n为读的长度fmt.Println("\nRead 读了5个byte之后的size和len")buf1 := make([]byte, 5)_, _ = s.Read(buf1)fmt.Println("buffer read : ", string(buf1)) // ===> abcdefmt.Printf("len : %d\n", s.Len()) //还未被读的string的长度 ===> 5fmt.Printf("size : %d\n", s.Size()) // 原始string长度,不会被改变的,每次调用都是一样的 ===> 10_, _ = s.Seek(1, io.SeekStart)buf1 = make([]byte, 5)_, _ = s.Read(buf1)fmt.Println("buffer read : ", string(buf1)) // ===> abcdefmt.Printf("len : %d\n", s.Len()) //还未被读的string的长度 ===> 5fmt.Printf("size : %d\n", s.Size()) // 原始string长度,不会被改变的,每次调用都是一样的 ===> 10// ReadAt不会影响未读长度的数值,为r.i+n,n为读的长度s = strings.NewReader("abcdefghij")fmt.Println("\nReatAt 读了指定长度之后的字符串,不影响任何len或size")buf2 := make([]byte, 6)_, _ = s.ReadAt(buf2, 6)fmt.Println("buffer read : ", string(buf2)) // ===> ghijfmt.Printf("len : %d\n", s.Len()) //还未被读的string的长度 ===> 10fmt.Printf("size : %d\n", s.Size()) // 原始string长度,不会被改变的,每次调用都是一样的 ===> 10// ReadByte每次只读1byte,从未读的index开始,每次只返回1byte,相对应的读完之后r.i会+1s = strings.NewReader("abcdefghij")fmt.Println("\nReadByte 只读1个byte,len修改 size不修改")buf3, _ := s.ReadByte()fmt.Println("buffer read : ", string(buf3)) // ===> afmt.Printf("len : %d\n", s.Len()) //还未被读的string的长度 ===> 9fmt.Printf("size : %d\n", s.Size()) // 原始string长度,不会被改变的,每次调用都是一样的 ===> 10// UnreadByte,从r.i开始,往后退,r.i会-1fmt.Println("\nUnreadByte len多1,不影响任何len或size")_ = s.UnreadByte()fmt.Printf("len : %d\n", s.Len()) //还未被读的string的长度 ===> 10fmt.Printf("size : %d\n", s.Size()) // 原始string长度,不会被改变的,每次调用都是一样的 ===> 10// Seek,算偏移,可以指定到那个index,会改变lenfmt.Println("\nSeek 偏移位数,一般配合read来用")bias, _ := s.Seek(4, io.SeekCurrent)buf4 := make([]byte, 3)_, _ = s.ReadAt(buf4, bias)fmt.Println("buffer read : ", string(buf4)) // ===> efgfmt.Printf("len : %d\n", s.Len()) //还未被读的string的长度 ===> 6fmt.Printf("size : %d\n", s.Size()) // 原始string长度,不会被改变的,每次调用都是一样的 ===> 10bias, _ = s.Seek(-2, io.SeekCurrent)buf5 := make([]byte, 3)_, _ = s.ReadAt(buf5, bias)fmt.Println("buffer read : ", string(buf5)) // ===> cdefmt.Printf("len : %d\n", s.Len()) //还未被读的string的长度 ===> 8fmt.Printf("size : %d\n", s.Size()) // 原始string长度,不会被改变的,每次调用都是一样的 ===> 10zw := strings.NewReader("测a中文")ch, size, _ := zw.ReadRune()fmt.Printf("buffer read : %c \n", ch) // ===> 测fmt.Println("buffer read  size : ", size) // ===> 3ch, size, _ = zw.ReadRune()fmt.Printf("buffer read : %c \n", ch) // ===> afmt.Println("buffer read  size : ", size) // ===> 1_ = zw.UnreadRune()ch, size, _ = zw.ReadRune()fmt.Printf("buffer read : %c \n", ch) // ===> afmt.Println("buffer read  size : ", size) // ===> 1

GO_strings.Reader相关推荐

  1. Ubuntu 14.04 64位上安装Adobe reader 9.5.5

    首先说明下面的方法本非完美的方案,但是我试验了下,确实可行. 1.从Adobe官网下载最新版的Adobe Reader 9.5.5的deb包,在下面的ftp位置: 2.安装相关依赖库,主要是ia-32 ...

  2. 基于Google Reader的个人知识管理方案

    来源月光博客:http://www.williamlong.info/archives/2172.html. 先前我写的<基于Dropbox的个人知识管理平台>讲述了使用Dropbox在个 ...

  3. [CareerCup] 8.5 Online Book Reader System 在线读书系统

    8.5 Design the data structures for an online book reader system. 这道题OOB的题让我们设计一个在线读书系统,还是没有任何提示,所以发挥 ...

  4. python csv模块 一次读多行_python中csv模块读取reader只能读取一次

    各位好,请问python读取csv文件时只能读取一次是为什么 现在有一个csv文件 大概是这个样子 现在对ID和length进行读取 import csv with open('ccc.csv','r ...

  5. 使用Oracle创建图书馆数据库(book reader lib loan表)

    -- 一.创建表 --  创建图书馆管理系统所涉及的表 --  创建产品销售系统所涉及的表 --  1.图书表book(bid,bname,price,qty) DROP TABLE book cas ...

  6. 简单的Writer和Reader

    Writer用于写出去到文件中,Reader用于将外面的文件读进来控制台 Writer和Reader有许多子类,但是子类大多都是直接运用父类Writer和Reader的方法,而且Writer和Read ...

  7. [05]EXTJS4.0的读写器reader,writer

    Reader:主要用于将proxy数据代理读取的数据按照不同的规则进行解析,将解析好的数据保持到Model(数据模型类)中 结构图  Ext.data.reader.Reader  读取器的根类 Ex ...

  8. 解决Adobe Reader安装错误150120

    今天Adobe Reader这个软件提示有新版本了,让我更新,出于信任,我不假思索地更新了Adobe Reader这个软件,于是我倒霉的一天就在这之后了. 我用这个软件打开赛灵思的DocNav里面的赛 ...

  9. python reader循环_python – 多次循环遍历csv.DictReader行

    您在第一次迭代时读取整个文件,因此第二次没有任何内容可供阅读.由于您第二次似乎没有使用csv数据,因此计算行数并在第二次迭代该范围会更简单. import csv from itertools imp ...

最新文章

  1. 2022-2028年中国橡胶带行业市场运营格局及未来前景分析报告
  2. Jquery真的很棒
  3. Failed to read schema document ‘http://code.alibabatech.com/schema/dubbo/dubbo.xsd‘问题解决方法
  4. 【.NET正则表达式库】v1.0上线
  5. 基于sklearn的朴素贝叶斯_Sklearn参数详解—贝叶斯
  6. 华为跨域bgp_通知:2019华为认证体系全新升级!
  7. 读《python核心编程2》笔记 1
  8. [转载]Spring Boot Actuator 使用
  9. Julia : Set or Array ?
  10. 数据库执行update语句,一直执行不完【已解决】
  11. qq空间html倒计时,空间倒计时flash代码,有图
  12. 用C 制作含万年历的台历(2009年样张)之1
  13. 我大121321321321321
  14. 论文阅读:Entangled Watermarks as a Defense against Model Extraction
  15. Codeforces765F. Souvenirs
  16. 配置IPSec安全策略
  17. python实现召回率、精度、f1代码
  18. 信创大比武总决赛,29日线上直播开赛!
  19. Reveal真机配置
  20. 基于k8s、docker、jenkins构建springboot服务

热门文章

  1. 基于matlab的电机运行分析,电机模型分析及拖动仿真:基于MATLAB的现代方法
  2. 物联网安全复习二感知层安全
  3. window10系统jdk1.8改成1.6
  4. Javascript的调试利器:Firebug使用详解(上)
  5. 企业云办公最佳方案油塔企业云盘
  6. 计算机底层存储字节还是字符,彻底搞懂乱码——字符,字节和编码
  7. 超流水线计算机原理,6计算机组成原理第6章流水线原理.ppt
  8. HTML插入FLASH的全兼容解决方案[主讲SWFObject方法]
  9. 江苏省职称计算机考试题,江苏省职称计算机考试模拟题操作部分讲解(41~44)
  10. 大泉州汽车网整站程序PHP生成html开源版 V1.1.4