惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
A
About on SuperTechFans
IT之家
IT之家
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Blog — PlanetScale
Blog — PlanetScale
aimingoo的专栏
aimingoo的专栏
云风的 BLOG
云风的 BLOG
The GitHub Blog
The GitHub Blog
Vercel News
Vercel News
G
Google Developers Blog
J
Java Code Geeks
宝玉的分享
宝玉的分享
T
Tailwind CSS Blog
Cloudbric
Cloudbric
L
LINUX DO - 最新话题
MyScale Blog
MyScale Blog
H
Heimdal Security Blog
PCI Perspectives
PCI Perspectives
Attack and Defense Labs
Attack and Defense Labs
S
Security @ Cisco Blogs
Latest news
Latest news
I
Intezer
L
Lohrmann on Cybersecurity
C
CXSECURITY Database RSS Feed - CXSecurity.com
月光博客
月光博客
T
Threatpost
博客园 - 【当耐特】
S
Schneier on Security
P
Privacy International News Feed
G
GRAHAM CLULEY
T
Tenable Blog
AWS News Blog
AWS News Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
雷峰网
雷峰网
博客园 - Franky
Engineering at Meta
Engineering at Meta
美团技术团队
S
Secure Thoughts
T
Troy Hunt's Blog
Microsoft Security Blog
Microsoft Security Blog
SecWiki News
SecWiki News
V
Visual Studio Blog
人人都是产品经理
人人都是产品经理
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Cisco Talos Blog
Cisco Talos Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Martin Fowler
Martin Fowler
Webroot Blog
Webroot Blog
Google DeepMind News
Google DeepMind News
H
Hackread – Cybersecurity News, Data Breaches, AI and More

博客园 - dribs

PD分离 基于GPT2训练构建医疗问诊机器人 物流行业信息咨询智能问答系统 day8 golang-chan-协程-定时器-锁-等待组 day7 golang GMP golang面试题单向链表和双向链表 golang 自行实现一个base64加密 golang标准库log+第三方zerolog golang标准库序列化反序列化 json + 第三方msgpack golang 标准库 目录操作 golang-day1 进制 golang-标准库时间time day6 golang-标准库(随时更新) golang--day5结构体+结构体排序+错误处理+结构体和接口实现面向对象的例子 golang-day4函数 ceph warn oldest client/flush tid ceph 扩容后healt-error k8s系列---pod手动驱逐 k8s系列---Chart(下)
golang-标准库文件操作
dribs · 2023-02-26 · via 博客园 - dribs

2023-02-26 18:00  dribs  阅读(63)  评论()    收藏  举报

package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func example1() {
	filename := "e:/test.txt" //内容为abc
	//Open是只读方式打开 实际是调用的OpenFile(name, O_RDONLY, 0)
	if f, err := os.Open(filename); err == nil {
		defer f.Close()
		fmt.Printf("%T,%[1]v\n", f)
		buffer := make([]byte, 2)
		for {
			n, err := f.Read(buffer)
			fmt.Println(n, err)
			if n == 0 {
				break //什么都没读取到,说明读到了文件的结尾EOF
			}
			////97 98
			////99 98 buffer 读abc 以2字节读取会多98(b),覆盖方式print
			//fmt.Println(buffer)

			//正常读取切出来的abc,byte强制类型转换成string
			fmt.Println(buffer[:n], string(buffer[:n]))
		}
	}

}

//带指针读取
func example2() {
	filename := "e:/test.txt" //内容为0123456789
	if f, err := os.Open(filename); err == nil {
		defer f.Close()
		buffer := make([]byte, 5)
		var n int
		//指定位置,从头向后偏移3字节开始读取长度5
		n, _ = f.ReadAt(buffer, 3)
		fmt.Println(n, f.Fd(), f.Name()) //5 384 e:/test.txt
		//[51 52 53 54 55] 5 5 34567
		fmt.Println("1:", buffer, len(buffer), cap(buffer), string(buffer[:n]))

		//Read不共用ReadAt的seek指针
		n, _ = f.Read(buffer)
		fmt.Println("2:", buffer, n, len(buffer), cap(buffer), string(buffer[:n]))
		n, _ = f.Read(buffer)
		fmt.Println("3:", buffer, n, len(buffer), cap(buffer), string(buffer[:n]))
		n, _ = f.Read(buffer)
		//读到结尾,如果有回车,就是13 10 两个字节\r\n
		fmt.Println("4:", buffer, n, len(buffer), cap(buffer), buffer[:n])

		//Seek(offset int64,whence int)的whence
		//whence=0 相对于开头,offset只能正,负报错
		//whence=1 相对于当前,offset可正可负,负指针不能超左边界
		//whence=2 相对于结尾,offset可正可负,负指针不能超左边界
		off, e := f.Seek(0, 1)
		if e == nil {
			fmt.Println(off, "------")
			buffer = make([]byte, 5)
			n, _ = f.Read(buffer)
			fmt.Println(n, buffer)
		} else {
			fmt.Println(e)
		}
	}
}

//带缓冲读取
func example3() {
	filename := "e:/test.txt" //内容为0123456789\nabc\nxyz
	if f, err := os.Open(filename); err == nil {
		defer f.Close()
		reader := bufio.NewReader(f) //File实现了Read方法
		//reader 可以按照字节或字符读取
		b1, err := reader.ReadBytes('5')
		fmt.Println("b1:", b1, string(b1), err) //012345 <nil>
		b2 := make([]byte, 3)
		n, err := reader.Read(b2)
		fmt.Println("b2:", n, b2, string(b2[:n]), err) //3 [54 55 56] 678 <nil>
		b3, err := reader.ReadBytes('\n')
		fmt.Println("b3:", b3, string(b3), err) //b3: [57 13 10] 9\n nil
		b4, err := reader.ReadSlice('\n')
		fmt.Println("b4:", b4, string(b4), err) // [97 98 99 13 10] abc \n nil
		line, err := reader.ReadString('\n')
		fmt.Println(line, err) //xyz EOF 意思是读到了文件末尾EOF还没有找到\n
		fmt.Println(
			strings.TrimRight(line, "\n"), //移除右边的换行符
		)

	}
}

//flag
func example4() {
	filename := "e:/test1.txt"
	flag := os.O_RDONLY //只读 写不报错但也写不进去
	//flag = os.O_WRONLY               //只写 从头写 文件必须存在
	//flag = os.O_WRONLY | os.O_CREATE //文件不存在就创建后写入,文件存在就写入从头写覆盖
	//flag = os.O_CREATE               //相当于 os.O_WRONLY | os.O_CREATE
	//flag = os.O_WRONLY | os.O_APPEND //文件末尾追加写,但是文件得存在
	//flag = os.O_APPEND               //相当于os.O_WRONLY|os.O_APPEND
	//flag = os.O_EXCL                 //不要单独使用
	//flag = os.O_EXCL | os.O_CREATE //文件存在报错。不存在创建从头写
	//flag = os.O_RDWR                 //既能读又能写。从头开始,要求文件存在

	f, err := os.OpenFile(filename, flag, 0o640)
	if err == nil {
		defer f.Close()
		fmt.Println(f)
		f.WriteString("abcd")
		f.WriteString("efg")
	} else {
		fmt.Println(err, "!!!")
	}
}

//带缓冲区的读写
func example5() {
	filename := "e:/test2.txt"
	flag := os.O_RDWR | os.O_CREATE | os.O_TRUNC
	if f, err := os.OpenFile(filename, flag, os.ModePerm); err == nil {
		defer f.Close()
		r := bufio.NewReader(f)
		w := bufio.NewWriter(f)
		w.WriteString("0123456789\n")
		w.WriteString("abcd\n")
		w.Flush() //写入

		f.Seek(0, 0) //底层共用同一个f,指针已经指到了EOF,00拉回到开始
		fmt.Println(r.ReadString('\n'))
		//f.Seek(0, 0) //这个seek在这里其实是没用的,内部有自己的记录,如果加了这个seek,读到结尾在读就又从头开始读了,文件读写中不要乱动指针
		fmt.Println(r.ReadString('\n'))
		//fmt.Println(r.ReadString('\n'))    //又循环去读了 配合 上面注释的f.seek
	} else {
		fmt.Println(err, "!!")
	}
}

func main() {
	//example1()
	//example2()
	//example3()
	//example4()
	example5()

}