#### Go 文件操作
文件在程序是以流的形式操作的, 在Python,JAVA,Go ... 都一樣;
流: 數據在數據源和程序之間經過的路徑
輸入流: 數據從數據源到程序的路徑
輸出流: 數據從程序到數據源的路徑
下面來學習一下在Go中如何操作文件;
os.File 封裝了所有文件相關的操作,File 是一個結構體,有很多方法


##### 打開和關閉文件
package main
import (
"fmt"
"os"
)
func main(){
// 打開文件
// 默認返回兩個值
// 第一個為file 對象,也可稱為file 指針
// 第二個為錯誤信息,如果有錯誤,則err != nil
file,err := os.Open("./test.txt")
if err != nil {
fmt.Println("open file error")
fmt.Println(err)
return
}
// 正常情況下打開文件后,file 實際上是一個指針,類型為*File
fmt.Printf("file=%v",file)
// 正常操作完文件后需要手動關閉文件,避免內存泄漏
err = file.Close()
if err != nil {
fmt.Println("close file error")
}
}
##### 讀取文件
package main
import (
"bufio"
"fmt"
"io"
"io/ioutil"
"os"
)
func main(){
// 打開文件
// 默認返回兩個值
// 第一個為file 對象,也可稱為file 指針
// 第二個為錯誤信息,如果有錯誤,則err != nil
file,err := os.Open("./test.txt")
if err != nil {
fmt.Println("open file error")
fmt.Println(err)
return
}
// 正常情況下打開文件后,file 實際上是一個指針,類型為*File
fmt.Printf("file=%v\n",file)
// 正常操作完文件后需要手動關閉文件,避免內存泄漏
defer file.Close()
// 第一種方式: 帶緩沖方式讀取文件
reader := bufio.NewReader(file)
//var content []byte
for {
//1. 一行一行讀取
str,err := reader.ReadString('\n')
//2. 帶緩沖讀取
//buf := make([]byte,1024)
//n,err := reader.Read(buf)
//content = append(content,buf[:n]...)
if err == io.EOF {
break
}
fmt.Print(str)
}
fmt.Println("file read end...")
// 第二種方式: 一次性讀取所有文件內容
// 適用於文件內容不大的情況
// ioutil.ReadFile 返回兩個值,一個是讀取到的內容字節切片,
// 一個是返回的錯誤信息
content,err := ioutil.ReadFile("test.txt")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(content))
// ioutil.ReadFile 不需要顯示的close 文件, open 和 close 方法被封裝在ReadFile 內部
}
##### 寫文件
關於打開文件指定選擇,可以自行測試,特別是O_APPEND,O_TRUNC 使用較多;
package main
import (
"bufio"
"fmt"
"os"
)
func main(){
// os.OpenFile 是一個更為通用的函數,它需要三個參數,
// 1. 文件路徑
// 2. 指定選項,以下選項可組合使用
//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 // 如果可能,打開文件時清空文件
// 3. 文件模式
// linux r=4,w=2,x=1
file,err := os.OpenFile("./abc.txt",os.O_WRONLY| os.O_CREATE,0666)
if err != nil {
fmt.Println("file open error")
return
}
defer file.Close()
writer := bufio.NewWriter(file)
for i := 0;i<5;i++{
writer.WriteString("hello,golang\n")
}
// bufio.NewWriter 是帶緩沖的寫,如果不調用Flush 方法, 那么數據不會寫入文件
writer.Flush()
}
##### 判斷文件是否存在
Go 中判斷文件或文件夾是否存在的方法為使用os.Stat() 函數返回的錯誤值進行判斷
1. 如果返回的錯誤為nil ,說明文件或文件夾存在
2. 如果返回的錯誤類型使用os.IsNotExist() 判斷為true, 說明文件或文件夾不存在
3. 如果返回的錯誤為其它類型, 則不確定是否存在
func PathExists(path string)(bool,error) {
_,err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) {
return false,nil
}
return false,err
}
return true,nil
}
##### 文件復制
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func copyFile(srcFileName,destFileName string)(int64,error){
srcFile,err := os.Open(srcFileName)
if err != nil {
return 0,err
}
defer srcFile.Close()
reader := bufio.NewReader(srcFile)
destFile,err := os.OpenFile(destFileName,os.O_CREATE|os.O_WRONLY,0666)
if err != nil {
return 0,err
}
writer := bufio.NewWriter(destFile)
defer destFile.Close()
n,err := io.Copy(writer,reader)
// 如果不調用 Flush 將會出現目標文件沒有內容
writer.Flush()
return n,err
}
func main(){
_,err := copyFile("./a.jpg","./b.jpg")
if err != nil {
fmt.Println("copy file error")
fmt.Println(err)
return
}
fmt.Println("file copy finish")
}
最新文章會在個人微信公眾號上同步更新,歡迎關注,大家一同交流學習

