走到這裏的探索者們,對電腦是相當瞭解的,接下來用go和系統來次對話!

一、go的角度認識文件

1. 什麼是文件

在面向對象編程語言中,一切皆對象,而在操作系統(如:Linux)一切皆文件!我們記錄的txt文件,辦公的excel文件,拍的照片jpg文件,錄的語音mp4文件,拍的視頻mp4文件…都是文件。他們都是進行保存我們的數據。

2. 輸入流/輸出流

編程操作文件的過程,是通過流的形式進行操作的!

Golang中文件的基本操作_#golang


圖中出現了“流”的概念,和流的經歷的路徑,具體意思如下:

流:數據在數據源(文件)和程序(內存)之間經歷的路徑 (上班下班來回路線)
輸入流:數據從數據源(文件)到程序(內存)的路徑 (從家到公司的路線)
輸出流:數據從程序(內存)到數據源(文件)的路徑 (從公司到家的路線)

站在了內存的角度去看流的方向

二、文件操作

https://studygolang.com/pkgdoc

os包File結構體下,有一些公用的文件操作方法

Golang中文件的基本操作_#開發語言_02

1. 打開/關閉文件

1.1 打開文件

根據官網學習網站,os包File結構體下需要調用這個方法,進行打開文件

func Open(name string) (file *File, err error)

在d盤新建一個txt文檔,進行打開文件

// 返回file指針對象,err為異常接收
	file, err := os.Open("d:\\file.txt")

	// 進行處理接收的異常 這裏直接結束main
	if err != nil {
		return
	}

	fmt.Printf("file: %v", file)

來到了公司(內存),我們不能一直上班,這時需要打卡下班…

1.2 關閉文件(有打開必有關閉)

打卡下班!!!

func (f *File) Close() error

沒有入參,返回拋出的異常。

// 關閉文件 接收拋出的異常
	err = file.Close()

	// 異常處理  這裏直接打印
	if err != nil {
		fmt.Println(err)
	}

2. 讀文件

2.1 讀取小文件

一次性加載全部內容到內存,適合讀取小文件

package main

import (
	"fmt"
	"os"
)

func main() {
	file, err := os.ReadFile("d:\\file.txt")
	if err != nil {
		return
	}
	fmt.Println(string(file))
	//《泊船瓜洲》
	//宋朝·王安石
	//京口瓜洲一水間,鐘山只隔數重山。
	//春風又綠江南岸,明月何時照我還。
}

2.2 按行讀取文件

獲取到文件對象,進行每行內容加載到內存,適合大文件

bufio 優化性能:通過緩衝減少 I/O 操作次數,適合頻繁讀寫。

package main

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

func main() {
	// 打開文件
	file, err := os.Open("d:\\file.txt")
	if err != nil {
		return
	}

	// 關閉文件
	defer file.Close()

	// 讀取文件
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		fmt.Println(scanner.Text())
		fmt.Println("------------------")
	}

	if scanner.Err() != nil {
		fmt.Println(scanner.Err())
	}
	//《泊船瓜洲》
	//------------------
	//宋朝·王安石
	//------------------
	//京口瓜洲一水間,鐘山只隔數重山。
	//------------------
	//春風又綠江南岸,明月何時照我還。
	//------------------
}

3. 寫文件

3.1 小文件寫入

打開文件並寫入,使用OpenFile方法進行模式選擇和權限賦予

package main

import (
	"fmt"
	"os"
)

func main() {
	// 打開文件的同時 如果有則進行清空寫入 無則進行創建並寫入
	file, err := os.OpenFile("d:\\writerfile.txt", os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()

	// 寫入一個文件 提前創建了一個空文件
	file.WriteString("hello golang2\n")
}

上邊我們看到OpenFile方法中入參有倆個陌生的參數,模式和參數

打開文件模式列表如下

必須項:必須指定O_RDONLY、O_WRONLY或O_RDWR中的一個。

  1. O_RDONLY int=syscall.O_RDONLY //以只讀方式打開文件。
  2. O_WRONLY int=syscall.O_WRONLY //以寫方式打開文件。
  3. O_RDWR int=syscall.O_RDWR //以讀寫方式打開文件。

可選項:其餘的值可以被輸入或輸入以控制行為。

  1. O_APPEND int=syscall.O_APPEND //寫入時向文件追加數據。
  2. O_CREATE int=syscall.O_CREAT //如果不存在,則創建一個新文件。
  3. O_EXCL int=syscall.O_EXCL //與O_CREATE一起使用時,文件必須不存在。
  4. O_SYNC int=syscall.O_SYNC //打開同步I/O。
  5. O_TRUNC int=syscall.O_TRUNC //打開時截斷常規可寫文件。

我使用了創建文件O_CREAT模式 和寫入O_WRONLY模式,想創建文件並寫人內容!

第二個陌生的參數是0666是什麼意思呢?這個熟悉Linux的探索者們一定不陌生,這個就是文件的權限

Golang中文件的基本操作_#開發語言_03


所以你需要什麼權限相加就行,0666意思如下

0:代表八進制

6:所有者擁有r(讀)和w(寫)權限

6:所屬組擁有r(讀)和w(寫)權限

6:其他人擁有r(讀)和w(寫)權限

3.2 按行寫入

package main

import (
	"bufio"
	"os"
)

func main() {
	// 打開文件
	file, err := os.Create("d:\\fileWriterLine.txt")
	if err != nil {
		return
	}

	// 關閉文件
	defer file.Close()

	// 寫入文件
	writer := bufio.NewWriter(file)
	arr := []string{
		"《泊船瓜洲》",
		"宋朝·王安石",
		"京口瓜洲一水間,鐘山只隔數重山。",
		"春風又綠江南岸,明月何時照我還。",
	}
	for _, line := range arr {
		writer.WriteString(line)
		writer.WriteString("\n")
	}

	writer.Flush()
}

為什麼最後會有個Flush方法呢?原因是NewWriter是帶緩存的,進行批次寫入,就像十字路口攢了一批人,可以闖紅燈一樣…

三、小練習

瞭解了怎麼文件是什麼,如何通過go去操作文件,那麼開始來個小練習
練習內容如下

// 1. 創建一個文件
	// 2. 按行寫入
	// 3. 追加寫入時間
	// 4. 進行文件重命名
	// 5. 按行讀取文件
	// 6. 刪除文件

根據上邊的需求內容,進行編寫

package main

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

func main() {
	// 1. 創建一個文件
	// 2. 按行寫入
	// 3. 追加寫入時間
	// 4. 進行文件重命名
	// 5. 按行讀取文件
	// 6. 刪除文件

	// 1. 創建一個文件
	fileWriter, err := os.OpenFile("d:\\file.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		fmt.Printf("open file failed, err:%v\n", err)
		return
	}

	// 2. 按行寫入文件
	writer := bufio.NewWriter(fileWriter)
	arr := []string{
		"《泊船瓜洲》",
		"宋朝·王安石",
		"京口瓜洲一水間,鐘山只隔數重山。",
		"春風又綠江南岸,明月何時照我還。",
	}
	for _, line := range arr {
		writer.WriteString(line)
		writer.WriteString("\n")
	}

	writer.Flush()

	// 3. 追加寫入時間
	fileWriter.WriteString("\n" + "2021-09-02 15:05:05")
	fileWriter.Sync()

	// 方法結束後,進行關閉文件
	fileWriter.Close()

	// 4. 文件重命名
	err = os.Rename("d:\\file.txt", "d:\\fileTest.txt")
	if err != nil {
		fmt.Printf("rename file failed, err:%v\n", err)
		return
	}

	// 5. 按行讀取文件
	fileRead, err := os.Open("d:\\fileTest.txt")
	if err != nil {
		fmt.Printf("open file failed, err:%v\n", err)
		return
	}
	// 按行讀取
	scanner := bufio.NewScanner(fileRead)
	for scanner.Scan() {
		fmt.Println(scanner.Text())
		fmt.Println("------------")
	}
	if scanner.Err() != nil {
		fmt.Println(scanner.Err())
	}

	// 關閉讀文件流
	fileRead.Close()

	// 6. 刪除文件
	err = os.Remove("d:\\fileTest.txt")
	if err != nil {
		fmt.Printf("remove file failed, err:%v\n", err)
		return
	}

}

文件其它方法調用方法大致相同,在特定的場景和需求下,進行合理使用!本篇為引導篇,不做全部列舉!

平常電腦操作的文件的時候,我們都是通過鼠標右鍵,選擇功能進行操作!

現在學了go,我們站在了go的角度,去思考和操作文件和文檔!

文件/文檔:大致生命流程,創建–重命名–修改權限–閲讀/修改內容–刪除