当前位置: 首页 > news >正文

Golang 文件操作

读取

  1. 一次性读取
data, err := os.ReadFile("filename.txt")
if err != nil {log.Fatal(err)
}
fmt.Println(string(data))
  1. 按行读取

方式1:bufio.NewScanner

file, err := os.Open("filename.txt")
if err != nil {panic(err)
}
defer file.Close()scanner := bufio.NewScanner(file)
for scanner.Scan() {fmt.Println(scanner.Text())
}if err := scanner.Err(); err != nil {log.Fatal(err)
}

方式2:bufio.NewReader

file, err := os.Open("filename.txt")
if err != nil {panic(err)
}
defer file.Close()reader:= bufio.NewReader(file)
for {line, _, err := reader.ReadLine()if err == io.EOF {break}fmt.Println(string(line))
}

区别是bufio.NewScanner 还可自定义扫描的分隔符,如:

file, _ := os.Open("filename.txt")
scanner := bufio.NewScanner(file)
//scanner.Split(bufio.ScanLines) // 按行读,是默认读取方式
//scanner.Split(bufio.ScanWords) // 按单词读,返回文本中每个以空格分隔的单词,并删除周围的空格
//scanner.Split(bufio.ScanBytes) // 按字节读
//scanner.Split(bufio.ScanRunes) // 按 UTF-8 编码的字符读,如:中文字符for scanner.Scan() {println(scanner.Text())
}
  1. 按指定字节长度读取
    可以使用 bufio.NewReaderRead 方法,能读取指定长度的字节到一个切片中
package mainimport ("bufio""fmt""os"
)func main() {file, err := os.Open("filename.txt")if err != nil {fmt.Println(err)return}defer file.Close()reader := bufio.NewReader(file)buf := make([]byte, 2)  // 指定读取的字节长度n, err := reader.Read(buf)if err != nil {return}fmt.Printf("读取的字节数: %d\n", n)fmt.Printf("读取的内容: %s\n", buf[:n])
}

假如要读取的文件中只有内容hello,那么将输出:

读取的字节数: 2
读取的内容: he

然后在此基础上,使用循环来读整个文件

package mainimport ("bufio""fmt""os"
)func main() {file, err := os.Open("filename.txt")if err != nil {fmt.Println(err)return}defer file.Close()reader := bufio.NewReader(file)buf := make([]byte, 2) // 指定读取的字节长度for {n, err := reader.Read(buf)if err != nil {break}fmt.Printf("%s\n", buf[:n])}
}

其输出将变为:

he
ll
o

写入

  1. 权限表示
    在 Unix 和类 Unix 系统的权限表示中,用3个数字表示,三个数字各代表了不同用户类别的访问权限:
  • 第一个数字:代表文件拥有者(owner)的权限。
  • 第二个数字:代表与文件拥有者同组的用户(group)的权限。
  • 第三个数字:代表其他所有用户(others)的权限。

每个数字可以是0到7之间的任意数字,分别控制读(4)、写(2)和执行(1)权限的开启和关闭。这些数字是对应的权限值的总和

  • 0 没有权限
  • 1 执行权限
  • 2 写权限
  • 4 读权限

一个权限表示是:0666,那么它其实是代表可读可写,前面的 0 是用来明确表示这是一个八进制数

  1. 操作标志
// Flags to OpenFile wrapping those of the underlying system. Not all
// flags may be implemented on a given system.
const (// Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.O_RDONLY int = syscall.O_RDONLY // open the file read-only.O_WRONLY int = syscall.O_WRONLY // open the file write-only.O_RDWR   int = syscall.O_RDWR   // open the file read-write.// The remaining values may be or'ed in to control behavior.O_APPEND int = syscall.O_APPEND // append data to the file when writing.O_CREATE int = syscall.O_CREAT  // create a new file if none exists.O_EXCL   int = syscall.O_EXCL   // used with O_CREATE, file must not exist.O_SYNC   int = syscall.O_SYNC   // open for synchronous I/O.O_TRUNC  int = syscall.O_TRUNC  // truncate regular writable file when opened.
)

举几个例子:

os.O_CREATE|os.O_WRONLY  // 不存在则创建,若存在则从头写入并覆盖原位置的内容,比如原先是hello,然后写入的是demo,那么会变成demoo
os.O_CREATE|os.O_TRUNC|os.O_WRONLY  // 不存在则创建,存在则清空
os.O_APPEND|os.O_WRONLY  // 追加写

常用方法:

os.OpenFile(name string, flag int, perm FileMode) (*File, error)
os.WriteFile(name string, data []byte, perm FileMode) error  // 存在则清空后以原权限写入,不存在则以指定权限创建
os.Open(name string) (*File, error)  //模式为 O_RDONLY
os.Create(name string) (*File, error)  //Create 创建或清空,模式为 O_RDWR
os.Remove(name string) error  //将指定的文件或目录删除
os.RemoveAll(path string) error  //删除路径及其包含的任何子项

文件复制

io.Copy(dst Writer, src Reader) (written int64, err error)
package mainimport ("io""os"
)// CopyFile copies a file from src to dst. If src and dst files exist, and are the same, then return error.
// If dst does not exist, it is created with mode 0666 (before umask).
func CopyFile(src, dst string) error {in, err := os.Open(src)if err != nil {return err}defer in.Close()out, err := os.Create(dst)if err != nil {return err}defer out.Close()_, err = io.Copy(out, in)if err != nil {return err}return out.Sync()
}func main() {src := "source.txt"dst := "destination.txt"if err := CopyFile(src, dst); err != nil {panic(err)}
}

操作目录

  1. 创建目录
package mainimport ("fmt""os"
)func main() {// 创建一个目录err := os.Mkdir("example_dir", 0755)if err != nil {fmt.Println(err)}// 创建目录路径中所有不存在的目录err = os.MkdirAll("example_dir/subdir", 0755)if err != nil {fmt.Println(err)}
}
  1. 读取目录
os.ReadDir(name string) ([]DirEntry, error)  // go 1.16 引入

读取指定目录下的文件和文件夹,及其大小

package mainimport ("fmt""os"
)// convertSize 将字节大小转换为更可读的单位
func convertSize(size int64) string {const (KB = 1 << 10 // 1024MB = 1 << 20 // 1024 * 1024GB = 1 << 30 // 1024 * 1024 * 1024)switch {case size >= GB:return fmt.Sprintf("%.2f GB", float64(size)/GB)case size >= MB:return fmt.Sprintf("%.2f MB", float64(size)/MB)case size >= KB:return fmt.Sprintf("%.2f KB", float64(size)/KB)default:return fmt.Sprintf("%d B", size)}
}func main() {entries, err := os.ReadDir(".") // 读取当前目录if err != nil {fmt.Println(err)return}for _, entry := range entries {info, err := entry.Info()if err != nil {// 如果无法获取文件信息,则跳过该文件fmt.Println("Error:", err)continue}fmt.Printf("%s: %s\n", info.Name(), convertSize(info.Size()))}
}

如果想读取子目录中的内容,可以添加一个循环,然后判断是否是目录,然后同样取即可,直至没有子目录
或者使用更高效的filepath.WalkDir(go 1.16),是filepath.Walk(go 1.0)的优化版,性能更好

package mainimport ("fmt""os""path/filepath"
)// convertSize 将字节大小转换为更可读的单位
func convertSize(size int64) string {const (KB = 1 << 10 // 1024MB = 1 << 20 // 1024 * 1024GB = 1 << 30 // 1024 * 1024 * 1024)switch {case size >= GB:return fmt.Sprintf("%.2f GB", float64(size)/GB)case size >= MB:return fmt.Sprintf("%.2f MB", float64(size)/MB)case size >= KB:return fmt.Sprintf("%.2f KB", float64(size)/KB)default:return fmt.Sprintf("%d B", size)}
}func visitFile(path string, d os.DirEntry, err error) error {if err != nil {fmt.Printf("访问文件时遇到错误: %v\n", err)return nil // 返回nil继续遍历}if !d.IsDir() {info, err := d.Info()if err != nil {fmt.Printf("获取文件信息时遇到错误: %v\n", err)return nil}fmt.Printf("%s: %s\n", path, convertSize(info.Size()))}return nil
}func main() {err := filepath.WalkDir(".", visitFile)if err != nil {fmt.Printf("遍历目录时遇到错误: %v\n", err)}
}
http://www.lryc.cn/news/281273.html

相关文章:

  • C++I/O流——(3)文件输入/输出(第二节)
  • 内网穿透[让你在家里也能榨干学校的服务器]Yep!
  • 构建基于RHEL9系列(CentOS9,AlmaLinux9,RockyLinux9等)的支持63个常见模块的PHP8.1.20的RPM包
  • 你知道什么是Java中的类型强转吗?
  • 【2023】ArrayList和LinkedList详解介绍对比
  • 【软件工程】基于领域建模的产品与技术方案设计(领域驱动设计DDD)
  • 跨境电商账号频繁?你的IP可能“不干净”了
  • Docker数据卷与拦截与目录拦截
  • Python 元类 metaclass 详解
  • HCIA基础知识
  • 翻译: Streamlit从入门到精通 部署一个机器学习应用程序 四
  • AI时代Python量化交易实战:ChatGPT引领新时代
  • 国科大软件安全原理期末复习笔记
  • 人工智能软件测试2024年主要趋势
  • 【JAVA】Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
  • 常见的反爬虫风控 | 验证码风控
  • ClickHouse(21)ClickHouse集成Kafka表引擎详细解析
  • JSP-概念
  • sqlite插入语句id自增列问题
  • C#,字符串匹配(模式搜索)AC(Aho Corasick)算法的源代码
  • 【网络取证篇】Windows终端无法使用ping命令解决方法
  • electron+vue网页直接播放RTSP视频流?
  • 【Delphi 基础知识 19】Assigned的用法
  • 多线程在编程中的重要性有什么?并以LabVIEW为例进行说明
  • K8S---kubectl top
  • Linux部署前后端项目
  • 一文搞懂系列——Linux C线程池技术
  • stable diffusion代码学习笔记
  • 腾讯云服务器怎么买?两种购买方式更省钱
  • 基于SpringBoot自定义控制是否需要开启定时功能