Golang bufio包Scanner源码

Go文件操作:读写与路径处理 这篇讲了Go文件读写的三种方式、追加写入、filepath路径处理、目录遍历和文件信息获取。记住两个要点,ReadFile适合小文件,Scanner适合大文件但一定要检查Err()并按需调大缓冲区。下一篇我们聊Go的单元测试,testing包和表驱动测试怎么玩。 阅读详情

Go jdk版本1.10.3  Scanner源码在bufio包中的scan.go文件中

 

一、Scanner介绍

       Scanner提供一个按指定规则来读取数据的缓冲区IO,比如通过”行匹配函数”来逐行读取数据,Scanner通过Scan方法来按”匹配函数”读取数。

      Scan方法会通过一个“匹配函数”读取数据中符合要求的部分,跳过不符合要求的部分。

      “匹配函数”由调用者指定。本包中提供的匹配函数有"行匹配函数"、"字节匹配函数"、"字符匹配函数"、"单词匹配函数",用户也可以自定义"匹配函数"。默认的匹配函数为"行匹配函数",用于获取数据中的一行内容(不包括行尾标记)。

      Scanner使用了缓存,所以匹配部分的长度不能超出缓存的容量。默认缓存容量为bufio.MaxScanTokenSize,用户可以通过Buffer方法指定缓存及最大容量

 

Scan方法 在遇到下面的情况时会终止扫描并返回 false(扫描一旦终止,将无法再继续):

1、遇到 io.EOF

2、遇到读写错误

3、“匹配部分”的长度超过了缓存的长度

 

二、Scanner源码

结构体

type Scanner struct {
   r            io.Reader // The reader provided by the client.  由用户提供的io.Reader
   split        SplitFunc // The function to split the tokens.  用于拆分tokens的函数(匹配函数,默认是行匹配)
   maxTokenSize int       // Maximum size of a token; modified by tests.   token的最大长度
   token        []byte    // Last token returned by split.  记录最后一次Scan操作匹配到的数据
   buf          []byte    // Buffer used as argument to split.
   start        int       // First non-processed byte in buf. 记录缓冲区buf中第一个未处理(扫描过)的位置
   end          int       // End of data in buf.  记录buf的结束位置
   err          error     // Sticky error.
   empties      int       // Count of successive empty tokens.  记录匹配到空数据的次数,如果超过指定maxConsecutiveEmptyReads次数,则会panic
   scanCalled   bool      // Scan has been called; buffer is in use.   标记Scan方法是否已经调用过,如果已经调用过则置为true,说明buffer在正在使用。
   done         bool      // Scan has finished.  标记是否已经扫描结束
}

 

type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)

      SplitFunc用来定义"匹配函数"类型,data是缓存中的数据,atEOF标记数据是否读完。

      advance返回data中已处理的数据的长度。token返回找到的"匹配部分"数据,"匹配部分"可以是缓存的切片,也可以是自己新建的数据(比如bufio.errorRune)。"匹配部分"将在Scan之后通过Bytes和Text反馈给用户。err返回错误信息

 

        如果在 data 中无法找到一个完整的“匹配部分”则应返回 (0, nil, nil),以便告诉Scanner 向缓存中填充更多数据,然后再次扫描(Scan 会自动重新扫描)。如果缓存已经达到最大容量还没有找到,则 Scan 会终止并返回 false。

      如果 data 为空,则“匹配函数”将不会被调用,意思是在“匹配函数”中不必考虑data 为空的情况。

     如果 err != nil,扫描将终止,如果 err == ErrFinalToken,则 Scan 将返回 true,表示扫描正常结束,如果 err 是其它错误,则 Scan 将返回 false,表示扫描出错。错误信息可以在 Scan 之后通过 Err 方法获取。

     SplitFunc 的作用很简单,从 data 中找出你感兴趣的数据,然后返回,同时返回已经处理的数据的长度。

 

初始化Scanner

func NewScanner(r io.Reader) *Scanner {
   return &Scanner{
      r:            r,
      split:        ScanLines,
      maxTokenSize: MaxScanTokenSize,
   }
}

       NewScanner函数用于初始化一个Scanner对象,NewScanner返回一个新的Scanner来扫描r,默认匹配函数为ScanLines(行匹配函数)

 

func (s *Scanner) Buffer(buf []byte, max int) {
   if s.scanCalled {
      panic("Buffer called after Scan")
   }
   s.buf = buf[0:cap(buf)]
   s.maxTokenSize = max
}

       Buffer方法用于指定该Scanner的缓冲区大小和最大可扩展的范围(即maxTokenSize),如果max小于len(buf),则buf的尺寸将固定不可调。

     Buffer必须在第一次Scan之前设置,否则会引发panic

 

func (s *Scanner) Split(split SplitFunc) {
   if s.scanCalled {
      panic("Split called after Scan")
   }
   s.split = split
}

       Split用于设置匹配函数,初始化Scanner的时候默认的匹配函数为ScanLines(行匹配函数),如果想使用其他的匹配函数可以通过该方法设置。

    Spit方法也必须在调用Scan前执行,否则会引起panic

 

获取匹配(Scan)的结果

func (s *Scanner) Err() error {
	if s.err == io.EOF {
		return nil
	}
	return s.err
}

该Err方法 返回扫描过程中遇到的非 EOF 错误,供用户调用,以便获取错误信息。

 

// Bytes returns the most recent token generated by a call to Scan.
// The underlying array may point to data that will be overwritten
// by a subsequent call to Scan. It does no allocation.
func (s *Scanner) Bytes() []byte {
	return s.token
}

 Bytes方法将最后一次扫描出的“匹配部分”作为一个切片引用返回,下一次的 Scan 操作会覆盖本次引用的内容。

 

// Text returns the most recent token generated by a call to Scan
// as a newly allocated string holding its bytes.
func (s *Scanner) Text() string {
	return string(s.token)
}

Text方法返回最后一次扫描出的"匹配部分"作为字符串返回

 

核心的匹配方法Scan

 func (s *Scanner) Scan() bool {
   if s.done {
      return false
   }
   s.scanCalled = true
   // Loop until we have a token.
   for {
      // See if we can get a token with what we already have.
      // If we've run out of data but have an error, give the split function
      // a chance to recover any remaining, possibly empty token.
      if s.end > s.start || s.err != nil { //如果缓冲区的结束位置 >  缓冲区未扫描的位置 或者err不为nil
         advance, token, err := s.split(s.buf[s.start:s.end], s.err != nil)  //尝试去缓冲区扫描匹配
         if err != nil {
            if err == ErrFinalToken {
               s.token = token
               s.done = true
               return true
            }
            s.setErr(err)
            return false
         }
         if !s.advance(advance) {
            return false
         }
         s.token = token  //记录本次匹配的token
         if token != nil {
            if s.err == nil || advance > 0 {  //当有匹配的token,并且扫描的长度大于0,则置空empties
               s.empties = 0   //emptis是记录连续匹配到为空的次数
            } else { //匹配到空数据
               // Returning tokens not advancing input at EOF.
               s.empties++
               if s.empties > maxConsecutiveEmptyReads {
                  panic("bufio.Scan: too many empty tokens without progressing")
               }
            }
            return true
         }
      }
      // We cannot generate a token with what we are holding.
      // If we've already hit EOF or an I/O error, we are done.
      if s.err != nil {
         // Shut it down.
         s.start = 0
         s.end = 0
         return false
      }
      // Must read more data.
      // First, shift data to beginning of buffer if there's lots of empty space
      // or space is needed.
      /*
      当start> 0 并且  s.end等于整个缓冲区的长度,或者start>0 并且 start大于缓冲区的一半
      则将未扫描的部分 移到 缓冲区的开头
      */
      if s.start > 0 && (s.end == len(s.buf) || s.start > len(s.buf)/2) {
         copy(s.buf, s.buf[s.start:s.end])
         s.end -= s.start
         s.start = 0
      }
      // Is the buffer full? If so, resize.
      /*
      如果缓冲区已满,
          1.如果缓冲区buf的长度已经大于等于maxTokenSize,或者缓冲区buf的长度大于maxInt的一半,则无法扩容
          2.将缓冲区扩大到现在缓冲区的2倍和maxTokenSize中的最小者,并设置start和end的值
      */
      if s.end == len(s.buf) {
         // Guarantee no overflow in the multiplication below.
         const maxInt = int(^uint(0) >> 1)
         if len(s.buf) >= s.maxTokenSize || len(s.buf) > maxInt/2 {
            s.setErr(ErrTooLong)
            return false
         }
         newSize := len(s.buf) * 2
         if newSize == 0 {
            newSize = startBufSize
         }
         if newSize > s.maxTokenSize {
            newSize = s.maxTokenSize
         }
         newBuf := make([]byte, newSize)
         copy(newBuf, s.buf[s.start:s.end])
         s.buf = newBuf
         s.end -= s.start
         s.start = 0
      }
      // Finally we can read some input. Make sure we don't get stuck with
      // a misbehaving Reader. Officially we don't need to do this, but let's
      // be extra careful: Scanner is for safe, simple jobs.
      //从输入流Reader中读取数据到缓冲区中
      for loop := 0; ; {
         n, err := s.r.Read(s.buf[s.end:len(s.buf)])
         s.end += n
         if err != nil {
            s.setErr(err)
            break
         }
         if n > 0 {
            s.empties = 0
            break
         }
         loop++
         if loop > maxConsecutiveEmptyReads {
            s.setErr(io.ErrNoProgress)
            break
         }
      }
   }
}

Scan开始一次扫描匹配,如果匹配成功,可以通过Bytes()或Text()方法取出结果,如果遇到错误,则终止扫描,并返回false。

 

func (s *Scanner) advance(n int) bool {
   if n < 0 {
      s.setErr(ErrNegativeAdvance)
      return false
   }
   if n > s.end-s.start {
      s.setErr(ErrAdvanceTooFar)
      return false
   }
   s.start += n
   return true
}

该advance方法用于Scan操作扫描了n个字节,这里会设置start的索引位置

 

bufio中内置的匹配函数

func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error) {
   if atEOF && len(data) == 0 {
      return 0, nil, nil
   }
   return 1, data[0:1], nil
}

ScanBytes 函数是"字节匹配"函数,扫描下一个字节

 

func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error) {
   if atEOF && len(data) == 0 {
      return 0, nil, nil
   }

   // Fast path 1: ASCII.
   if data[0] < utf8.RuneSelf {
      return 1, data[0:1], nil
   }

   // Fast path 2: Correct UTF-8 decode without error.
   _, width := utf8.DecodeRune(data)
   if width > 1 {
      // It's a valid encoding. Width cannot be one for a correctly encoded
      // non-ASCII rune.
      return width, data[0:width], nil
   }

   // We know it's an error: we have width==1 and implicitly r==utf8.RuneError.
   // Is the error because there wasn't a full rune to be decoded?
   // FullRune distinguishes correctly between erroneous and incomplete encodings.
   if !atEOF && !utf8.FullRune(data) {
      // Incomplete; get more bytes.
      return 0, nil, nil
   }

   // We have a real UTF-8 encoding error. Return a properly encoded error rune
   // but advance only one byte. This matches the behavior of a range loop over
   // an incorrectly encoded string.
   return 1, errorRune, nil
}

ScanRunes函数 是"字符匹配"函数,扫描下一个字符

 

func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
   if atEOF && len(data) == 0 { //已经扫描结束
      return 0, nil, nil
   }
   if i := bytes.IndexByte(data, '\n'); i >= 0 {//如果缓冲区data中可以找到'\n'换行结束符
      // We have a full newline-terminated line.
      return i + 1, dropCR(data[0:i]), nil
   }
   // If we're at EOF, we have a final, non-terminated line. Return it.
   if atEOF {  //如果没有找到换行符,并且atEOF为true,则说明已经EOF,扫描结束,并返回剩余的数据
      return len(data), dropCR(data), nil
   }
   // Request more data.
   return 0, nil, nil
}

      ScanLines函数是一个"行匹配函数",用来找出data中的单行数据并返回(包括空行),返回值不包含行尾标记(\n或\r\n),advance返回data中已处理的数据长度,该函数也是NewScanner初始化Scanner时默认的匹配函数。

 

func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error) {
   // Skip leading spaces.
   start := 0
   for width := 0; start < len(data); start += width {
      var r rune
      r, width = utf8.DecodeRune(data[start:])
      if !isSpace(r) {
         break
      }
   }
   // Scan until space, marking end of word.
   for width, i := 0, start; i < len(data); i += width {
      var r rune
      r, width = utf8.DecodeRune(data[i:])
      if isSpace(r) {
         return i + width, data[start:i], nil
      }
   }
   // If we're at EOF, we have a final, non-empty, non-terminated word. Return it.
   if atEOF && len(data) > start {
      return len(data), data[start:], nil
   }
   // Request more data.
   return start, nil, nil
}

ScanWords函数是"单词匹配"函数,它返回每个以空格分割的单词,并删除周围的空格。不会返回一个空字符串。

 

binja_degobfuscate:修复使用gobfuscator混淆的Go混淆二进制文件 解密(v1.0.1) 作者:杰米·汉金斯(Jamie Hankins) 在混淆的Go二进制文件中对字符串进行反混淆 描述: 该插件实现了一个简单的LLIL仿真器,以静态消除对简单字符串混淆的混淆,例如完成的混淆。 要激活它,请使用“ Tools菜单或命令面板。 它提供了两种模式,第一种将尝试分析当前函数,而另一种将尝试查找仅是混淆字符串的所有函数并将其重命名。 如果无法彻底替换函数名称,则除了截断的重命名外,还将在所有调用位置添加带有详细的反混淆字符串的注释。 安装说明 达尔文 没有特殊说明,建议使用程序包管理器 视窗 没有特殊说明,建议使用程序包管理器 Linux 没有特殊说明,建议使用程序包管理器 最低版本 此插件需要以下最低版本的Binary Ninja: 1528 执照 该插件是根据MIT许可发布的。 元数据版本 2个 立即下载

相关推荐

计算机组成原理(二)—— 数据的表示与运算

本章目录引言一、数制与编码1.1 进位计数制1.1.1 进制及转换1.1.2 真值、机器数1.2 BCD码1.3 ASCII 码1.4 校验码1.4.1 奇偶校验码1.4.2 海明码1.4.3 CRC循环冗余码二、定点数的表示和运算2.1 定点数的表示2.1.1 无符号2.1.2 有符号(原码、反码、补码、移码)2.2 定点数的运算2.2.1 移位运算2.2.2 加减运算(溢出判断)2.2.3 乘法运算2.2.4 除法运算2.3 强制类型转换2.4 数据的存储和排列三、浮点数的表示和运算3.1 浮点数的表示

S mile0804的博客 7478

Golang 中的 bufio 包详解(四):bufio.Scanner

bufio.Scanner 是 Golang 中一个用于逐个读取输入缓冲区的扫描器,通常与 bufio.Reader 一起使用,bufio.Reader 用于从输入中读取数据,而 bufio.Scanner 则用于逐个读取输入缓冲区的内容。bufio.Scanner 可以将输入数据分解为逻辑上的行并返回。Scanner 通过定义一个 Split 函数来将输入分解为行。

路多辛的所思所想 2682

Windows7 64位系统PL2303驱动无法安装问题解决

问题描述:电脑安装的是Win7 64位的旗舰版,USB to RS232这种线很简单,对于笔记本如果要用串口,就不能少了它了。USB to RS232转换芯片种类繁多,常见的有ch340,0108,PL2303,FT232等,这里面FT232的应该价格是相对比较贵的,因为FTDI的芯片本身比较贵。由于买了一根PL2303芯片的USB to RS232转换线,于是插上后发现驱动无法安装,又是在设备管

suxiang198的博客 5810

Go语言学习笔记—golang标准库bufio包

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

qq_39280718的博客 2392

WiseFlow本地搭建实录---保姆教程

本文介绍了如何从0开始搭建wiseflow的个人情报官的方法,目前所有的API全部都是免费的,对机器没有要求,大家可以放心搭建

liuhui244的博客 1962

AUTOSAR入门

一、AUTOSAR是什么 AUTOSAR组织自己的介绍是 AUTOSAR (AUTomotive Open System ARchitecture) is a worldwide development partnership of vehicle manufacturers, suppliers, service providers and companies from the automot...

天涯遍地是小草的博客 3万+

Go源码学习:bufio包 - 1.2 - scan.go -(2)

Go:bufio:Scan、advance、setERR、Buffer、Split、SplitBytes、errorRune、ScanRunes、dropCR、ScanLines

风不归的乐园 1096

EEGnet模型论文讲解(画图详解三种卷积层操作)

我录了一个讲解视频:https://www.bilibili.com/video/BV1si4y1s7g7/ 目录 一、整体介绍 二、梳理激活函数 三、图解三种卷积层 (核心内容) 四、总结 一、整体介绍 EEGnet是为专门一般的脑电图识别任务而设计的通用且紧凑的卷积神经网络。(设计思路借鉴了MobileNet) 下图是EEGnet的整体结构图,只有三个卷积模块,重点是depthwise conv 和separable conv这两个卷积模块。 表格表明了EEGnet的...

Amigo_1997的博客 2万+

golang-bufio 缓冲读

好了,到这里就结束了。这里至少Reader相关的部分,后面还会继续Writer相关的部分。不过,目前还没有特别好的记录方式,只是大致挑几个代码贴出来,写一些自己的理解,然后配一些示意图,再加上一些测试代码。这篇博客不是为了说明这个包是怎么使用的,而是为什么要用它,以及它的一些实现的细节。现这样写吧,以后再探索是不是有更好的方式。

qq_40734247的博客 976

Vue中实现word文档渲染、在线编辑、保存

Vue3对word文档进行渲染、编辑、保存。word转成html,html转成word

h18749849699的博客 1330

UI渲染顺序:合批为何被拆碎?

在 Hierarchy 中,避免出现:Image(列表1) → Text(列表1) → 特效 → Image(列表2) → Text(列表2)…若可行,在逻辑上把布局组织成“同类元素集中”:例如:列表行中,Image 集中、Text 集中;或者接受 Text 本身就拆出一批,关键是不要在 Text 中间再插入别的材质。现实中不一定能做到完美的“所有 Image 连在一起”,但你会有一个意识:同一 Canvas 内,如果你把不同材质的元素交错穿插,

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 85

golang中的bufio

原理 bufio按行读取 func ReadFile(path string) { //打开文件,新建文件 f, err := os.Open(path) if err != nil { fmt.Println("err = ", err) return } //使用完毕,需要关闭文件 defer f.Close() //新建一个缓冲区,把内容放在缓冲区 r := bufio.NewReader(f) for .

1516

基于物联网设计温室水培系统(NBIOT+华为云IOT)_338

本项目设计并实现了一套基于物联网的温室水培系统。系统以STM32F103RCT6单片机为核心控制器,结合SHT30温湿度传感器、SGP30二氧化碳传感器、BH1750光照传感器及液位检测传感器等硬件,实现对温室内环境参数的实时采集。系统支持自动和手动两种控制模式,能够根据传感器数据自动控制补光灯、通风风扇、遮光卷帘、降温水帘及营养液补充电机。通过NBIoT模块,系统可将采集的数据通过MQTT协议上传至华为云IOT平台,用户可通过Android手机APP或Windows上位机进行远程监控与控制。

414

Go 语言从入门到进阶 | 第 10 章:I/O 与文件操作

Go 语言从入门到进阶:耿雨飞。

weixin_43674738的博客 204

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Go源码学习:bufio包 - 1.2 - scan.go -(1)

Go:bufio:Scanner、SplitFunc、Errors、const、NewScanner、Err、Bytes、Text、ErrFinalToken

风不归的乐园 1173

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

go bufio缓冲io详解

bufio介绍 bufio包实现了有缓冲的I/O。它包装一个io.Reader或io.Writer接口对象,创建另一个也实现了该接口,且同时还提供了缓冲和一些文本I/O的帮助函数的对象。 bufio目的 bufio 是通过缓冲来提高效率 简单的说就是,把文件读取进缓冲(内存)之后再读取的时候就可以避免文件系统的io 从而提高速度。同理,在进行写操作时,先把文件写入缓冲(内存),然后由缓冲写入文件系...

爱死亡机器人 2278

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Golang标准库:bufio包 — 缓存IO

bufio 包实现了缓存IO。它包装了 io.Reader 和 io.Writer 对象,创建了另外的Reader和Writer对象,它们也实现了 io.Reader 和 io.Writer 接口,不过它们是有缓存的。该包同时为文本I/O提供了一些便利操作。bufio.Reader 结构包装了一个 io.Reader 对象,提供缓存功能,同时实现了 io.Reader 接口。Reader 结构没有任何导出的字段,结构定义如下: 1.4.1.1 实例化 bufio 包提供了两个实例化 bufio.Reader

学亮编程手记 819

go newscanner判断文件读取结束_深入理解 Go 标准库之 bufio.Scanner

众所周知,带缓冲的 IO 标准库 一直是 Go 中优化读写操作的利器。对于写操作来说,在被发送到 socket 或硬盘之前,IO 缓冲区 提供了一个临时存储区来存放数据,缓冲区存储的数据达到一定容量后才会被"释放"出来进行下一步存储,这种方式大大减少了写操作或是最终的系统调用被触发的次数,这无疑会在频繁使用系统资源的时候节省下巨大的系统开销。而对于读操作来说,缓冲 IO 意味着每次操作能够读取更多...

weixin_29662775的博客 2351

(10-4)文件操作:包bufio

10.4 包bufio 包bufio是 Go 语言标准库中的一个包,用于实现带缓冲的 I/O 操作。包bufio提供了一些方便的函数和类型,可以显著提高数据读写的效率。 10.4.1 包bufio和包io的区别 包bufio和包io是 Go 语言标准库中常用的两个 I/O 操作包,两者之间主要有以下区别: 缓冲方式不同 包bufio提供了带缓冲的读写操作,可以大幅提高文件读写效率。例如,通过使用 bufio.Reader 类型,可以按行读取文件内容,从而避免手动处理每个字节,并显著提高文件读取效

码农三叔 1033

Go源码学习:bufio包 - 1.2 - scan.go -(3)

Go:bufio:isSpace、ScanWords

风不归的乐园 554

Go36-42,43-bufio包

bufio包 这是另一个与I/O操作强相关的代码包。bufio是“buffered I/O”的缩写,这个代码包中的程序实体实现的I/O操作都内置了缓冲区。 主要数据类型 bufio包中的数据类型主要有: Reader Scanner Writer和ReadWriter 与io包中的数据类型类似,这些类型的值也都需要在初始化的时候,包装一个或多个简单I/O接口类型的值。这里的简单I/O接口类...

weixin_33963594的博客 153

标准库bufio个人详解

本文是我有通俗的语言写的如果有误请指出。 先看bufio官方文档 https://studygolang.com/pkgdoc文档地址 主要分三部分Reader、Writer、Scanner 分别是读数据、写数据和扫描器三种数据类型的相关操作 这个扫描后面会详细说我开始也没弄明白其实很简单。 Reader funcNewReaderSize比奇小说网 https://m.b...

爱无止 525

go split 换行_Go源码浅析:bufio中的Scanner

go语言源码的bufio为我们提供了一个有缓存的io读取库,能较大的提高读取的性能,其中的Scanner可以通过自定义分割方法的形式,为我们提供一个可以按某个分隔符进行单条数据读取的便捷方法。比如我们以换行符为分割可以读取一行一行的数据文件,以句号为分割可以读取一句一句的内容。Scanner的定义如下,r是需要我们传入一个实现了Reader接口的实例,split需要我们通过Split方法...

weixin_39855658的博客 618

go 输入输出流(bufio)

bufio 包实现了缓存IO。它包装了 io.Reader 和 io.Writer 对象,创建了另外的Reader和Writer对象,它们也实现了io.Reader和io.Writer接口,不过它们是有缓存的。该包同时为文本I/O提供了一些便利操作。1.1. 1.4.1 Reader 类型和方法bufio.Reader 结构包装了一个 io.Reader 对象,提供缓存功能,同时实现了 io.Re...

tianlongtc的博客 4089

Golang读取单行超长的文本

前言: 最近在探索用Go来读取文件,读取文本时发现,对于单行超长的文本,我的Go代码无法处理。经过查阅才发现,Go提供的Scanner无法读取单行超长文本文件。我这里就来总结一下问题的发现和解决过程。 1.问题复现 首先注释main函数里面的内容,执行 CreateBigText 函数,它会创建一个含有3行内容的文件,第一行是一个长度超过100KB的行。然后解决main函数的注释,尝试执行代码,会发现只有一行错误信息: package main import ( "bufio" "bytes" "

qq_40734247的博客 2084

Go 文件与 IO 操作知识点总结:操作系统底层、源码原理与 bufio 流式高性能实战

本文完整梳理 Go 文件与 IO 核心体系,区分os、io、bufio三大核心包定位。从操作系统文件描述符、用户态缓冲原理切入,详解Reader/Writer抽象接口、文件基础 API、目录与路径操作;重点讲解缓冲 IO,对比bufio.Scanner、bufio.Reader/Writer使用场景,给出超大文件流式处理方案。同时整理大量开发易错坑、权限规则、API 选型标准,并结合简易源码剖析底层实现,覆盖业务开发与面试全部高频考点。

2402_88969947的博客 587
上一篇: Golang bufio包源码分析
下一篇: Golang bytes源码分析
思维的深度
博客等级 码龄11年 2万+粉丝 391原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值