<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Golang基礎筆記十四之文件操作

      本文首發于公眾號:Hunter后端

      原文鏈接:Golang基礎筆記十四之文件操作

      這一篇筆記介紹 Golang 里文件的相關操作,主要用的庫是 io

      以下是本篇筆記目錄:

      1. 文件讀取
      2. 文件寫入
      3. 文件追加
      4. os.OpenFile()
      5. 文件屬性

      1、文件讀取

      1. 文件的打開與關閉

      1) os.Open()

      打開一個文件可以使用 os.Open() 函數,其代碼示例如下:

      filePath := "a.txt"
      file, err := os.Open(filePath)
      

      我們可以通過判斷 err 是否等于 nil 來決定是否可以接著讀取文件,假設這里的 filePath 不存在,那么 err 則的信息則會是:

      open file fail, err: open a.txt: The system cannot find the file specified.
      

      file 的具體讀取操作在后面再介紹。

      2) file.Close()

      在打開文件后,我們可以使用 defer file.Close() 操作來確保文件最后會被正常關閉。

      2. 文件內容的讀取

      在文件打開以后,介紹幾種對文件進行讀取的方式,以下是打開文件的代碼:

      filePath := "a.txt"
      file, err := os.Open(filePath)
      if err != nil {
          fmt.Println("open file fail, err:", err)
          return
      }
      defer file.Close()
      

      假設 a.txt 文件內容為:

      第一行
      second_line
      end of line
      
      1) 一次性讀取

      如果目標文件不大,希望一次性讀取文件內容的話,可以使用 io.ReadAll() 函數:

      data, err := io.ReadAll(file)
      if err != nil {
          fmt.Println("read file error: ", err)
          return
      }
      fmt.Println("read file data: ", string(data))
      return
      

      返回的結果是一個 []byte 類型,可以使用 string() 將其轉換為字符串。

      2) 分塊讀取

      如果文件過大,我們可以分塊讀取,每次讀取指定字節數的數據,下面提供一個示例,用于分批次讀取文件內容,直到讀完整個文件:

      data := make([]byte, 6)
      for {
          count, err := file.Read(data)
          if err == io.EOF {
              fmt.Println("end of file, exit")
              break
          }
          if err != nil {
              fmt.Println("Error: ", err)
              break
          }
          if count > 0 {
              fmt.Println("read count: ", count, ", data: ", string(data[:count]))
          }
      }
      

      這里我們定義了一個長度為 6 的 byte 數組,然后在 for 循環里一直使用 file.Read() 讀取,每次都往 data 中填充數據,直到讀取到文件末尾,或者讀取出現 error。

      在這里需要注意,Go 里對讀取文件到末尾的信息包裝成了一個 error,我們需要進行判斷下。

      file.Seek()

      在讀取文件內容的時候,我們還可以指定指針讀取的位置,比如重置讀取的指針到開頭,我們可以如下操作:

      file.Seek(0, io.SeekStart)
      

      file.Seek() 函數接收兩個參數,一個是偏移量,一個是起始位置,上面這行代碼的含義就是從文件開頭的偏移量為 0 的位置開始讀取文件內容。

      如果我們想從文件開頭往后三個字節長度的地方開始讀取,可以如下操作:

      file.Seek(3, io.SeekStart)
      

      而指定讀取有三個參數:

      const (
          SeekStart   = 0 // seek relative to the origin of the file
          SeekCurrent = 1 // seek relative to the current offset
          SeekEnd     = 2 // seek relative to the end
      )
      

      分別表示文件開頭,指針當前位置和文件末尾。

      當然,file.Seek() 的第一個參數也可以是負數,比如我們想讀取文件最后六個字節的內容,可以如下操作:

      file.Seek(-6, io.SeekEnd)
      
      3) 按行讀取

      我們可以使用 bufio.NewScanner() 函數來按行讀取文件內容:

      file.Seek(0, io.SeekStart)
      scanner := bufio.NewScanner(file)
      
      for scanner.Scan() {
          fmt.Println(scanner.Bytes(), scanner.Text())
      }
      

      這里,我們使用了兩個內容,一個是 .Bytes(),一個是 .Text(),分別打印的內容是該行的字節數組和字符串數據。

      2、文件寫入

      1. 文件的打開與關閉

      文件寫入的操作中,打開與關閉一個文件的操作如下:

      filePath := "a.txt"
      file, err := os.Create(filePath)
      if err != nil {
          fmt.Println("create file error: ", err)
          return
      }
      
      defer file.Close()
      

      使用到的函數是 os.Create(),在這里,如果目標文件 filePath 不存在則會自動創建一個文件,如果存在,則會清空原來的數據,重新寫入。

      2. 文件內容的寫入

      文件打開以后,下面介紹幾種寫入內容的方式

      1) file.Write()

      可以直接使用 file 以字節數組的形式往文件寫入數據:

          n, err := file.Write([]byte("first line\n"))
          if err != nil {
              fmt.Println("write error: ", err)
              return
          }
          fmt.Printf("write %d bytes", n)
      

      這里需要注意,如果要換行需要在末尾手動加上 \n 字符。

      2) io.WriteString()

      我們也可以使用 io.WriteString() 函數往文件里寫入數據:

          n, err := io.WriteString(file, "first line\n")
          if err != nil {
              fmt.Println("write error: ", err)
              return
          }
          fmt.Printf("write %d ", n)
      
      3) bufio.NewWriter()

      我們還可以使用 bufio.NewWriter() 函數寫入,這種操作是以緩沖的形式寫入,操作示例如下:

          writer := bufio.NewWriter(file)
          n, err := writer.WriteString("first line\n")
          if err != nil {
              fmt.Println("write error: ", err)
              return
          }
          writer.Flush()
          fmt.Printf("write %d bytes\n", n)
      

      這種操作需要在最后使用 writer.Flush() 函數將數據從緩沖區寫入文件。

      3、文件追加

      1. 文件的打開與關閉

      如果要對文件內容進行追加,我們可以使用 os.OpenFile() 函數,以下是一個使用示例:

      filePath := "a.txt"
      
      file, err := os.OpenFile(filePath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
      if err != nil {
          fmt.Println("append file error: ", err)
          return
      }
      defer file.Close()
      

      在這里,os.OpenFile() 函數接受三個參數,第一個是文件地址,第二個是標志位,第三個是文件的權限。

      對于標志位,這里的 os.O_APPEND、os.O_WRONLY、os.O_CREATE 分別表示追加,只寫和創建,這樣即便是文件不存在也不會報錯,而是會創建一個新文件。

      2. 文件內容的追加

      追加操作可以使用 file.Write() 來寫入字節數組,或者 file.WriteString() 寫入字符串:

      file.Write([]byte("hello write byte\n"))
      file.WriteString("hello write string\n")
      

      4、os.OpenFile()

      這里再單獨介紹一下 os.OpenFile() 函數,這個函數在前面追問文件內容的時候已經使用過一次了,這里著重再講一下。

      os.OpenFile() 函數是上面介紹的這些操作的基礎函數,也就是說讀取文件使用的 os.Open(),寫入文件使用的 os.Create(),在底層的邏輯里都是調用的 os.OpenFile(),不過是在具體實現的時候,根據不同的目標,比如讀取或者寫入來傳入不同的參數以實現具體功能。

      先來介紹 os.OpenFile() 函數的參數。

      1. os.OpenFile() 參數

      這個函數接收三個參數,name,flag 和 perm。

      1) name

      name 就是文件名稱,string 類型,表示我們需要操作的目標文件。

      2) flag

      flag 表示的是操作的目的,比如前面介紹追加文件的時候用到的 os.O_APPEND|os.O_WRONLY|os.O_CREATE

      參數類型是 int,在源碼里定義了一系列關于文件的操作,如下:

      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.
      )
      

      比如這里有 O_RDONLY 表示只讀,O_WRONLY 表示只寫,O_RDWR 表示讀和寫,在操作文件的時候,這幾個參數之一是必傳的,用來表示文件操作的目的是讀或者寫。

      下面幾個參數則需要和其他上面的幾個參數之一合并使用,比如 O_APPEND 追加,O_CREATE 創建等。

      上面我們介紹追加功能的時候,就是一個示例,內容是 os.O_APPEND|os.O_WRONLY|os.O_CREATE,這個操作首先通過必傳的 os.O_WRONLY 表示是一個寫操作,然后通過 os.O_APPEND 表示是追加操作,會在文件的末尾接著寫入,而 os.O_CREATE 則表示如果目標文件不存在則創建一個新文件。

      通過這種操作疊加的方式使我們追加文件的程序變得更健壯,不會因為文件不存在而報錯。

      3) perm

      perm 表示權限,指的是我們操作文件的時候,對文件賦予的權限,和 Linux 上文件操作的權限是一致的,比如 0644 代表的含義是當前用戶擁有可讀可寫,同用戶組和其他用戶組只擁有可讀權限。

      2. os.Open() 和 os.Create()

      前面介紹了 os.Open() 和 os.Create() 分別用來讀取和寫入文件的操作示例,這兩個函數背后也是通過調用 os.OpenFile() 來實現的。

      1) os.Open()

      os.Open() 函數在源代碼中的定義如下:

      func Open(name string) (*File, error) {
          return OpenFile(name, O_RDONLY, 0)
      }
      

      可以看到通過 OpenFile() 給了一個只讀的權限實現了讀取文件內容的操作。

      2) os.Create()

      os.Create() 函數的源碼如下:

      func Create(name string) (*File, error) {
          return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
      }
      

      os.Create() 函數則是通過讀寫操作,不存在就創建文件操作,存在就對原文件進行截斷操作的方式來實現寫入。

      3. os.ReadFile() 和 os.WriteFile()

      除了上面介紹的讀寫操作,這里還介紹兩個以 os.OpenFile() 函數為基礎實現的讀寫操作,不過這兩個函數的讀和寫都是一次性的,也就是會一次性讀取文件全部內容,或者一次性寫入全部內容。

      1) os.ReadFile()

      os.ReadFile() 函數操作示例如下:

          filePath := "a.txt"
          data, err := os.ReadFile(filePath)
          fmt.Println("data: ", string(data), ", err: ", err)
      

      返回的是一個字節數組,如果想要按行進行切割,可以使用 strings.Split(string(data), "\n") 操作。

      2) os.WriteFile()

      os.WriteFile() 操作示例如下:

          err = os.WriteFile(filePath, []byte("hello write byte\nok write done\nlast line write\n"), 0644)
          fmt.Println("write error: ", err)
      

      這里將多行數據使用 \n 進行分隔。

      5、文件屬性

      打開一個文件后,我們可以獲取這個文件的相關屬性。

      可以如下操作:

      filePath := "a.txt"
      file, _ := os.Open(filePath)
      
      info, err := file.Stat()
      if err != nil {
          fmt.Println("error: ", err)
      }
      defer file.Close()
      

      我們通過 file.Stat() 獲取 FileInfo,文件的信息就都在 info 里了:

      fmt.Println("文件名稱: ", info.Name())
      fmt.Printf("文件大小為 %d bytes\n", info.Size())
      fmt.Printf("文件權限:%s, %o \n", info.Mode(), info.Mode())
      fmt.Println("文件上次修改時間為:", info.ModTime())
      

      這里文件權限打印出的字符串是 -rw-rw-rw-,然后我們打印其八進制的內容就是常見的 666 形式了。

      posted @ 2025-07-23 22:34  XHunter  閱讀(611)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 成人精品大片—懂色av| 乱熟女高潮一区二区在线| 国产AV巨作丝袜秘书| 亚洲色偷偷色噜噜狠狠99| 无码天堂亚洲国产AV| 曲麻莱县| 日本黄页网站免费观看| 老王亚洲AV综合在线观看| 欧美猛少妇色xxxxx猛叫| 中文字幕av中文字无码亚| 国产不卡精品一区二区三区| 欧美日韩高清在线观看| 亚洲AV日韩AV综合在线观看| 韩国美女福利视频在线观看| 日韩在线视频网| 亚洲中文一区二区av| 国产亚洲真人做受在线观看| 国产一区二区三区不卡视频 | 久久人人97超碰人人澡爱香蕉| 99久久成人亚洲精品观看| 日韩深夜福利视频在线观看| 一区二区三区无码免费看| 国产精品自在拍在线播放| 2020国产欧洲精品网站| 最新精品国偷自产在线美女足| 老司机午夜精品视频资源| 色欧美片视频在线观看| 日韩精品中文字一区二区| 亚洲国产精品日韩在线| 日本丰满老妇bbb| 国产精品自拍实拍在线看| 福利视频一区二区在线| 国产精品久久久久影院| 无人去码一码二码三码区| 中文亚洲成A人片在线观看| 亚洲国产午夜福利精品| 清纯唯美经典一区二区| 高清偷拍一区二区三区| 亚洲成人av在线高清| 精品久久久无码中文字幕| 五月婷婷激情视频俺也去淫|