Go语言文件操作

文件的打开和关闭

  • os包中提供了方法叫做Open,就是专门用于打开某一个文件的
  • 注意点:
    • 如果文件不存在不会自动创建
    • 通过open函数打开的文件只能读取, 不能写入
     // 1.打开文件
     //os.Open("D:\\lnj.txt")
     fp, err := os.Open("D:/lnj.txt") // 推荐写法
     if err != nil {
        fmt.Println("打开失败")
     }else{
        fmt.Println(fp)//fp是文件句柄
     }
  • os包中提供了函数叫做Close,用于关闭某个文件
    • 通过defer和匿名函数来关闭文件
 // 2.关闭文件
     defer func() {
        if err = fp.Close(); err !=nil{
            fmt.Println("关闭文件失败")
        }
     }()

文件的读取

  • 第一种:通过os包中的Read函数读取(读取较小的文件)
    • func (f *File) Read(b []byte) (n int, err error)
  • 注意点:
    • 这是File的一个方法,由文件来调用

    • 接收一个字符型切片,会把读取到的数据保存在切片中(会一次性把文件里所有的东西都读取过来)

    • 返回值返回读取到的长度和err(读取到时err为nil)

     fp, err := os.Open("D:/lnj.txt")
     if err != nil{
        fmt.Println("打开文件失败")
         return
     }
     // 2.关闭文件
     defer func() {
        if err = fp.Close(); err != nil{
            fmt.Println("关闭文件失败")
        }
     }()

// sce := make([]byte,7)
//len,err := fp.Read(sce)
// if err != nil{
 //   fmt.Println("读取失败")
//}else{
//   fmt.Println("len = ",len)
//  fmt.Println(string(sce[:len]))
//}

//sce := make([]byte,7)
//len,err := fp.Read(sce)
//for ;len>0;{
 // fmt.Print(string(buff[:len]))
//  // 再次利用Read函数去读取7个字节
//  len, err = fp.Read(buff)
//}
sce := make([]byte,7)
for{
  len,err := fp.Read(sce)
  if err == io.EOF || len < 0{
    break
}
 // 将读到的数据转换为字符串打印
  fmt.Print(string(buff[:len]))
}

  • 第二种方式: 通过bufio包中的ReadBytes和ReadString函数(读取较大的文件,如音视频文件)
    • func (b *Reader) ReadBytes(delim byte) (line []byte, err error)
    • 接收一个参数, 这个参数用于告诉ReadBytes函数, 读取到什么地方接收
    • 返回一个切片,用于保存读取到的数据
    • ReadString底层也是用ReadBytes实现,只不过转换为了字符串返回
  • 步骤
    1. 创建缓冲区(这样可以不用反复从硬盘里读取,可以增加效率)

    2. 将打开的文件句柄传递给NewReader函数, 会返回一个新的句柄

    3. 缓冲区默认的大小是4096

// 1.打开文件
    fp, err := os.Open("D:/lnj.txt")
    if err != nil{
        fmt.Println("打开文件失败")
        return
    }
    // 2.关闭文件
    defer func() {
        if err = fp.Close(); err != nil{
            fmt.Println("关闭文件失败")
        }
    }()
  r := bufio.NewReader(fp) //接收一个句柄,返回一个句柄,利用返回的句柄来读取数据
/*
  buff, err :=  r.ReadBytes('\n')
    if(err != nil){
        fmt.Println("读取失败")
    }else{
        fmt.Println(string(buff))
    }
*/
//str,err := r.ReadString('\n')
for{
    buff, err :=  r.ReadBytes('\n')
    fmt.Print(string(buff))
    if err == io.EOF{
    //if err != nil{
        //fmt.Print("读取失败")
        //fmt.Print(err)
        break
    }
}
  • 错误读取
    /*
    abcdefg\n
    1234567
    第一次读取: buf = abcdefg\n
    第二次读取: buf = 1234567
    但是由于第二次读取一直读到了文件的末尾都没有读到\n, 所以ReadBytes函数就给err赋值了一个io.EOF
    所以如果1234567后面没有\n, 并且是先判断错误, 那么就会少输出一次
     */

 /*
    for{
        buff, err :=  r.ReadBytes('\n')
        if err == io.EOF{
        //if err != nil{
            //fmt.Print("读取失败")
            //fmt.Print(err)
            break
        }
        fmt.Print(string(buff))
    }
 */

  • 第三种方式
    • 通过ioutil包中的ReadFile函数读取(读取较小的文件)
    • func ReadFile(filename string) ([]byte, error)
    • 接收文件所在地址的字符串,返回读取到的数据和错误
buff,err := ioutil.Readfile("D:/lnj.txt")
if err != nil {
  fmt.Println(err)
}else{
  fmt.Print(string(buff))
}

文件写入

  • 第一种方式
    • 通过os包中的Write函数写入(特点:一次性写入,不适合写数据量比较大的文件)
  • 注意点:由于通过Open函数打开的文件是只读的不能写入,所以我们需要用Create函数
    • Create函数注意点:
      • 文件不存在时,自动创建,文件存在时覆盖
      • 函数返回文件的句柄和错误信息
fp,err := os.Create("D:/lnj.txt")
if err != nil {
  fmt.Println(err)
  return
}
defer func(){
  if err = fp.Close();err != nil{
    fmt.Println("关闭文件失败")
  }
}
//写入数据
buf := []byte{'x','x','z','\r','\n'}
len,err := os.Write(buf)
 if err !=nil{
    fmt.Println("写入失败")
}else{
     fmt.Println("写入成功, 写入了", len, "个字节")
 } 

  • 第二种方式
    • 通过bufio包中的Write和WirteString函数写入
    • 注意点:
      • Write函数接收一个切片,WriteString函数接收要写入的字符串,返回写入数据的长度和错误信息
      • 尤其注意:这两个函数是在缓冲区中写入,如果需要真正的写入到文件里面,需要刷新缓冲区,刷新缓冲区用 (缓冲区句柄).Flush()
     // 1.创建一个文件
    fp, err := os.Create("D:/lnj.txt")
    if err != nil{
        fmt.Println("打开文件失败")
        return
    }
    // 2.关闭文件
    defer func() {
        if err = fp.Close(); err !=nil{
            fmt.Println("关闭文件失败")
        }
    }()

    // 3.创建一个写入缓冲区
     w := bufio.NewWriter(fp)
    //buf := []byte{'l','n','j','\r','\n'}
    //len, err := w.Write(buf)
    len, err := w.WriteString("www.it666.com\r\n")
      if err != nil {
    fmt.Println("打开文件失败")
    }else{
     fmt.Println("写入了",len,"个字符")
    }  
    //刷新缓冲区
    w.Flush()

  • 第三种方式
    • 通过ioutil包中的Write和WirteString函数写入
  • func WriteFile(filename string, data []byte, perm os.FileMode) error
  • 第一个参数: 文件地址的自字符串
  • 第二个参数: 写入的内容的切片
  • 第三个参数: 指定文件的权限, 只对Linux系统有效, 在Windows下无效
  • 返回值:返回err
    buf := []byte{'l','n','j','\r','\n'}
    err := ioutil.WriteFile("D:/lnj.txt", buf, 0666)
    if err != nil{
        fmt.Println("写入数据失败")
    }else{
        fmt.Println("写入数据成功")
    }

文件读写

  • 以上的代码只能读或者写入的时候会覆盖原文件,如果要对文件内容进行追加,我们需要用到文件的读写操作

  • os包中有一个函数叫OpenFile 作用:打开一个文件, 并且文件不存在可以创建(注意是可以不是自动)

  • func OpenFile(name string, flag int, perm FileMode) (*File, error)

  • 第一个参数: 需要打开文件的路径

  • 第二个参数: 以什么模式打开文件 (只读/只写/可读可写/追加/)模式可以同时指定多个, 多个之间使用|分隔, 例如 O_CREATE | O_WRONLY

  • 第三个参数: 指定文件的权限, 只对Linux系统有效, 在Windows下无效

  • 模式的种类:const (
    O_RDONLY int = syscall.O_RDONLY // 只读模式打开文件
    O_WRONLY int = syscall.O_WRONLY // 只写模式打开文件
    O_RDWR int = syscall.O_RDWR // 读写模式打开文件
    O_APPEND int = syscall.O_APPEND // 写操作时将数据附加到文件尾部
    O_CREATE int = syscall.O_CREAT // 如果不存在将创建一个新文件
    O_EXCL int = syscall.O_EXCL // 和O_CREATE配合使用,文件必须不存在
    O_SYNC int = syscall.O_SYNC // 打开文件用于同步I/O
    O_TRUNC int = syscall.O_TRUNC // 如果可能,打开时清空文件
    )

  • 文件的权限:
    0.没有任何权限
    1.执行权限(如果是可执行程序, 可以运行)
    2.写权限
    3.写权限和执行权限
    4.读权限
    5.读权限和执行权限
    6.读权限和写权限
    7.读权限和写权限以及执行权限
    一般情况下写 0666

    注意点: OpenFile和Open函数一样, 打开文件之后需要手动关闭文件

以下代码为文件内容的追加:

fp, err := os.OpenFile("D:/lnj.txt", os.O_APPEND | os.O_RDWR, 0666)
     if err != nil{
        fmt.Println("创建失败")
     }else{
        fmt.Println(fp)
     }
     defer func() {
        if err := fp.Close(); err != nil{
            fmt.Println("关闭文件失败")
        }
     }()

w := bufio.NewWriter(fp)
    len , err := w.WriteString("\r\n123456")
    if err != nil{
        fmt.Println("写入数据失败")
    }else{
        fmt.Println("写入成功, 写入了", len, "个字节")
    }
    w.Flush()

文件的拷贝

  • io包中的copy函数
  • 函数接收两个参数,第一个参数是被写入的文件,第二个参数是写入的东西所在的文件

文件判断

  • os包里有个函数叫Stat()
  • func Stat(name string) (FileInfo, error)
  • 函数接收一个字符串,是文件地址的字符串,返回一个文件句柄和错误信息,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)
    }
finfo, err := os.Stat("D:/WWW")
    if err != nil {
        fmt.Println(err)
    }else{
        //fmt.Println(finfo)
        fmt.Println(finfo.Name())
        fmt.Println(finfo.Size())
        fmt.Println(finfo.ModTime())
        fmt.Println(finfo.IsDir())
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 读写文件示例:### 删除文件os.Remove(fname) 创建目录os.Mkdir(dname, os.Mo...
    ppice阅读 4,631评论 0 0
  • 我相信真的有一根红线,连着过去和未来。 如果时光闭合成一个光圈,那么这个光圈一定是温柔的,充满着轮回交错。我不知...
    樱小丸子阅读 1,436评论 4 1
  • 时间是一个很空泛的概念,当时间有了记录也便有了与众不同的意义。 看到小伙伴写的与TA之间的100件小事,也激起我想...
    追逐繁星的猫阅读 1,709评论 0 2
  • 最近負能量爆棚,感觉自己都要疯了。切身体验了一下被負能量传染,感觉好想哭。 我始终觉得每天在宿舍听音乐喝茶和每天在...
    枼曦阅读 5,649评论 0 3
  • 明明已经困了 却不愿睡去 在等什么呢 还是 还是 我也说不上 静听窗外 除了偶尔的 汽车轮胎摩擦地面的声音 由远及...
    YQ筑梦阅读 1,924评论 0 4