Golang 文件操作

2023-05-16

1. 读文件

  • os.Open(name string) (file *File, err error)
  • os.OpenFile(name string, flag int, perm FileMode) (*File, error)
  • ioutil.ReadFile(name string) ([]byte, error)

1.1 带缓存读

func main() {
	file, err := os.Open("./abc.txt")
	if err != nil {
		fmt.Printf("Open file error: %v\n", err)
		return
	}
	defer file.Close()

	reader := bufio.NewReader(file)
	for {
		// 按行读取
		line, err := reader.ReadString('\n')
		if err == io.EOF {
			break
		}
		fmt.Print(line)
	}
}

1.2 一次性读

适合配置文件等小文件

func main() {
	bs, err := ioutil.ReadFile("./abc.txt")
	if err != nil {
		fmt.Printf("Read file error: %v\n", err)
		return
	}

	fmt.Printf("%s\n", bs)
}

1.3 分片读取

func main() {
	file, err := os.Open("abc.txt")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	for {
		buf := make([]byte, 32)
		_, err = file.Read(buf)
		if err == io.EOF {
			break
		}

		if err != nil {
			panic(err)
		}

		fmt.Printf("%s", buf)
	}
}

1.4 寻址 seek

寻址标记 whence: 0-begin, 1-current, 2-end

file, _ := os.Open("abc.txt")
	defer file.Close()

	// 开始位置前进5个字节
	var whence = 0
	var offset int64 = 5
	pos, _ := file.Seek(offset, whence)
	fmt.Println("Jump forward 5 bytes from start position:", pos)

	// 当前位置回退2个字节
	whence = 1
	offset = -2
	pos, _ = file.Seek(offset, whence)
	fmt.Println("Jump back 2 bytes from current position:", pos)
}

1.5 分隔符读取

  • bufio.NewScanner(r io.Reader) *Scanner
func main() {
	file, _ := os.Open("abc.txt")
	defer file.Close()

	scanner := bufio.NewScanner(file)

	// 分隔函数,默认 bufio.ScanLines
	scanner.Split(bufio.ScanWords)

	for scanner.Scan() {
		fmt.Println(scanner.Text())
	}

	err := scanner.Err()
	if err != nil {
		panic(err)
	}
}

1.6 按行读取

func main() {
	file, err := os.Open("abc.txt")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	// 放入缓冲读
	reader := bufio.NewReader(file)

	for {
		// 自动丢失结尾符 \n
		line, _, err := reader.ReadLine()
		if err == io.EOF {
			break
		}
		if err != nil {
			panic(err)
		}

		fmt.Printf("%s\n", line)
	}
}

2. 写文件

  • os.OpenFile(name string, flag int, perm FileMode) (file *File, err error)
  • os.Create(name string) (*File, error)
  • io/ioutil.Write(filename string, data []byte, perm fs.FileMode) error

文件操作模式:

  • 覆盖写:os.O_WRONLY | os.O_TRUNC
  • 追加写:os.O_WRONLY | os.O_APPEND
  • 读写并追加:os.O_RDWR | os.OS_APPEND

2.1. 常规写

func writeFile() {
	file, err := os.OpenFile("abc.txt", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644)
	if err != nil {
		panic(err)
	}
	defer file.Close()

	byteSlice := []byte("hello world!")
	bytesWritten, err := file.Write(byteSlice)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Wrote %d bytes\n", bytesWritten)
}

2.2 快速写

覆盖写:

func main() {
	err := ioutil.WriteFile("abc.txt", []byte("add a new line"), 0644)
	if err != nil {
		panic(err)
	}
}

2.3 缓冲写

bufio 包:

func NewWriter(w io.Writer) *Writer
func NewWriterSize(w io.Writer, size int) *Writer

func (b *Writer) Write(p []byte) (nn int, err error)
func (b *Writer) WriteString(s string) (int, error)
func (b *Writer) WriteByte(c byte) error
func (b *Writer) WriteRune(r rune) (size int, err error)

func (b *Writer) Flush() error
func bufferedWrite() {
	file, err := os.OpenFile("abc.txt", os.O_WRONLY, 0644)
	if err != nil {
		panic(err)
	}
	defer file.Close()

	// 缓冲写
	bufferedWriter := bufio.NewWriter(file)

	// 写入字节
	bytesWritten, err := bufferedWriter.Write([]byte{65, 66, 47, '\n'})
	if err != nil {
		panic(err)
	}
	fmt.Printf("Bytes written: %d\n", bytesWritten)

	// 写入字符串
	bytesWritten, err = bufferedWriter.WriteString("Buffered string\n")
	if err != nil {
		panic(err)
	}
	fmt.Printf("Bytes written: %d\n", bytesWritten)

	// 缓冲中的字节数
	unflushedBufferSize := bufferedWriter.Buffered()
	fmt.Printf("Bytes buffered: %d\n", unflushedBufferSize)

	// 未使用缓存的大小
	bytesAvailable := bufferedWriter.Available()
	fmt.Printf("Available buffer: %d\n", bytesAvailable)

	// 写入磁盘
	bufferedWriter.Flush()

	// 重置缓存写,将丢弃缓存内容
	bufferedWriter.Reset(bufferedWriter)

	bytesAvailable = bufferedWriter.Available()
	fmt.Printf("Available buffer after reset: %d\n", bytesAvailable)

	// 重置缓存大小
	bufferedWriter = bufio.NewWriterSize(bufferedWriter, 8000)

	// 重置后的缓存大小
	bytesAvailable = bufferedWriter.Available()
	fmt.Printf("Available buffer after set buffered size: %d\n", bytesAvailable)
}

简单:

func main() {
	file, err := os.OpenFile("abc.txt", os.O_CREATE|os.O_WRONLY, 0600)
	if err != nil {
        panic(err)
	}
	defer file.Close()

	msg := "Hello World!\n"

	writer := bufio.NewWriter(file)
	for i := 0; i < 5; i++ {
		writer.Write([]byte(msg))
	}
	writer.Flush()
}

3. 拷贝文件

3.1 直接拷贝

适合小文件、文本文件

func main() {
	bs, err := ioutil.ReadFile("abc.txt")
	if err != nil {
        panic(err)
	}

	err = ioutil.WriteFile("abc.txt", bs, 0600)
	if err != nil {
		 panic(err)
	}
}

3.2 缓冲拷贝

io 包,适合大文件、二进制文件:

// 默认缓冲区大小
func Copy(dst Writer, src Reader) (written int64, err error)

// 自定义缓冲区大小
func CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error)
func CopyFile(dstFileName, srcFileName string) (written int64, err error) {
	srcFile, err := os.OpenFile(srcFileName, os.O_RDONLY, 0)
	if err != nil {
		return 0, err
	}
	defer srcFile.Close()

	dstFile, err := os.OpenFile(dstFileName, os.O_CREATE|os.O_WRONLY, 0600)
	if err != nil {
		return 0, err
	}
	defer dstFile.Close()

	writer := bufio.NewWriter(dstFile)
	reader := bufio.NewReader(srcFile)

	written, err = io.Copy(writer, reader)
    
    // flush to disk
	err = writer.Sync()
	if err != nil {
		return 0, err
	}

	return
}

4. 统计文件

4.1 文件信息

func statFile() {
	fileInfo, err := os.Stat("abc.txt")
	if err != nil {
        // 判断文件是否存在
		if os.IsNotExist(err) {
			fmt.Println("file not exist")
		}
		panic(err)
	}

	fmt.Println("File name:", fileInfo.Name())
	fmt.Println("Size in bytes:", fileInfo.Size())
	fmt.Println("Permissions:", fileInfo.Mode())
	fmt.Println("Last modified:", fileInfo.ModTime())
	fmt.Println("Is directory:", fileInfo.IsDir())
	fmt.Printf("System interface type: %T\n", fileInfo.Sys())
	fmt.Printf("System info: %+v\n", fileInfo.Sys())
}

4.1 字符统计

type Statistic struct {
	Char   int
	Number int
	Space  int
	Other  int
}

func main() {
	file, err := os.Open("./abc.txt")
	if err != nil {
		fmt.Printf("Open file error: %v\n", err)
		return
	}
	defer file.Close()

	stat := Statistic{}

	reader := bufio.NewReader(file)
	for {
		bs, err := reader.ReadString('\n')
		if err == io.EOF {
			break
		}

		for _, c := range []rune(bs) {
			switch {
			case c >= 'a' && c <= 'z':
				fallthrough
			case c >= 'A' && c <= 'Z':
				stat.Char++
			case c >= '0' && c <= '9':
				stat.Number++
			case c == ' ' || c == '\t':
				stat.Space++
			default:
				stat.Other++
			}
		}
	}

	fmt.Printf("%v\n", stat)
}

5. 目录遍历

filepath 包:

  • type WalkFunc func(path string, info os.FileInfo, err error) error
  • func Walk(root string, walkFn WalkFunc) error
func main() {
	err := filepath.Walk("/tmp", walkFunc)
	if err != nil {
		panic(err)
	}
}

func walkFunc(path string, info fs.FileInfo, err error) error {
	fmt.Println(path)

	return nil
}

7. 压缩文件

7.1 zip

7.1.1 压缩

func zipCompress() {
	target := "/var/log"
	zipFilename := fmt.Sprintf("%s.zip", filepath.Base(target))

	// 压缩文件
	writer, err := os.Create(zipFilename)
	if err != nil {
		log.Fatal(err)
	}
	defer writer.Close()

	err = CompressZip(target, writer)
	if err != nil {
		log.Fatal(err)
	}
}

func CompressZip(rootDir string, writer io.Writer) (err error) {
	// writer
	zipWriter := zip.NewWriter(writer)
	defer zipWriter.Close()

	// 遍历写入文件
	err = filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// 压缩包头信息
		header, err := zip.FileInfoHeader(info)
		if err != nil {
			return err
		}

		// 文件名,去除最外层的
		header.Name = strings.TrimPrefix(path, filepath.Dir(rootDir))
		if info.IsDir() {
			header.Name += "/"
		}

		// 普通文件,进行压缩
		if info.Mode().IsRegular() {
			header.Method = zip.Deflate
		}

		// 创建压缩包头信息
		fileWriter, err := zipWriter.CreateHeader(header)
		if err != nil {
			return err
		}

		// 非文件,直接返回
		if !info.Mode().IsRegular() {
			return nil
		}

		// 打开待压缩的文件
		reader, err := os.Open(path)
		if err != nil {
			return err
		}
		defer reader.Close()

		// 写入文件
		_, err = io.Copy(fileWriter, reader)

		return err
	})

	return
}

7.1.2 解压

func zipExtract() {
	zipFilename := `C:\Users\MSN\Downloads\log.zip`

	// 解压文件
	err := ExtractZip(zipFilename)
	if err != nil {
		log.Fatal(err)
	}
}


func ExtractZip(zipFilename string) error {
	baseDir := filepath.Dir(zipFilename)

	zipReader, err := zip.OpenReader(zipFilename)
	if err != nil {
		return err
	}
	defer zipReader.Close()

	for _, file := range zipReader.Reader.File {
		err = func(file *zip.File) error {
			zippedFile, err := file.Open()
			if err != nil {
				return err
			}
			defer zippedFile.Close()

			extractedFilePath := filepath.Join(baseDir, file.Name)

			if file.FileInfo().IsDir() {
				err = os.MkdirAll(extractedFilePath, file.Mode())
				if err != nil {
					return err
				}
			} else if file.FileInfo().Mode().IsRegular() {
				outputFile, err := os.OpenFile(extractedFilePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, file.Mode())
				if err != nil {
					return err
				}
				defer outputFile.Close()

				_, err = io.Copy(outputFile, zippedFile)
				if err != nil {
					return err
				}
			} else {
				log.Printf("unknown type: %c in %s\n", file.Mode().Type(), file.Name)
			}

			return nil
		}(file)

		if err != nil {
			return err
		}
	}

	return nil
}

7.2 tar & gzip

7.2.1 压缩

func tgzCompress() {
	target := "/var/log"
	tgzFilename := fmt.Sprintf("%s.tar.gz", filepath.Base(target))

	// 压缩文件
	writer, err := os.Create(tgzFilename)
	if err != nil {
		log.Fatal(err)
	}
	defer writer.Close()

	err = CompressTarGz(target, writer)
	if err != nil {
		log.Fatal(err)
	}
}

func CompressTarGz(rootDir string, writer io.Writer) (err error) {
	gzipWriter := gzip.NewWriter(writer)
	defer gzipWriter.Close()

	tarWriter := tar.NewWriter(gzipWriter)
	defer tarWriter.Close()

	// 遍历写入文件
	err = filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		var link string
		if info.Mode()&os.ModeSymlink == os.ModeSymlink {
			if link, err = os.Readlink(path); err != nil {
				return err
			}
		}

		// 压缩包头信息
		header, err := tar.FileInfoHeader(info, link)
		if err != nil {
			return err
		}

		// 文件名,去除最外层的
		header.Name = strings.TrimPrefix(path, filepath.Dir(rootDir))

		// 创建压缩包头信息
		err = tarWriter.WriteHeader(header)
		if err != nil {
			return err
		}

		// nothing more to do for non-regular
		if !info.Mode().IsRegular() {
			return nil
		}

		// 打开待压缩的文件
		reader, err := os.Open(path)
		if err != nil {
			return err
		}
		defer reader.Close()

		// 写入文件
		_, err = io.Copy(tarWriter, reader)

		return err
	})

	return
}

7.2.2 解压

func tgzExtract() {
	tgzFilename := `C:\Users\MSN\Downloads\log.tar.gz`
	baseDir := filepath.Dir(tgzFilename)

	// 解压文件
	reader, err := os.Open(tgzFilename)
	if err != nil {
		log.Fatal(err)
	}
	defer reader.Close()

	err = ExtractTarGz(reader, baseDir)
	if err != nil {
		log.Fatal(err)
	}
	reader.Close()
}

func ExtractTarGz(reader io.Reader, baseDir string) error {
	gzipReader, err := gzip.NewReader(reader)
	if err != nil {
		return err
	}

	tarReader := tar.NewReader(gzipReader)

	for {
		header, err := tarReader.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			return err
		}

		filename := filepath.Join(baseDir, header.Name)

		switch header.Typeflag {
		case tar.TypeDir:
			if err = os.MkdirAll(filename, fs.FileMode(header.Mode)); err != nil {
				return err
			}
		case tar.TypeReg:
			outFile, err := os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, fs.FileMode(header.Mode))
			if err != nil {
				return err
			}
			_, err = io.Copy(outFile, tarReader)
			if err != nil {
				return err
			}
			outFile.Close()
		default:
			log.Printf("unknown type: %c in %s\n", header.Typeflag, header.Name)
		}
	}

	return nil
}

8. 临时文件

未指定目录时,在系统临时目录下创建,名称随机的

func main() {
	tmpDir, err := ioutil.TempDir("", "temp")
	if err != nil {
		panic(err)
	}
	defer os.RemoveAll(tmpDir)

	tmpFile, err := ioutil.TempFile(tmpDir, "tmp.txt")
	if err != nil {
		panic(err)
	}
	defer tmpFile.Close()

	var i byte
	for i = 0; i < 127; i++ {
		_, err = tmpFile.Write([]byte{i})
		if err != nil {
			panic(err)
		}
	}
}

9. 其他操作

// 清空文件 100 bytes
err := os.Truncate("abc.txt", 100)

// 重命名
err := os.Rename(oldPath, newPath)

// 删除文件
err := os.Remove("abc.txt")

// 文件权限
err := os.Chmod("abc.txt", 0700)

// 文件所有者
err := os.Chown("abc.txt", os.Getuid(), os.Getgid())

// 文件时间戳
lastAccessTime := time.Now().Add(30 * time.Second)
lastModifyTime := time.Now().Add(-2 * time.Hour)
err := os.Chtimes("abc.txt", lastAcessTime, lastModifyTime)

// 硬链接
err := os.Link("abc.txt", "abc.txt.1")

// 软链接
err := os.Symlink("abc.txt", "abc_sym.txt")
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Golang 文件操作 的相关文章

  • QT读取XML

    读取XML 1 读取根节点 xff1a QDomElement root 61 doc documentElement 2 读取第一个子节点 xff1a QDomNode node 61 root firstChild 3 读取下一个子节点

随机推荐

  • C++基础入门学习笔记

    C 43 43 基础入门 1 1 hello world include lt iostream gt using namespace std int main cout lt lt 34 Hello world 34 lt lt endl
  • Android的Handler的简单理解和使用

    简单来说 xff0c Handler就是用来传递消息的 Handler可以当成子线程与主线程的消息传送的纽带 在安卓开发中 xff0c 在子线程中无法刷新UI xff0c 是因为UI在子线程中刷新的话 xff0c 是不安全的 xff0c 就
  • 使用datax-web把oracle数据库中的数据导入到mysql

    一 所需环境 Windows系统电脑 Python2 7 18 xff08 需要配置环境变量 xff09 oracle环境 mysql环境 jdk1 8 navicat git python安装下载 https www python org
  • 自己动手做后端(三)用户登录系统

    前言 用户登录系统 xff0c 最简单的解释是将用户账号和密码传输到后端 xff0c 后端将传过来的账号和密码信息与数据库进行比对 xff0c 如果正确则登陆成功 这一简单的描述可以概况绝大部分用户登录系统 xff0c 但是真正实现的时候
  • 单片机小白学习之路(十五)---定时器和计数器的理解(一)

    目标 xff1a 定时器和计数器的理解 一 1 定时器 计数器简介 定时器 计数器 xff08 Timer Counter xff0c 简称T C xff09 是单片机中最基本的接口之一 即可以定时又可以计数 常用于计数 延时 测量周期 脉
  • stm32---ADXL345

    ADXL345是一款三轴加速度传感器 xff0c 广泛用于手机 游戏手柄等设计 ADXL 支持标准的 I2C 或 SPI 数字接口 xff0c 自带 32 级 FIFO 存储 xff0c 并且内 部有多种运动状态检测和灵活的中断方式等特性
  • HZ和秒之间换算

    Hz和毫秒不能直接换算 xff0c 两者是交流电频率与周期的关系 xff0c 并且是倒数关系 xff1a 周期T 61 1 100 61 0 01秒 61 10毫秒 100Hz即100次 秒 xff0c 即60x100 60秒 xff0c
  • 野火 FireConfig 从SD卡下载镜像到EMMC

    1 用balenaEtcher把镜像下载到SD卡 2 拨码到SD卡启动 3 用MobaXterm当串口终端 xff0c 选择115200 xff0c 取消硬件流 4 输入用户名cat 密码fish 5 输入sudo fire config
  • K8S 网络策略

    1 网络策略 NetworkPolicy 是一种以应用为中心的结构 xff0c 允许你设置如何允许 Pod 与网络上的各类网络 实体 通信 xff0c 在 IP Port L3 L4 层面控制网络流量 xff0c 用于隔离应用以减少攻击面
  • VCC、VDD、VSS以及VBAT的区别

    原链接 xff1a https blog csdn net LemonLeeB article details 99417945 在STM32 的学习中 xff0c 发现有几种看起来相关的名称 xff0c 分别是VCC VDD VSS VB
  • LWIP_MDNS

    一 xff0e mdns1 什么是mdns xff1f mDNS协议适用于局域网内没有DNS服务器时的域名解析 xff0c 设备通过组播的方式交互DNS记录来完成域名解析 xff0c 约定的组播地址是 xff1a 224 0 0 251 x
  • 组播IGMP

    一 xff0e 什么是组播 xff1f 1 一个发送 组播源 xff0c 多个接收 xff0c 接收的有个特点就是在同一个组播组里面 xff0c 组播组有自己的IP 2 对于组播源来说 xff0c 发送命令到组播IP等于把命令发送到所有组成
  • 单片机小白学习之路(四十三)---LCD12864液晶显示

    目标 xff1a LCD12864原理的理解 1 LCD12864简介 LCD12864可以用来显示字符 数字 汉字 图形等内容 xff0c 其分辨率是128 64点 意思是横着有128个点 xff0c 竖直方向有64点 LCD12864
  • stm32---红外接受

    一个脉冲对应 560us 的连续载波 xff0c 一个逻辑 1 传输需要 2 25ms xff08 560us 脉冲 43 1680us 低电平 xff09 xff0c 一个逻辑 0 的传输需要 1 125ms xff08 560us 脉冲
  • 串口通信的校验---奇偶校验,0校验,1校验

    捕获 PNG 设置为奇校验 xff0c 先看发送方将要发送的一帧数据中有几个1 xff0c 如果是偶数个1则校验位置1 xff0c 保证1的个数是奇数 如果是奇数就置0 保证是奇数后发送给接收方 xff0c 接受方此时要检查发送的数据位是否
  • printf重定向

    C语言中printf默认输出设备是显示器 xff0c 当开发板没有时我们就用串口来打印数据 int fputc int ch FILE p USART SendData USART1 ch 如果用串口2打印 xff0c 和换成USART2
  • SPI的CRC校验计算

    22 3 6 CRC计算 CRC校验仅用于保证全双工通信的可靠性 数据发送和数据接收分别使用单独的CRC计算器 通过对每一个接收位进行可编程的多项式运算来计算CRC CRC的计算是在由SPI CR1寄存器 中CPHA和CPOL位定义的采样时
  • 每天一道算法练习题--Day21&& 第一章 --算法专题 --- ----------位运算

    我这里总结了几道位运算的题目分享给大家 xff0c 分别是 136 和 137 xff0c 260 和 645 xff0c 总共加起来四道题 四道题全部都是位运算的套路 xff0c 如果你想练习位运算的话 xff0c 不要错过哦 xff5e
  • argparse库的作用及其用法详解

    一 背景 当一个项目的输入参数较多 xff0c 且要进行修改和调试时 xff0c 经常涉及到参数的格式和路径问题 如果一行一行去进行修改代码 xff0c 会非常繁琐且错误率很高 argparse模块就是为了解决这个问题 二 作用 argpa
  • Golang 文件操作

    1 读文件 os Open name string file File err error os OpenFile name string flag int perm FileMode File error ioutil ReadFile