走到這裏的探索者們,對電腦是相當瞭解的,接下來用go和系統來次對話!
一、go的角度認識文件
1. 什麼是文件
在面向對象編程語言中,一切皆對象,而在操作系統(如:Linux)一切皆文件!我們記錄的txt文件,辦公的excel文件,拍的照片jpg文件,錄的語音mp4文件,拍的視頻mp4文件…都是文件。他們都是進行保存我們的數據。
2. 輸入流/輸出流
編程操作文件的過程,是通過流的形式進行操作的!
圖中出現了“流”的概念,和流的經歷的路徑,具體意思如下:
流:數據在數據源(文件)和程序(內存)之間經歷的路徑 (上班下班來回路線)
輸入流:數據從數據源(文件)到程序(內存)的路徑 (從家到公司的路線)
輸出流:數據從程序(內存)到數據源(文件)的路徑 (從公司到家的路線)
站在了內存的角度去看流的方向
二、文件操作
https://studygolang.com/pkgdoc
os包File結構體下,有一些公用的文件操作方法
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中的一個。
- 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 //打開時截斷常規可寫文件。
我使用了創建文件O_CREAT模式 和寫入O_WRONLY模式,想創建文件並寫人內容!
第二個陌生的參數是0666是什麼意思呢?這個熟悉Linux的探索者們一定不陌生,這個就是文件的權限
所以你需要什麼權限相加就行,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的角度,去思考和操作文件和文檔!
文件/文檔:大致生命流程,創建–重命名–修改權限–閲讀/修改內容–刪除