【Go】--文件和目录的操作

Go 文件和目录操作

一、目录操作

1.1 创建目录

1.1.1 创建单级目录

使用os.Mkdir函数创建单级目录:

go 复制代码
package main

import (
    "os"
    "fmt"
)

// 创建单级目录
func createSingleDir(dirname string, perm os.FileMode) {
    err := os.Mkdir(dirname, perm)
    if err != nil {
        fmt.Println("创建目录失败", err)
        return
    }
    fmt.Println("目录创建成功")
}

func main() {
    // 创建目录,权限为0666
    createSingleDir("testdir", 0666)
}
1.1.2 创建多级目录

使用os.MkdirAll函数创建多级目录:

go 复制代码
package main

import (
    "os"
    "fmt"
)

// 创建多级目录
func createMultiLevelDir(dirname string, perm os.FileMode) {
    err := os.MkdirAll(dirname, perm)
    if err != nil {
        fmt.Println("创建目录失败", err)
        return
    }
    fmt.Println("多级目录创建成功")
}

func main() {
    // 创建多级目录
    createMultiLevelDir("parent/child/grandchild", 0666)
}

1.2 删除目录

1.2.1 删除空目录

使用os.Remove函数删除空目录:

go 复制代码
package main

import (
    "os"
    "fmt"
)

// 删除空目录
func removeEmptyDir(dir string) {
    err := os.Remove(dir)
    if err != nil {
        fmt.Println("删除目录失败", err)
        return
    }
    fmt.Println("目录删除成功")
}

func main() {
    removeEmptyDir("testdir")
}
1.2.2 删除非空目录

使用os.RemoveAll函数递归删除目录及其所有内容:

go 复制代码
package main

import (
    "os"
    "fmt"
)

// 删除非空目录
func removeNonEmptyDir(dir string) {
    err := os.RemoveAll(dir)
    if err != nil {
        fmt.Println("删除目录失败", err)
        return
    }
    fmt.Println("非空目录删除成功")
}

func main() {
    removeNonEmptyDir("parent")
}

二、文件操作

2.1 文件读取

2.1.1 方法一:使用 os.Open 和 file.Read

适用于需要精细控制读取过程的场景:

go 复制代码
package main

import (
    "fmt"
    "io"
    "os"
)

// 打开文件(只读模式)
func openFile(filename string) (*os.File, error) {
    file, err := os.Open(filename)
    if err != nil {
        fmt.Println("打开文件失败", err)
        return nil, err
    }
    return file, nil
}

// 读取文件内容(缓冲区方式)
func readFileWithBuffer(file *os.File) {
    var buf []byte
    var tempBuff = make([]byte, 128)

    for {
        n, err := file.Read(tempBuff)
        if err != nil {
            if err == io.EOF {
                fmt.Println("文件读取结束")
                fmt.Printf("文件内容:%s\n", string(buf))
                break
            } else {
                fmt.Println("读取文件失败", err)
                return
            }
        } else {
            fmt.Printf("读取了%d字节\n", n)
            buf = append(buf, tempBuff[:n]...)
        }
    }
}

func main() {
    file, err := openFile("config.json")
    if err != nil {
        return
    }
    defer file.Close()
    
    readFileWithBuffer(file)
}
2.1.2 方法二:使用 bufio 读取器

适用于需要逐行读取的场景:

go 复制代码
package main

import (
    "bufio"
    "fmt"
    "os"
)

func readFileWithBufio(filename string) {
    file, err := os.Open(filename)
    if err != nil {
        fmt.Println("打开文件失败", err)
        return
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
    
    if err := scanner.Err(); err != nil {
        fmt.Println("读取文件失败", err)
    }
}

func main() {
    readFileWithBufio("config.json")
}
2.1.3 方法三:使用 os.ReadFile

适用于读取小文件的简单场景:

go 复制代码
package main

import (
    "fmt"
    "os"
)

func readEntireFile(filename string) {
    data, err := os.ReadFile(filename)
    if err != nil {
        fmt.Println("读取文件失败", err)
        return
    }
    fmt.Printf("文件内容:%s\n", string(data))
}

func main() {
    readEntireFile("config.json")
}

2.2 文件写入

2.2.1 方法一:直接写入文件

使用os.OpenFile和文件对象的写入方法:

go 复制代码
package main

import (
    "os"
    "time"
    "fmt"
)

func writeFileDirectly(filename string, flag int, perm os.FileMode) *os.File {
    file, err := os.OpenFile(filename, flag, perm)
    if err != nil {
        fmt.Println("打开文件失败", err)
        return nil
    }
    
    // 写入字节切片数据
    file.Write([]byte(time.Now().Format("2006-01-02 15:04:05") + " 直接写入字节数据\n"))
    
    // 直接写入字符串数据
    file.WriteString(time.Now().Format("2006-01-02 15:04:05") + " 直接写入字符串数据\n")
    
    return file
}

func main() {
    file := writeFileDirectly("log.txt", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
    if file != nil {
        defer file.Close()
    }
}
2.2.2 方法二:使用 bufio 写入器

适用于需要缓冲写入的场景:

go 复制代码
package main

import (
    "bufio"
    "os"
    "time"
    "fmt"
)

func writeFileWithBufio(filename string, flag int, perm os.FileMode) *os.File {
    file, err := os.OpenFile(filename, flag, perm)
    if err != nil {
        fmt.Println("打开文件失败", err)
        return nil
    }
    
    writer := bufio.NewWriter(file)
    
    // 写入缓存
    writer.WriteString(time.Now().Format("2006-01-02 15:04:05") + " bufio写入数据\n")
    
    // 将缓存数据写入文件
    writer.Flush()
    
    return file
}

func main() {
    file := writeFileWithBufio("log.txt", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
    if file != nil {
        defer file.Close()
    }
}
2.2.3 方法三:使用 os.WriteFile

适用于一次性写入小文件的简单场景:

go 复制代码
package main

import (
    "os"
    "fmt"
)

func writeFileSimple(filename string, perm os.FileMode) {
    data := []byte("Hello, Golang! 这是一次性写入的文件内容。")
    err := os.WriteFile(filename, data, perm)
    if err != nil {
        fmt.Println("写入文件失败", err)
        return
    }
    fmt.Println("文件写入成功")
}

func main() {
    writeFileSimple("output.txt", 0666)
}

2.3 文件复制

2.3.1 方法一:使用 os.ReadFile 和 os.WriteFile

适用于小文件的快速复制:

go 复制代码
package main

import (
    "os"
    "fmt"
)

func copyFileSimple(source, destination string) {
    data, err := os.ReadFile(source)
    if err != nil {
        fmt.Println("读取源文件失败:", err)
        return
    }
    
    err = os.WriteFile(destination, data, 0666)
    if err != nil {
        fmt.Println("写入目标文件失败:", err)
        return
    }
    
    fmt.Println("文件复制成功")
}

func main() {
    copyFileSimple("source.txt", "destination.txt")
}
2.3.2 方法二:使用流式处理

适用于大文件的复制,节省内存:

go 复制代码
package main

import (
    "os"
    "fmt"
    "io"
)

// 利用os.Open、os.Read(流处理)和os.OpenFile方法复制文件
func CopyFile2(filename string, newFilename string) {
    var buf_all []byte
    
    // 打开源文件
    if file, err := os.Open(filename); err != nil {
        fmt.Println("打开原文件失败:", err)
        return
    } else {
        defer file.Close()
        
        var buf = make([]byte, 128)
        for {
            if n, readerr := file.Read(buf); readerr != nil {
                if readerr == io.EOF {
                    fmt.Println("读取完成")
                    break
                } else {
                    fmt.Println("读取文件失败:", readerr)
                    return
                }
            } else {
                buf_all = append(buf_all, buf[:n]...)
            }
        }

        // 使用os.OpenFile创建目标文件
        if newFile, newerr := os.OpenFile(newFilename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666); newerr != nil {
            fmt.Println("创建备份文件失败", newerr)
            return
        } else {
            defer newFile.Close()
            newFile.Write(buf_all)
        }
    }
}

func main() {
    CopyFile2("largefile.txt", "largefile_copy.txt")
}

三、文件打开模式详解

3.1 常用打开模式标志

os.OpenFile函数支持多种打开模式,可以组合使用:

go 复制代码
// 基本模式(三选一)
os.O_RDONLY  // 只读模式
os.O_WRONLY  // 只写模式  
os.O_RDWR    // 读写模式

// 附加模式(可组合)
os.O_CREATE   // 文件不存在时创建
os.O_APPEND   // 追加模式
os.O_TRUNC    // 打开时清空文件内容
os.O_EXCL     // 与O_CREATE一起使用,文件必须不存在

// 使用示例
file, err := os.OpenFile("file.txt", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)

3.2 文件权限说明

文件权限使用八进制表示:

go 复制代码
0666  // 所有用户可读写
0644  // 所有者可读写,其他用户只读
0600  // 仅所有者可读写

四、错误处理最佳实践

4.1 使用 defer 确保资源释放

go 复制代码
func processFile(filename string) error {
    file, err := os.Open(filename)
    if err != nil {
        return err
    }
    defer file.Close()  // 确保文件被关闭
    
    // 处理文件内容
    // ...
    
    return nil
}

4.2 检查文件是否存在

go 复制代码
func checkFileExists(filename string) bool {
    _, err := os.Stat(filename)
    if os.IsNotExist(err) {
        return false
    }
    return err == nil
}
相关推荐
Mr -老鬼13 分钟前
Rust适合干什么?为什么需要Rust?
开发语言·后端·rust
予枫的编程笔记16 分钟前
【Java集合】深入浅出 Java HashMap:从链表到红黑树的“进化”之路
java·开发语言·数据结构·人工智能·链表·哈希算法
ohoy22 分钟前
RedisTemplate 使用之Set
java·开发语言·redis
mjhcsp22 分钟前
C++ 后缀数组(SA):原理、实现与应用全解析
java·开发语言·c++·后缀数组sa
hui函数23 分钟前
如何解决 pip install 编译报错 ‘cl.exe’ not found(缺少 VS C++ 工具集)问题
开发语言·c++·pip
西京刀客28 分钟前
golang路由与框架选型(对比原生net/http、httprouter、Gin)
http·golang·gin
云栖梦泽32 分钟前
易语言Windows桌面端「本地AI知识管理+办公文件批量自动化处理」双核心系统
开发语言
Mr -老鬼36 分钟前
Rust与Go:从学习到实战的全方位对比
学习·golang·rust
r_oo_ki_e_42 分钟前
java22--常用类
java·开发语言
AI小怪兽1 小时前
轻量、实时、高精度!MIE-YOLO:面向精准农业的多尺度杂草检测新框架 | MDPI AgriEngineering 2026
开发语言·人工智能·深度学习·yolo·无人机