在項目中,我們可能會需要獲取一個文件的大小,在Go語言中,有很多方法來獲取一個文件的大小
Read字節方式
func main() {
file,err:=os.Open("water")
if err ==nil {
sum := 0
buf:=make([]byte,2014)
for {
n,err:=file.Read(buf)
sum+=n
if err==io.EOF {
break
}
}
fmt.Println("file size is ",sum)
}
}
這種方式需要打開文件,通過for循環讀取文件的字節內容,然后算出文件的大小,這樣時也是最不能用的辦法,因為效率低,代碼量大。
ioutil方式
上面的代碼比較啰嗦,這時候我們可能想到了使用ioutil包的ReadFile來代替,直接獲得文件的內容,進而計算出文件的大小。
func main() {
content,err:=ioutil.ReadFile("water")
if err == nil {
fmt.Println("file size is ",len(content))
}
}
通過ioutil.ReadFile函數,我們三行代碼就可以搞定,的確方便很多,但是效率慢的問題依然,存在,如果是個很大的文件呢?
Stat方法
繼續再進一步,我們不讀取文件的內容來計算了,我們通過文件的信息
func main() {
file,err:=os.Open("water")
if err == nil {
fi,_:=file.Stat()
fmt.Println("file size is ",fi.Size())
}
}
這種方式不會再讀取文件的內容,而是通過Stat方法直接獲取,速度會非常快,尤其對於大文件尤其有用。但是它還不是我們今天要講的終極辦法,因為它還是會打開文件,會占用它
終極方案 os.Stat()
func main() {
fi,err:=os.Stat("water")
if err ==nil {
fmt.Println("file size is ",fi.Size(),err)
}
}
是的,也只需要三行代碼即可實現,這里使用的是os.Stat,通過他可以獲得文件的元數據信息,現在我們看看它能獲取到哪些信息。
獲取文件信息
通過os.Stat方法,我們可以獲取文件的信息,比如文件大小、名字等。
func main() {
fi,err:=os.Stat("water")
if err ==nil {
fmt.Println("name:",fi.Name())
fmt.Println("size:",fi.Size())
fmt.Println("is dir:",fi.IsDir())
fmt.Println("mode::",fi.Mode())
fmt.Println("modTime:",fi.ModTime())
}
}
運行這段代碼看下結果:
name: water
size: 403
is dir: false
mode:: -rw-r--r--
modTime: 2018-05-06 18:52:07 +0800 CST
以上就是可以獲取到的文件信息,還包括判斷是否是目錄,權限模式和修改時間。所以我們對於文件的信息獲取要使用os.Stat函數,它可以在不打開文件的情況下,高效獲取文件信息。
判斷文件是否存在
os.Stat函數有兩個返回值,一個是文件信息,一個是err,通過err我們可以判斷文件是否存在。
首先,err==nil的時候,文件肯定是存在的;其次err!=nil的時候也不代表不存在,這時候我們就需要進行嚴密的判斷。
func main() {
_,err:=os.Stat(".")
if err ==nil {
fmt.Println("file exist")
}else if os.IsNotExist(err){
fmt.Println("file not exist")
}else{
fmt.Println(err)
}
}
通過os.IsNotExist來判斷一個文件不存在。最后else的可能性比較少,這個時候可以看下具體的錯誤是什么,再根據錯誤來判斷文件是否存在。os.Stat是一個非常好的函數,可以讓我們非常高效的獲取文件信息,所以在項目中盡可能的使用它。
os.Stat()方法用於獲取文件屬性,示例如下
import (
"fmt"
"os"
)
func main() {
fileInfo, err := os.Stat(`C:\Users\Administrator\Desktop\應用商店.txt`)
if err != nil {
fmt.Println(err)
}
fmt.Println(fileInfo.Name()) //應用商店.txt
fmt.Println(fileInfo.IsDir()) //false 判斷是否是目錄
fmt.Println(fileInfo.ModTime()) //2019-12-05 16:59:36.8832788 +0800 CST 文件的修改時間
fmt.Println(fileInfo.Size()) //3097 文件大小
fmt.Println(fileInfo.Mode()) // -rw-rw-rw- 讀寫屬性
fmt.Println(fileInfo.Sys()) //&{32 {2160608986 30778972} {2160608986 30778972} {1375605524 30780234} 0 3097}
}
終端執行命令: go run demo.go e:\face.jpg
name = face.jpg
size = 178154 //Size()是按Byte字節進行計算大小.
mode = -rw-rw-rw-
modtime = 2019-02-20 21:02:58.0055166 +0800 CST
isDir = false
sys = &{32 {1739327783 30722332} {2624535810 30722332} {2583200894 30722332} 0 178154}
PS其fileInfo源碼
type FileInfo interface {
Name() string // 文件的名字(不含擴展名)
Size() int64 // 普通文件返回值表示其大小;其他文件的返回值含義各系統不同
Mode() FileMode // 文件的模式位
ModTime() time.Time // 文件的修改時間
IsDir() bool // 等價於Mode().IsDir()
Sys() interface{} // 底層數據來源(可以返回nil)
}
