go語言文件讀取以及IO操作

文章目錄

  • 文件信息接口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ù)有兩個包逻杖,pathpath/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í)行)
    • 如果文件存在會清空它

打開文件

  • os.Open(name string) (file *File, err error)

    • 底層調(diào)用OpenFile(name, O_RDONLY, 0)
    • 以只讀的方式打開文件
  • os.OpenFile(name string, flag int, perm FileMode) (file *File, err error)

    • perm可為06660777
    • flagos包中定義的常量:
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ù)
    • 讀取到末尾時errEOF(end of file)
  • 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.Readerio.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將為0err將為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)
    • delimdelimiter的縮寫意為定位符
    • 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)
    • Writep的內(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()依次讀取
  • 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)
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末璧帝,一起剝皮案震驚了整個濱河市捍岳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌裸弦,老刑警劉巖祟同,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異理疙,居然都是意外死亡晕城,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門窖贤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來砖顷,“玉大人,你說我怎么就攤上這事赃梧÷蓑穑” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵授嘀,是天一觀的道長物咳。 經(jīng)常有香客問我,道長蹄皱,這世上最難降的妖魔是什么览闰? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮巷折,結(jié)果婚禮上压鉴,老公的妹妹穿的比我還像新娘。我一直安慰自己锻拘,他們只是感情好油吭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著署拟,像睡著了一般婉宰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上推穷,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天芍阎,我揣著相機(jī)與錄音,去河邊找鬼缨恒。 笑死谴咸,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的骗露。 我是一名探鬼主播岭佳,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼萧锉!你這毒婦竟也來了珊随?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤柿隙,失蹤者是張志新(化名)和其女友劉穎叶洞,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體禀崖,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡衩辟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了波附。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片艺晴。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖掸屡,靈堂內(nèi)的尸體忽然破棺而出封寞,到底是詐尸還是另有隱情,我是刑警寧澤仅财,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布狈究,位于F島的核電站,受9級特大地震影響盏求,放射性物質(zhì)發(fā)生泄漏抖锥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一风喇、第九天 我趴在偏房一處隱蔽的房頂上張望宁改。 院中可真熱鬧,春花似錦魂莫、人聲如沸还蹲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谜喊。三九已至,卻和暖如春倦始,著一層夾襖步出監(jiān)牢的瞬間斗遏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工鞋邑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诵次,地道東北人账蓉。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像逾一,于是被迫代替她去往敵國和親铸本。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容