文章目錄
- 文件信息接口os.FileInfo
- 文件的常規(guī)操作 (os包)
- 文件的讀取和寫入 (io及os包)
- ioutil包
- bufio包
一蹈丸、文件信息
os.FileInfo接口
接口屬性
type FileInfo interface {
Name() string // 文件的名字
Size() int64 // 普通文件返回值表示其大小;其他文件的返回值含義各系統(tǒng)不同
Mode() FileMode // 文件的模式位 (例-rw-rw-r--)
ModTime() time.Time // 文件的修改時間
IsDir() bool // 等價于Mode().IsDir()
Sys() interface{} // 底層數(shù)據(jù)來源(可以返回nil)
}
os.fileStat結(jié)構(gòu)體實(shí)現(xiàn)了FileInfo接口的所有方法
type fileStat struct {
name string
size int64
mode FileMode
modTime time.Time
sys syscall.Stat_t
}
示例
fileInfo, err := os.Stat("./aa.txt")
if err != nil{
fmt.Println(err)
return
}
fmt.Printf("%T: %v", fileInfo, fileInfo) // *os.fileStat: &{aa.txt 23 ...}
fmt.Println(fileInfo.Name()) // aa.txt
fmt.Println(fileInfo.IsDir()) // false
fmt.Println(fileInfo.Size()) // 23
fmt.Println(fileInfo.Mode()) // -rw-rw-r--
fmt.Println(fileInfo.ModTime()) // 2019-02-15 14:44:39.745 +0800 CST
文件路徑相關(guān)函數(shù)
路徑相關(guān)的函數(shù)有兩個包逻杖,path
和 path/filepath
,
兩個包內(nèi)有一些相同的函數(shù)奋岁,如IsAbs()
、Join()
荸百、Dir()
filepath
中的函數(shù)兼容各個操作系統(tǒng)闻伶,涉及到windows系統(tǒng)路徑操作時,應(yīng)該使用filepath
包
-
filepath.Rel(basepath, targpath string) (string, error)
獲取相對路徑 -
filepath.Abs(path string) (string, error)
獲取絕對路徑够话,如果path不是絕對路徑蓝翰,會加入當(dāng)前工作目錄以使之成為絕對路徑。 -
path.Join(elem ...string) string
路徑拼接 -
path.IsAbs(path string) bool
判斷文件是否是絕對路徑 -
path.Dir(path string) string
獲取目錄
二女嘲、文件的常規(guī)操作
創(chuàng)建目錄 如果存在則失敗
-
os.Mkdir(name string, perm FileMode) error
- 僅創(chuàng)建一層
- 相當(dāng)于
linux
命令mkdir
-
os.MkdirAll(path string, perm FileMode) error
- 創(chuàng)建多層
- 相當(dāng)于
linux
命令mkdir -p
創(chuàng)建文件 如果存在會覆蓋
-
os.Create(name string) (file *File, err error)
- 底層調(diào)用
os.OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
- 采用模式
0666
(任何人都可讀寫畜份,不可執(zhí)行) - 如果文件存在會清空它
- 底層調(diào)用
打開文件
-
os.Open(name string) (file *File, err error)
- 底層調(diào)用
OpenFile(name, O_RDONLY, 0)
- 以只讀的方式打開文件
- 底層調(diào)用
-
os.OpenFile(name string, flag int, perm FileMode) (file *File, err error)
-
perm
可為0666
、0777
等 -
flag
是os
包中定義的常量:
-
const (
O_RDONLY int = syscall.O_RDONLY // 只讀模式打開文件
O_WRONLY int = syscall.O_WRONLY // 只寫模式打開文件
O_RDWR int = syscall.O_RDWR // 讀寫模式打開文件
O_APPEND int = syscall.O_APPEND // 寫操作時將數(shù)據(jù)附加到文件尾部
O_CREATE int = syscall.O_CREAT // 如果不存在將創(chuàng)建一個新文件
O_EXCL int = syscall.O_EXCL // 和O_CREATE配合使用欣尼,文件必須不存在
O_SYNC int = syscall.O_SYNC // 打開文件用于同步I/O
O_TRUNC int = syscall.O_TRUNC // 如果可能爆雹,打開時清空文件
)
關(guān)閉文件
-
file.Close() error
- *File指針的方法
- 程序與文件之間的連接斷開
刪除文件或目錄
-
os.Remove(name string) error
- 只刪除一層
- 相當(dāng)于
linux
命令rm
-
os.RemoveAll(path string) error
- 刪除path指定的文件,或目錄及它包含的任何下級對象
- 相當(dāng)于
linux
命令rm -r
三愕鼓、文件的讀寫操作
讀取文件
-
os.Open(filename)
-->*File
-
file.Read([]byte)
-->n, err
- 單次讀取的字節(jié)數(shù)最大為
[]byte
的長度 -
n
為實(shí)際讀取到的字節(jié)數(shù) - 讀取到末尾時
err
為EOF(end of file)
- 單次讀取的字節(jié)數(shù)最大為
-
file.Close()
關(guān)閉文件
示例:
//step1:打開文件
fileName := ".text.txt"
file, err := os.Open(fileName)
if err != nil {
fmt.Println("打開錯誤", err)
return
}
//step2:讀/寫
//從file中讀取最多l(xiāng)en(bs)個字節(jié)钙态,存入bs切邊中,n是實(shí)際讀取的數(shù)量
bs := make([]byte, 1024, 1024)
for {
n, err := file.Read(bs)
if n == 0 || err == io.EOF {
fmt.Println("讀取結(jié)束")
break
}
fmt.Println(string(bs[:n]))
}
//step3:關(guān)閉文件
file.Close()
寫入文件
寫入文件與讀取類似
-
os.Open(filename)
-->*File
-
file.Write([]byte)
-->n, err
- 將
[]byte
中的數(shù)據(jù)寫入文件
- 將
-
file.WriteString(string)
-->n, err
- 將
string
寫入文件
- 將
file.Close()
文件復(fù)制
-
io.Copy(dst Writer, src Reader) (written int64, err error)
- dst和src為實(shí)現(xiàn)了接口io.Writer和io.Reader的實(shí)例
示例:
func copyFile(srcFile, destFile string) (int64, error) {
file1, err := os.Open(srcFile)
if err != nil {
return 0, err
}
file2, err := os.OpenFile(destFile, os.O_WRONLY|os.O_CREATE, os.ModePerm)
if err != nil {
return 0, err
}
defer file1.Close()
defer file2.Close()
return io.Copy(file2, file1)
}
四拒啰、ioutil包
-
ReadFile()
-->([]byte, error)
- 讀取所有數(shù)據(jù)驯绎,返回字節(jié)數(shù)組
-
WriteFile(filename string, data []byte, perm os.FileMode)
-->error
- 文件不存在則創(chuàng)建文件,存在則清空文件
- os.FileMode可以直接用
0666
或者0777
-
ReadDir()
-->([]os.FileInfo, error)
- 讀取一個目錄下的字內(nèi)容谋旦,目錄或文件剩失,但是只有一層
- 返回一個
os.FileInfo
切片
示例:
data, err := ioutil.ReadFile("aa.txt")
fmt.Println(string(data))
if err != nil {
fmt.Println(err)
return
}
err = ioutil.WriteFile("bb.txt", data, 0666)
if err != nil {
fmt.Println(err)
return
}
fileInfos, err := ioutil.ReadDir(".")
if err != nil {
fmt.Println(err)
return
}
for i := range fileInfos {
fmt.Println(i, fileInfos[i].IsDir(), fileInfos[i].Name())
}
五、bufio包
-
bufio
包實(shí)現(xiàn)了有緩沖的I/O
-
bufio
封裝了一個Reader
?及Writer
結(jié)構(gòu)體册着,分別實(shí)現(xiàn)了io.Reader
和io.Writer
接口 - 通過對對
io
模塊的封裝拴孤,提供了帶有緩沖的io
操作,減小了大塊數(shù)據(jù)讀寫的io開銷
io.Reader和io.Writer
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
os.Open(name string) (*File, error)
返回的文件指針就實(shí)現(xiàn)了io.Reader
bufio.Reader結(jié)構(gòu)體
-
NewReader(rd io.Reader) *Reader
-
NewReader
創(chuàng)建一個具有默認(rèn)大小緩沖甲捏、從r
讀取的*Reader
-
-
Reader.Read(p []byte) (n int, err error)
-
Read
讀取數(shù)據(jù)寫入p
演熟。本方法返回寫入p
的字節(jié)數(shù) - 返回值n可能小于
len(p)
,讀取到達(dá)結(jié)尾時,返回值n
將為0
而err
將為io.EOF
- 類似
File.Read()
方法
-
示例:
s := strings.NewReader("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
br := bufio.NewReader(s)
b := make([]byte, 20)
n, err := br.Read(b)
fmt.Printf("%-20s %-2v %v\n", b[:n], n, err) // ABCDEFGHIJKLMNOPQRST 20 <nil>
n, err = br.Read(b)
fmt.Printf("%-20s %-2v %v\n", b[:n], n, err) // UVWXYZ1234567890 16 <nil>
n, err = br.Read(b)
fmt.Printf("%-20s %-2v %v\n", b[:n], n, err) // 0 EOF
-
Reader.ReadBytes(delim byte) (line []byte, err error)
-
delim
是delimiter
的縮寫意為定位符 -
ReadBytes
讀取直到第一次遇到delim
字節(jié)司顿,返回一個包含已讀取的數(shù)據(jù)和delim
字節(jié)的切片
-
示例:
s := strings.NewReader("ABCDEFG\n123456\n")
br := bufio.NewReader(s)
for {
sli, err := br.ReadBytes('\n')
if err err == io.EOF {
break
}
fmt.Println(sli)
}
// [65 66 67 68 69 70 71 10]
// [49 50 51 52 53 54 10]
-
Reader.ReadString(delim byte) (line string, err error)
- 返回的是字符串類型
示例:
s := strings.NewReader("ABCDEFG\n123456\n")
br := bufio.NewReader(s)
for {
s, err := br.ReadString('\n')
if err err == io.EOF {
break
}
fmt.Print(s)
}
// ABCDEFG
// 123456
bufio.Writer結(jié)構(gòu)體
-
NewWriter(w io.Writer) *Writer
-
NewWriter
創(chuàng)建一個具有默認(rèn)大小緩沖芒粹、寫入w
的*Writer
-
-
Writer.Write(p []byte) (nn int, err error)
-
Write
將p
的內(nèi)容寫入緩沖。返回寫入的字節(jié)數(shù)大溜。如果返回值nn < len(p)
化漆,還會返回一個錯誤說明原因 - 類似
File.Write()
方法
-
-
Writer.WriteString(s string) (int, error)
- 寫入一個字符串,返回寫入的字節(jié)數(shù)
-
Writer.Flush() error
- Flush方法將緩沖中的數(shù)據(jù)輸出
示例:
file1, _ := os.Open("aa.txt")
defer file1.Close()
reader := bufio.NewReader(file1)
file2, _ := os.Create("cc.txt")
defer file2.Close()
writer := bufio.NewWriter(file2)
for {
bs, err := reader.ReadBytes('\n')
if err == io.EOF {
fmt.Println("讀取完畢")
break
}
writer.Write(bs)
writer.Flush()
}
bufio.Scanner結(jié)構(gòu)體
-
NewScanner(r io.Reader) *Scanner
- 創(chuàng)建并返回一個從
r
讀取數(shù)據(jù)的Scanner
钦奋,默認(rèn)的分割函數(shù)是ScanLines
- 通過
Scanner.Split(split SplitFunc)
方法座云,可以為Scanner
指定splitFunc
- Scanner可以通過plitFunc將
r
中的數(shù)據(jù)拆分為多個token疙赠,然后通過Scanner.Scan()
依次讀取
- 創(chuàng)建并返回一個從
-
bufio
中提供的默認(rèn)splitFunc
:-
ScanBytes
,按照byte
進(jìn)程拆分 -
ScanRunes
朦拖,按照行("\n")
進(jìn)程拆分 -
ScanWords
圃阳,按照utf-8
字符進(jìn)行拆分 -
ScanLines
,按照單詞(" ")
進(jìn)程拆分
-
- 常用方法
Split(split SplitFunc)
Scan() bool
Text() string
Bytes() []byte
示例:
scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
if scanner.Text() == "q" {
break
}
fmt.Println(scanner.Text()) // Println will add back the final '\n'
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "reading standard input:", err)
}