GO文件操作

文件操作案例

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

//写入方式一
func main01() {
    //路径分为绝对路径和相对路径
    //create,文件存在则会覆盖原始内容(其实就相当于清空),不存在则创建
    fp, error := os.Create("./a.txt")
    if error != nil {
        fmt.Println("文件创建失败!")
        return
    }
    //延迟调用,关闭文件
    defer fp.Close()
    //写入文件,windows上面换行\r\n其他\n即可
    fp.WriteString("hello\r\n")
    n, _ := fp.WriteString("world\r\n")
    fmt.Println(n) //7 其实就是写入的内容长度world\r\n刚好7
}

//写入方式二
func main2() {
    fp, error := os.Create("./a.txt")
    if error != nil {
        fmt.Println("文件创建失败!")
        return
    }
    defer fp.Close()
    b := []byte{'h', 'e', 'l', 'l'}
    fp.Write(b)
    str := "world"
    //字符串和切片允许相互转换
    b1 := []byte(str)
    fp.Write(b1)
}

//写入方式三:指定位置
func main3() {
    //os.Open是只读打开

    /**
    读写方式:
    O_APPEND:追加
    O_RDONLY: 只读
    O_RDWR:可读可写
    O_WRONLY:只写
    */

    //第三个参数是权限,取值范围0-7
    /**
    0:没有任何权限
    1:执行权限(如果是可执行文件,是可以运行的)
    2:写权限
    3:写权限与执行权限
    4:读权限
    5:读权限与执行权限
    6:读权限与写权限
    7:读权限,写权限,执行权限
    */
    //OpenFile无法创建文件
    fp, error := os.OpenFile("./a.txt", os.O_RDWR, 6)
    if error != nil {
        fmt.Println("文件创建失败!")
        return
    }
    defer fp.Close()
    //b:=[]byte("hello")
    //执行前内容aaaaa
    //执行后内容ahello
    //fp.WriteAt(b,1)

    //获取文件字符个数,参数一可以是负数,这样可以往左偏移
    n, _ := fp.Seek(0, io.SeekEnd)
    b := []byte("hello")
    //此时就相当于追加了,因为n此时是内容总长度了
    fp.WriteAt(b, n) //ahellohello

}

//读取文件
func main4() {
    fp, error := os.Open("./a.txt")
    if error != nil {
        /**
        系统打开文件个数限制是65535
        所以重复打开同一文件是可以的

        1. 文件不存在
        2. 文件权限
        3. 文件打开上限
        */
        fmt.Println("文件打开失败!")
        return
    }
    defer fp.Close()

    b := make([]byte, 1024)
    //n, error := fp.Read(b)
    //fmt.Println(n) //n是长度
    fp.Read(b)

    //也可以通过for遍历读取
    fmt.Println(string(b)) //ahellohello
}

func main5() {
    fp, error := os.Open("./a.txt")
    if error != nil {
        fmt.Println("文件打开失败!")
        return
    }
    defer fp.Close()
    b := make([]byte, 20)
    for {
        n, err := fp.Read(b)
        //文件结束
        if err == io.EOF { //-1
            break
        }
        fmt.Print(string(b[:n]))
    }
}

func main() {
    fp, error := os.Open("./a.txt")
    if error != nil {
        fmt.Println("文件打开失败!")
        return
    }
    defer fp.Close()
    //行读取。新建缓冲区,把内容先放到缓冲区
    r := bufio.NewReader(fp)
    for {
        buf, err := r.ReadBytes('\n')
        fmt.Print(string(buf))

        //文件结束,此时必须读取在上面,否则最后一行的时候err == io.EOF,则永远会少读取一行
        if err == io.EOF { //-1
            break
        }
    }
}

拷贝文件

func main() {

    // 打开读文件
    f_r, err := os.Open("C:/z1/测试.avi")
    if err != nil {
        fmt.Println("Open err: ", err)
        return
    }
    defer f_r.Close()
    // 创建写文件
    f_w, err := os.Create("C:/z1/test.avi")
    if err != nil {
        fmt.Println("Create err: ", err)
        return
    }
    defer f_w.Close()

    // 从读文件中获取数据,放到缓冲区中。
    buf := make([]byte, 4096)
    // 循环从读文件中,获取数据,“原封不动的”写到写文件中。
    for {
        n, err := f_r.Read(buf)
        if err != nil && err == io.EOF {
            fmt.Printf("读完。n = %d\n", n)
            return
        }
        f_w.Write(buf[:n]) // 读多少,写多少
    }
}

目录操作

打开目录

OpenFile:以只读方式打开目录

  • 参1:name, 打开目录的路径: 绝对路径、相对路径
  • 参2:打开目录权限: O_RDONLY
  • 参3:os.ModeDir,
    返回值: 返回一个可以读目录的 文件指针。

读目录:Readdir

原型:func (f *File) Readdir(n int) ([]FileInfo, error) {
            
参数: 欲打开的目录项个数。 -1 , 表所有;例如10,则只读取十个目录项

返回值:  FileInfo :    
type FileInfo interface {
    Name() string               // base name of the file
    Size() int64                // length in bytes for regular files; system-dependent for others
    Mode() FileMode             // file mode bits
    ModTime() time.Time     // modification time
    IsDir() bool                // abbreviation for Mode().IsDir()
    Sys() interface{}           // underlying data source (can return nil)
}   

代码案例

func main()  {
    // 获取用户输入的目录路径
    fmt.Println("请输入待查询的目录:")
    var path string
    fmt.Scan(&path)

    // 打开目录
    f, err := os.OpenFile(path, os.O_WRONLY, os.ModeDir)
    if err != nil {
        fmt.Println("OpenFile err: ", err)
        return
    }
    defer f.Close()
    // 读取目录项
    info, err:= f.Readdir(-1)   // -1: 读取目录中所有目录项
    if err != nil {
        fmt.Println("Readdir err: ", err)
        return
    }
    // 变量返回的切片
    for _, fileInfo := range info {
        if fileInfo.IsDir() {           // 是目录
            fmt.Println(fileInfo.Name(), " 是一个目录")
        } else {
            fmt.Println(fileInfo.Name(), " 是一个文件")
        }
    }
}

MMU

虚拟内存映射单元


MMU.png

缓冲区

缓冲区.png

文件读写分为,系统缓存和用户缓冲,用户缓存就是写代码时候创建的缓存,而用户缓存则是系统内部的缓存调度,不是每次读写都是操作磁头扇区等硬件,而是系统尽可能的预读入缓输出,减少硬件交互,代码的读取和写入都是读取和写入系统缓冲区,真正什么时候写入硬盘,有系统内部IO优化算法操作。

结构体指针传参

结构体指针传参.png

你可能感兴趣的:(GO文件操作)