golang的文件操作

获取文件列表路径

package _case

import (
	"fmt"
	"log"
	"os"
	"strings"
)

// 获取文件路径
// 源文件目录
const sourceDir = "file/"

// 目标文件目录
const destDir = "det_file/"

// 拿到目录下完整的路径
func geFiles(dir string) []string {
	//读取目录
	fs, err := os.ReadDir(dir)
	if err != nil {
		log.Fatal()
	}
	//定义一个list接收我们的文件路径
	list := make([]string, 0)
	for _, f := range fs {
		//如果是个空的文件夹就继续
		if f.IsDir() {
			continue
		}
		//去掉字符串s中首部以及尾部与字符串cutset中每个相匹配的字符   //Name返回条目所描述的文件(或子目录)的名称。
		fullName := strings.Trim(dir, "/") + "/" + f.Name()
		list = append(list, fullName)
		fmt.Println(list)
	}
	return list
}

文件目录拷贝

package _case

//文件复制
import (
	"io"
	"log"
	"os"
	"path"
)

// 拷贝目录到目录
func Copy() {
	list := geFiles(sourceDir)
	for _, f := range list {
		//Split 函数将路径从最后一个斜杠后面位置分隔为两个部分( dir 和 file )并返回。如果路径中没有斜杠,
		//函数返回值 dir 会设为空字符串, file 会设为 path 。两个返回值满足 path == dir+file
		_, name := path.Split(f)                 //把文件名输出
		destFileName := destDir + "copy/" + name //这个name是把文件名放在了目标文件加后
		//fmt.Println(destFileName)
		//复制文件
		CopyFile(f, destFileName)
	}
}

func CopyFile(srcName, destName string) (int64, error) {
	//打开源文件
	src, err := os.Open(srcName)
	if err != nil {
		log.Fatal(err)
	}
	defer src.Close()
	//打开目标文件   可读可写可创建
	det, err := os.OpenFile(destName, os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Fatal(err)
	}
	defer det.Close()
	return io.Copy(det, src)
}
一次性读取文件内容并写入

读取文件内容并写入

package _case

import (
	"log"
	"os"
	"path"
)

// 一次性读取文件内容并写入
func ReadWriteFiles() {
	//获取源文件路径
	list := geFiles(sourceDir)
	for _, f := range list {
		bytes, err := os.ReadFile(f)
		if err != nil {
			log.Fatal(err)
		}
		_, name := path.Split(f)
		destname := destDir + "normal/" + name
		err1 := os.WriteFile(destname, bytes, 0644)
		if err1 != nil {
			log.Fatal(err1)
		}
	}
}

分片读取文件并写入

package _case

import (
	"io"
	"log"
	"os"
	"path"
)

// 适用大文件
// 分片读取文件内容分布写入新文件
func OneSideReadWriteToDest() {
	list := geFiles(sourceDir)
	for _, f := range list {
		_, name := path.Split(f)
		destFileName := destDir + "one_side/" + name
		//文件写入
		OneSideReadWrite(f, destFileName)

	}
}
func OneSideReadWrite(srcName, destName string) {
	src, err := os.Open(srcName)
	if err != nil {
		log.Fatal("1", err)
	}
	defer src.Close()
	dst, err := os.OpenFile(destName, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
	if err != nil {
		log.Fatal("2", err)
	}
	defer dst.Close()
	//切片 文件最大的限度
	buf := make([]byte, 1024)
	for {
		n, err := src.Read(buf)
		if err != nil && err != io.EOF { //如果没有这个io.EOF的话就会报错
			log.Fatal("3...", err)
		}
		if n == 0 {
			break
		}
		dst.Write(buf[:n])
	}

}

一次性读取按行拆分

const README = "README.MD"
func ReadLine1() {
	fileHeader, err := os.OpenFile(README, os.O_RDONLY, 0444)
	if err != nil {
		log.Fatal(err)
	}
	defer fileHeader.Close()
	//将文件一次性读取出来
	bytes, err := io.ReadAll(fileHeader)
	if err != nil {
		log.Fatal(err)
	}
	list := strings.Split(string(bytes), "\n")
	for _, i := range list {
		fmt.Println(i)
	}

}

按行读取用于大文件

bufio 通过对io模块的封装提供了数据的缓冲功能,能一定程度减少大文件数据块带来的开销。当发起读写操作时,会尝试从缓冲区读取数据,缓冲区没有数据后,才会从数据源去读取缓冲区大小默认为4k

func ReadLine2() {
	fileHeader, err := os.OpenFile(README, os.O_RDONLY, 0444)
	if err != nil {
		log.Fatal(err)
	}
	defer fileHeader.Close()
	reader := bufio.NewReader(fileHeader)
	for true {
		//加上分隔符
		line, err := reader.ReadString('\n')
		if err == io.EOF {
			break
		}
		fmt.Print(line)
	}
}

func ReadLine3() {
	fileHeader, err := os.OpenFile(README, os.O_RDONLY, 0444)
	if err != nil {
		log.Fatal(err)
	}
	defer fileHeader.Close()
	scanner := bufio.NewScanner(fileHeader)
	for scanner.Scan() {
		line := scanner.Text()
		fmt.Println(line)
	}
}

Scanner按行读取文件

先使用 NewScanner() 创建 Scanner 对象。然后在 for 循环中,使用 Scanner 的 Scan() 方法读取文件的每一行,在使用 Text() 方法获取每一行的内容。最后,将获取到的行追加到字符串切片中。

func ReadLines(path string) ([]string, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	var lines []string
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}
	return lines, scanner.Err()
}

Reader 读取每一行

使用 bufio.Reader 时,需用 ReadBytes() 或 ReadString() 方法来读取每一行。使用 NewReader() 函数创建一个 Reader 对象。在 for 循环中,我们使用 ReadString() 函数读取每一行的内容,并将其追加到字符串切片中。

func ReadLinesV2(path string) ([]string, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	var lines []string
	reader := bufio.NewReader(file)
	for {
		// ReadString reads until the first occurrence of delim in the input,
		// returning a string containing the data up to and including the delimiter.
		line, err := reader.ReadString('\n')
		if err == io.EOF {
			lines = append(lines, line)
			break
		}
		if err != nil {
			return lines, err
		}
		lines = append(lines, line[:len(line)-1])
	}
	return lines, nil
}

ReadLine 按行读取

使用 bufio.Reader 逐行读取文件时,除使用 ReadBytes() 或 ReadString() 方法,可以用 ReadLine() 函数

func ReadLinesV3(path string) ([]string, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	var lines []string
	r := bufio.NewReader(f)
	for {
		// ReadLine is a low-level line-reading primitive.
		// Most callers should use ReadBytes('\n') or ReadString('\n') instead or use a Scanner.
		bytes, _, err := r.ReadLine()
		if err == io.EOF {
			break
		}
		if err != nil {
			return lines, err
		}
		lines = append(lines, string(bytes))
	}
	return lines, nil
}

使用 bufio.Reader 的 ReadLine() 方法可以读取一行数据,但是需要注意它的返回值。ReadLine() 函数的返回值包括三个部分:读取到的数据、是否读取完整一行以及错误信息。如果读取到的数据超出了缓存区的大小,它会返回一个错误信息,而不是完整的一行数据。

因此,如果读取的一行数据的长度超过了缓存区的大小,ReadLine() 函数将无法读取到完整的一行数据。为了避免这种情况的发生,我们可以通过设置缓存区的大小来解决。

ReadLine 是一个低级的行读取原语。大多数调用者应该使用 ReadBytes(‘\n’) 或 ReadString(‘\n’),或者使用 Scanner。

你可能感兴趣的:(Goland,golang)