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)
}
}
先使用 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()
}
使用 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
}
使用 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。