golang的文件读写操作


一、获取文件列表路径

第一步我要获取一个文件列表类似于

[file/DSC_5882.png file/IMG_4634.png file/IMG_4669.png]

具体代码如下:

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
}

二、copy操作

下面我们用到了一个path.split()的函数就是把文件名输出然后再进行路径的拼接,

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)
		}
	}
}

四、 分片读取文件内容分布写入新文件

下面就是一边把文件读出来然后再写入,适用于大文件的io操作

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])
	}

}

五、按行读取

1.1一次性读取,按行拆分并打印

这里就是将文件一次性读取出来然后按行输出, 适合小文件读取。

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)
	}

}

1.2通过bufio按行读取可以用于大文件

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)
	}
}

通过Scanner , scanner的默认大小则是64k

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)
	}
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
### 回答1: 在 Windows 下,Go 语言实现文件锁可以使用标准库中的 `os` 包。可以使用 `os.OpenFile` 函数打开文件,并使用 `os.O_CREATE` 和 `os.O_EXCL` 参数来创建并锁定文件。 以下是一个示例代码: ``` package main import ( "fmt" "os" ) func main() { file, err := os.OpenFile("file.lock", os.O_CREATE|os.O_EXCL, 0666) if err != nil { fmt.Println("文件已被锁定:", err) return } fmt.Println("文件锁定成功") defer file.Close() // do something here } ``` 在上面的代码中,当文件锁定失败时,会返回错误,表示文件已被锁定。否则,文件锁定成功,可以在后面的代码中进行读写操作。 ### 回答2: 在Windows下,可以使用`github.com/alexbrainman/locker`包来实现文件锁。 首先,安装`locker`包: ```shell go get github.com/alexbrainman/locker ``` 接下来,使用以下代码实现文件锁: ```go package main import ( "fmt" "github.com/alexbrainman/locker" ) func main() { // 创建一个文件锁对象 fileLock, err := locker.NewFileLock("path/to/file.lock") if err != nil { fmt.Println("创建文件锁失败:", err) return } // 获取文件锁 err = fileLock.Lock() if err != nil { fmt.Println("获取文件锁失败:", err) return } defer fileLock.Unlock() // 在程序执行完毕后释放文件锁 // 在这里可以执行需要加锁的代码逻辑 fmt.Println("文件锁已获取,执行加锁操作") // 在这里可以执行需要加锁的代码逻辑 fmt.Println("文件锁已释放") } ``` 在上述代码中,首先通过`locker.NewFileLock`函数创建一个文件锁对象,并传入要进行加锁的文件路径。接下来,使用`Lock`方法获取文件锁,如果获取失败,会返回一个错误。在加锁操作之后的代码段,只有在程序执行完毕后才会执行,确保在该代码段执行期间,其他进程无法访问该文件。最后,通过`Unlock`方法释放文件锁。 需要注意的是,加锁的文件应该是一个临时文件,而不是与其他进程共享的重要文件,以防止可能的死锁和资源争夺问题。 ### 回答3: 在Windows下,可以使用Golang中的`os`标准库来实现文件锁。 首先,需要使用`os.OpenFile`函数打开文件,并指定`os.O_RDWR|os.O_CREATE`标志来进行读写操作和创建文件(如果文件不存在的话)。 然后,可以使用`syscall.Flock`函数来对打开的文件应用锁。该函数的第二个参数是`syscall.LOCK_EX`,它会将文件锁定为独占模式,即其他进程无法同时对该文件进行读写操作。 最后,在文件使用完毕后,需要释放文件锁。可以使用`syscall.Flock`函数的第二个参数设置为`syscall.LOCK_UN`来解锁文件。 以下是一个简单的示例代码,演示了如何在Windows下使用Golang实现文件锁: ``` package main import ( "log" "os" "syscall" ) func main() { // 打开文件 file, err := os.OpenFile("test.txt", os.O_RDWR|os.O_CREATE, 0666) if err != nil { log.Fatal(err) } defer file.Close() // 对文件应用锁 err = syscall.Flock(int(file.Fd()), syscall.LOCK_EX) if err != nil { log.Fatal(err) } defer func() { // 解锁文件 err := syscall.Flock(int(file.Fd()), syscall.LOCK_UN) if err != nil { log.Fatal(err) } }() // 进行文件操作,如读取或写入 // 锁定期间其他进程无法对该文件进行读写操作 } ``` 需要注意的是,文件锁在Windows系统下是通过使用Windows API实现的,并不是完全按照POSIX标准库的实现方式。所以,在使用文件锁时,应当注意兼容性问题,并确保适合当前系统的特性和限制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天你学golang了吗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值