go語言文件操作,這期資料比較詳細( 歡迎加入go語言群: 218160862 )


 

go語言文件操作,這期資料比較詳細

歡迎加入go語言群: go語言深圳群 golang深圳 218160862

點擊加入 go語言深圳群 golang深圳


文件操作


func Open(name string) (file *File, err error),*File 是實現了 io.Reader這個接口
byte[] 轉化為 bytes.Buffer:bytes.NewBuffer([]byte).


一、建立與打開

建立文件函數:
func Create(name string) (file *File, err Error)
func NewFile(fd int, name string) *File


打開文件函數:
func Open(name string) (file *File, err Error)
func OpenFile(name string, flag int, perm uint32) (file *File, err Error)

 

判斷文件是否存在:
// it returns false when it's a directory or does not exist.
func IsFile(file string) bool {
    f, e := os.Stat(file)
    if e != nil {
        return false
    }
    return !f.IsDir()
}

// IsExist returns whether a file or directory exists.
func IsExist(path string) bool {
    _, err := os.Stat(path)
    return err == nil || os.IsExist(err)
}


// 追加寫入文件日志
func myLog( str string ){
    // 這行使用追加模式寫入文件,如果文件不存在則創建
    fp, err := os.OpenFile( LOGFILE, os.O_CREATE|os.O_APPEND|os.O_RDWR,0660 )
    defer fp.Close()
    
    if err != nil{
        walk.MsgBox(nil, "寫入日志結果:", "失敗", walk.MsgBoxIconError)
    }
    
    timeStr := time.Now().Format("2006-01-02 15:04:05") // 這是個奇葩,必須是這個時間點, 據說是go誕生之日, 記憶方法:6-1-2-3-4-5
    fp.WriteString( timeStr + " 日志信息: " + str + " \n" )    
}




二、寫文件


寫文件函數:
func (file *File) Write(b []byte) (n int, err Error)
func (file *File) WriteAt(b []byte, off int64) (n int, err Error)
func (file *File) WriteString(s string) (ret int, err Error)


寫文件示例代碼:

 package main
import (
        "os"
        "fmt"
)
func main() {
        userFile := "test.txt"
        fout,err := os.Create(userFile)
        defer fout.Close()
        if err != nil {
                fmt.Println(userFile,err)
                return
        }
        for i:= 0;i<10;i++ {
                fout.WriteString("Just a test!\r\n")
                fout.Write([]byte("Just a test!\r\n"))
        }
}

 
三、讀文件


讀文件函數:
func (file *File) Read(b []byte) (n int, err Error)
func (file *File) ReadAt(b []byte, off int64) (n int, err Error)

具體見官網:http://golang.org/pkg/os/#File.Read
 
讀文件示例代碼:

package main
import (
        "os"
        "fmt"
)
func main() {
        userFile := "test.txt"
        fin,err := os.Open(userFile)
        defer fin.Close()
        if err != nil {
                fmt.Println(userFile,err)
                return
        }
        buf := make([]byte, 1024)
        for{
                n, _ := fin.Read(buf)
                if 0 == n { break }
                os.Stdout.Write(buf[:n])
        }
}

 
四、刪除文件


函數:
func Remove(name string) Error

------------------------------------------------------------------------------------------------
使用os庫os.Open os.Create。

package main
import (
    "io"
    "os"
)
 
func main() {
    fi, err := os.Open("input.txt")
    if err != nil { panic(err) }
    defer fi.Close()
 
    fo, err := os.Create("output.txt")
    if err != nil { panic(err) }
    defer fo.Close()
 
    buf := make([]byte, 1024)
    for {
        n, err := fi.Read(buf)
        if err != nil && err != io.EOF { panic(err) }
        if n == 0 { break }
 
        if n2, err := fo.Write(buf[:n]); err != nil {
            panic(err)
        } else if n2 != n {
            panic("error in writing")
        }
    }
}

 
使用bufio庫
package main
import (
    "bufio"
    "io"
    "os"
)
 
func main() {
    fi, err := os.Open("input.txt")
    if err != nil { panic(err) }
    defer fi.Close()
    r := bufio.NewReader(fi)
 
    fo, err := os.Create("output.txt")
    if err != nil { panic(err) }
    defer fo.Close()
    w := bufio.NewWriter(fo)
 
    buf := make([]byte, 1024)
    for {
        n, err := r.Read(buf)
        if err != nil && err != io.EOF { panic(err) }
        if n == 0 { break }
 
        if n2, err := w.Write(buf[:n]); err != nil {
            panic(err)
        } else if n2 != n {
            panic("error in writing")
        }
    }
 
    if err = w.Flush(); err != nil { panic(err) }
}


使用ioutil庫
package main
import (
    "io/ioutil"
)
 
func main() {
    b, err := ioutil.ReadFile("input.txt")
    if err != nil { panic(err) }
 
    err = ioutil.WriteFile("output.txt", b, 0644)
    if err != nil { panic(err) }
}


五、遍歷文件夾
package main
import (
    "path/filepath"
    "os"
    "fmt"
    "flag"
)

func getFilelist(path string) {
        err := filepath.Walk(path, func(path string, f os.FileInfo, err error) error {
                if ( f == nil ) {return err}
                if f.IsDir() {return nil}
                println(path)
                return nil
        })
        if err != nil {
                fmt.Printf("filepath.Walk() returned %v\n", err)
        }
}

func main(){
        flag.Parse()
        root := flag.Arg(0)
        getFilelist(root)
}












 golang編程之文件操作 2013-11-17 16:11:07

分類: LINUX

    操作文件是任何編程語言都繞不過,要掌握一門語言,知道如何操作文件是必不可少的,今天學習了下golang對文件操作的支持。
    golang對文件的支持是在os package里。我無意將本文寫成官方文檔的模樣,我只是想討論如何利用這些接口操作文件。
    OPEN
     熟悉文件系統的人都知道,open是整個文件系統中最復雜的接口之一。熟悉C語言的都知道,C語言中有open和creat,接口如下:

           #include <sys/types.h>
           #include <sys/stat.h>
           #include <fcntl.h>

           int open(const char *pathname, int flags);
           int open(const char *pathname, int flags, mode_t mode);

           int creat(const char *pathname, mode_t mode)

    對C的open而言,如果flag里面有了O_CREAT,那么必須帶上mode參數,制定創建文件時的perm,如果文件已經存在了,這個O_CREAT標志就無效了(除非O_EXCL標志被指定。 除了O_CREAT,還有很多的標志  

    O_RDONLY
    O_WRONLY
    O_RDWR
    O_DIRECT
    O_APPEND
    O_TRUNC
    。。。。
    這些標志位基本是顧名思義,對於open這種很復雜很綜合的文件操作,golang中對應的是OpenFile   

    func OpenFile(name string, flag int, perm FileMode) (file *File, err error)

    我們看到了也有flag,也有FileMode.比如說我要讀寫打開一個文件,如果不存在就創建,如果存在,就追加寫,如何寫go 代碼?

        f,err := os.OpenFile("test.txt",os.O_CREATE|os.O_APPEND|os.O_RDWR,0660)
        if(err != nil){
            panic(err)
        }

    我們看到了,golang中也有這些標志(注意O_CREATE,在C語言中,是O_CREAT),我在上面代碼片段中用了幾個標志

    const (
            O_RDONLY int = syscall.O_RDONLY // open the file read-only.
            O_WRONLY int = syscall.O_WRONLY // open the file write-only.
            O_RDWR int = syscall.O_RDWR // open the file read-write.
            O_APPEND int = syscall.O_APPEND // append data to the file when writing.
            O_CREATE int = syscall.O_CREAT // create a new file if none exists.
            O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist
            O_SYNC int = syscall.O_SYNC // open for synchronous I/O.
            O_TRUNC int = syscall.O_TRUNC // if possible, truncate file when opened.
          )

     C語言中有creat,沒有則創建,有則截斷寫,本質等於O_WRONLY | O_CREAT | O_TRUNC

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    int creat (const char *name, mode_t mode)

    Ken Thompson大神曾經戲言,漏掉creat系統調用中的e字母是他設計Unix最后悔的事情,呵呵看起來老爺子接收了教訓,沒有犯同樣的拼寫錯誤,golang中對應的接口是Create(大神這一次沒有拼寫錯)

    func Create(name string) (file *File, err error)

    和C的creat系統調用相比,少了mode入參,默認是0x666(before umask),同時標志不再是O_WRONLY,而是O_RDWR,仍然帶創建標志位,仍然帶截斷標志。
    golang中的Open和C中的open就不能相比了(和C中的open PK那是OpenFile的事兒)接口如下:    

    func Open(name string) (file *File, err error)

    直白說,就是帶O_RDONLY的open,太菜了。

    CLOSE
    這個接口無甚好說。接口如下

    func (f *File) Close() error

    但說接口沒啥說的,但是golang提供了defer,這是一個我認為很贊的特點,就是將不得不做的cleanup放到defer去做。
    我們寫C的人,經常遇到了這種代碼  

    fd = open(...)
    if(fd < 0 )
    {
        ...
    }

    if (failed_1)
    {
       ...
       close(fd);
       ....
    }

    if(faile_2)
    {
        ...
        close(fd);
        ...
    }
    ....

    只要打開了文件,每次異常處理都要想着close,否則句柄泄漏,太煩。所以C語言是一門你要小心伺候的語言。
    go提供了defer解決這種困境,后面不用時刻惦記close,函數退出前,會執行close。

        f,err := os.OpenFile("test.txt",os.O_CREATE|os.O_APPEND|os.O_RDWR,0660)
        if(err != nil){
            panic("open file failed")
        }
        defer f.Close()
        ...

    READ和WRITE
    read和write是比較重要的文件操作了,這是C的接口。

      #include <unistd.h>

      ssize_t write(int fd, const void *buf, size_t count);
      ssize_t read(int fd, void *buf, size_t count)

    對於golang,接口如下:  

    func (f *File) Read(b []byte) (n int, err error)
    func (f *File) ReadAt(b []byte, off int64) (n int, err error)

    func (f *File) Write(b []byte) (n int, err error)
    func (f *File) WriteAt(b []byte, off int64) (n int, err error)
    func (f *File) WriteString(s string) (ret int, err error)

   看到代碼片段,學習使用讀寫接口:  

        read_buf := make([]byte,32)
        var pos int64 = 0
        for{

            n,err := f.ReadAt(read_buf,pos)
            if err != nil && err != io.EOF{
                panic(err)
            }
            if n == 0{
                fmt.Printf("\nfinish read\n")
                break
            }
            fmt.Printf("%s",string(read_buf[:n]))
            pos = pos +(int64)(n)
        }

    在看一個代碼片段:

        var buff = make([]byte,1024)
        for{
            n,err := fi.Read(buff)
            if err != nil && err != io.EOF{
                panic(err)
            }
            
            if n == 0{
                break
            }

            if _,err := fo.Write(buff[:n]); err != nil{
                panic(err)
            }

        }

    最后,我寫了一個完整的代碼,完成簡單cp功能,就叫mycp  

    manu@manu-hacks:~/code/go/self$ cat mycp.go
    package main
    import "fmt"
    import "os"
    import "io"

    func usage(){
        fmt.Printf("%s %s %s\n",os.Args[0],"filename" , "newfile")
    }


    func main(){
        
        if len(os.Args) != 3{
            usage()
            return
        }

        filename_in := os.Args[1]
        fi,err := os.Open(filename_in)
        if err != nil{
            panic(err)
        }
        defer fi.Close()

        filename_out := os.Args[2]
        fo,err := os.Create(filename_out)
        if err != nil{
            panic(err)
        }
        defer fo.Close()


        var buff = make([]byte,1024)
        for{
            n,err := fi.Read(buff)
            if err != nil && err != io.EOF{
                panic(err)
            }
            
            if n == 0{
                break
            }

            if _,err := fo.Write(buff[:n]); err != nil{
                panic(err)
            }

        }
    }

    執行結果:  

    manu@manu-hacks:~/code/go/self$ ./mycp test.txt test.bak
    manu@manu-hacks:~/code/go/self$ diff test.txt test.bak
    manu@manu-hacks:~/code/go/self$ cat test.txt
    this is test file created by go
    if not existed ,please create this file
    if existed, Please write append
    hello world,hello go
    this is test file created by go
    if not existed ,please create this file
    if existed, Please write append
    hello world,hello go


參考文獻
1 Linux system program
2 golang os package
3 StackOverflow How to read/write from/to file?



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM