(原文地址:https://blog.gm7.org/%E4%B8%AA%E4%BA%BA%E7%9F%A5%E8%AF%86%E5%BA%93/03.%E7%BC%96%E7%A8%8B%E5%BC%80%E5%8F%91/GO/02.GO%E5%B8%B8%E7%94%A8%E5%AE%9E%E4%BE%8B.html)

按字节读取文件

  1. package main
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. )
  7. func main() {
  8. file, _ := os.Open("c:\\windows\\win.ini") //打开文件。这里file返回的是文件的指针,不是具体值。
  9. fmt.Println("os.Open返回文件指针:", file)
  10. defer file.Close() //在执行完函数,就关闭文件句柄。
  11. //字节类型的集合,byte是uint8的别名,所以在这里用[]uint8也是可以的。
  12. buf := make([]byte, 1024)
  13. var result string //用于存放最终的结果
  14. for { //这里for是永真条件
  15. count, err := file.Read(buf) //最多读取len(buf),即1024字节,并追加在集合buf中。
  16. if err == io.EOF { //检测是否到结尾
  17. break //文件读取结尾,就跳出循环
  18. } else {
  19. currBytes := buf[:count] //把buf缓冲区中的字节赋值给currBytes
  20. result += string(currBytes)
  21. }
  22. }
  23. fmt.Println(result)
  24. }

image.png

借助ioutil来读取

这方法可以将文件所有字节一次性取出来,省去了使用字节循环读取的过程。

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. )
  7. func main() {
  8. //这两句是不变的,获取文件的指针
  9. file, _ := os.Open("c:\\windows\\win.ini")
  10. defer file.Close()
  11. byteRes, _ := ioutil.ReadAll(file) //返回byte类型,要用string转换一下输出
  12. fmt.Println(string(byteRes))
  13. }

image.png

仅使用ioutil

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. )
  6. func main() {
  7. byteRes, _ := ioutil.ReadFile("c:\\windows\\win.ini") //返回byte类型,要用string转换一下输出
  8. fmt.Println(string(byteRes))
  9. }

image.png
就这么简单!

利用scanner

有些时候,按字节不符合业务场景,比如读取文件里面的url,一行一个url,用scanner比较适合。

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "os"
  6. )
  7. func main() {
  8. file, _ := os.Open("F:\\Codes\\Go\\url.txt")
  9. defer file.Close()
  10. scanner := bufio.NewScanner(file)
  11. //读到了,scan返回true
  12. for scanner.Scan() {
  13. fmt.Println(scanner.Text())
  14. }
  15. }

image.png

通过ioutil

读用到了ioutil.ReadFile,当然也有WriteFile。这个方法使用覆盖写入,如果有此文件,会清空文件写入,如果没有此文件,会根据权限来创建文件。

要注意一点就是os.FileMode,在Linux中,rwx用4,2,1来代表,相加为7则为最高权限可读可写可执行,所以赋予777是最高权限,666则为可读可写。第一个6代表文件所有者本身的权限,第二个6代表同组的用户权限,第三个6代表其他用户的权限。

  1. package main
  2. import (
  3. "io/ioutil"
  4. )
  5. func main() {
  6. data := "12312312313123"
  7. ioutil.WriteFile("test.txt", []byte(data), 0666) //0666是可读可写
  8. }

image.png

通过file句柄

os.OpenFile(name string, flag int , prem FileMove)方法,可以指定额外的读写方法和文件权限参数。
一下几个常用的flag值:

  • os.O_CREATE: create if none exists 不存在则创建
  • os.O_RDONLY: read-only 只读
  • os.O_WRONLY: write-only 只写
  • os.O_RDWR: read-write 可读可写
  • os.O_TRUNC: truncate when opened 文件长度截为0:即清空文件
  • os.O_APPEND: append 追加新数据到文件 ```go package main

import ( “os” )

func main() { //按权限打开句柄,可读可写,追加,不存在则创建 file, _ := os.OpenFile(“test1.txt”, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666) defer file.Close()

  1. data := "111111111111111111111"
  2. file.Write([]byte(data)) //按字节写入
  3. file.WriteString("2222222222222222222") //按字符串写入

}

  1. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/22872200/1655713238051-44957bd2-52c8-463d-8bd5-bbbd998e3654.png#clientId=u5263a180-96fc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=247&id=u85beddc1&margin=%5Bobject%20Object%5D&name=image.png&originHeight=247&originWidth=608&originalType=binary&ratio=1&rotation=0&showTitle=false&size=13920&status=done&style=none&taskId=u6ef591b4-0284-40e7-a80d-5ffab3355aa&title=&width=608)
  2. <a name="cgWpI"></a>
  3. ## 通过ioutil
  4. 这个方法比上面一种,只多了一行代码:
  5. ```go
  6. import (
  7. "bufio"
  8. "os"
  9. )
  10. func main() {
  11. //按权限打开句柄,可读可写,追加,不存在则创建
  12. file, _ := os.OpenFile("test2.txt", os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
  13. defer file.Close()
  14. w := bufio.NewWriter(file)
  15. data := "333333333333"
  16. w.Write([]byte(data)) //按字节写入
  17. w.WriteString("4444444444444444") //按字符串写入
  18. w.Flush() //情况缓存
  19. }

image.png