golang讀寫文件

1. 標準輸入輸出html

os提供了標準輸入輸出文件:golang

    Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
    Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
    Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
func NewFile(fd uintptr, name string) *File

2. os包讀取文件安全

文件使用os.File類型的指針來表示,也叫做文件句柄。File是struct,表示一個open file descriptor。標準輸入輸出os.Stdin/os.Stdout都是*os.File。app

os.File與unix file descriptor fd使用相似,但不能共同使用。golang中用os.File封裝或代替unix fd。less

func NewFile(fd uintptr, name string) *File

NewFile returns a new File with the given file descriptor and name. The returned value will be nil if fd is not a valid file descriptor.ide

func (f *File) Fd() uintptr

Fd returns the integer Unix file descriptor referencing the open file. The file descriptor is valid only until f.Close is called or f is garbage collected. 函數

On Unix systems this will cause the SetDeadline methods to stop working.post

os包包含操做文件的最底層處理函數,相似unix系統調用。ui

const (
    // Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.
    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.
    // The remaining values may be or'ed in to control behavior.
    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  // truncate regular writable file when opened.
)
const (
    SEEK_SET int = 0 // seek relative to the origin of the file
    SEEK_CUR int = 1 // seek relative to the current offset
    SEEK_END int = 2 // seek relative to the end
)
var (
    // ErrInvalid indicates an invalid argument.
    // Methods on File will return this error when the receiver is nil.
    ErrInvalid = errInvalid() // "invalid argument"

    ErrPermission = errPermission() // "permission denied"
    ErrExist      = errExist()      // "file already exists"
    ErrNotExist   = errNotExist()   // "file does not exist"
    ErrClosed     = errClosed()     // "file already closed"
    ErrNoDeadline = errNoDeadline() // "file type does not support deadline"
)
type File struct {
        // contains filtered or unexported fields
} func Open(name string) (*File, error) func OpenFile(name string, flag int, perm FileMode) (*File, error) func (f *File) Read(b []byte) (n int, err error) func (f *File) Write(b []byte) (n int, err error) func (f *File) WriteString(s string) (n int, err error)
func (f *File) Seek(offset int64, whence int) (ret int64, err error)
func Create(name string) (*File, error)

Open()默認的mode爲O_RDONLY。this

Read reads up to len(b) bytes from the File. It returns the number of bytes read and any error encountered. At end of file, Read returns 0, io.EOF.

Write writes len(b) bytes to the File. It returns the number of bytes written and an error, if any. Write returns a non-nil error when n != len(b).

Seek sets the offset for the next Read or Write on file to offset, interpreted according to whence: 0 means relative to the origin of the file, 1 means relative to the current offset, and 2 means relative to the end. It returns the new offset and an error, if any.  

package main
import (
    "fmt"
    "os"
    "log"
    "io"
    _"strings"
)

func main(){
    file, err := os.OpenFile("file.txt", os.O_APPEND | os.O_RDWR | os.O_CREATE, 0644)
    if err != nil {
        log.Fatal(err)
    }   
    defer file.Close()
    
    if _, err := file.Write([]byte("appended some data\n")); err != nil {
        log.Fatal(err)
    }   
    if _, err := file.Seek(0, os.SEEK_SET); err != nil {
        log.Fatal(err)
    }   

    buf := make([]byte, 1024)
    err = nil 
    for err == nil {
        n, err := file.Read(buf)
        if err == io.EOF {
            break   
        }
        fmt.Printf("Read %d bytes:", n)
        //fmt.Println(strings.TrimSpace(string(buf)))
        fmt.Println((string(buf)))
    }   
}

3. io/ioutil包讀取文件

io包對os包的file基礎操做封裝爲interface,並行處理非安全。

Package io provides basic interfaces to I/O primitives. Its primary job is to wrap existing implementations of such primitives, such as those in package os, into shared public interfaces that abstract the functionality, plus some other related primitives.

Because these interfaces and primitives wrap lower-level operations with various implementations, unless otherwise informed clients should not assume they are safe for parallel execution.

type Reader interface {
    Read(p []byte) (n int, err error)
}
type Writer interface {
    Write(p []byte) (n int, err error)
}
type StringWriter interface {
    WriteString(s string) (n int, err error)
}
type ReadWriter interface {
    Reader
    Writer
}
func ReadFull(r Reader, buf []byte) (n int, err error)
func WriteString(w Writer, s string) (n int, err error)
func Copy(dst Writer, src Reader) (written int64, err error)
    r := strings.NewReader("some io.Reader stream to be read\n")

    if _, err := io.Copy(os.Stdout, r); err != nil {
        log.Fatal(err)
    }
func copyFile(source string, dest string) (err error) {
    sf, err := os.Open(source)
    if err != nil {
        return err
    }
    defer sf.Close()
    df, err := os.Create(dest)
    if err != nil {
        return err
    }
    defer df.Close()
    _, err = io.Copy(df, sf)
    if err == nil {
        si, err := os.Stat(source)
        if err == nil {
            err = os.Chmod(dest, si.Mode())
        }

    }
    return
}

ioutil將整個文件的內容讀到一個內存中。

func ReadFile(filename string) ([]byte, error)
func WriteFile(filename string, data []byte, perm os.FileMode) error
func ReadAll(r io.Reader) ([]byte, error)

示例:

package main
import (
        "fmt"
        "io/ioutil" ) func main(){ // data, err := ioutil.ReadFile("/home/golang/file/test.txt") data, err := ioutil.ReadFile("./test.txt") if err != nil { fmt.Println("File reading error", err) return } fmt.Println("Contents of File:", string(data)) }

4. bufio包緩衝讀取(buffered reader)文件

Package bufio implements buffered I/O. It wraps an io.Reader or io.Writer object, creating another object (Reader or Writer)

that also implements the interface but provides buffering and some help for textual I/O. 

bufio提供了新的bufio.Reader, bufio.Writer, bufio.Scanner結構體,提供緩衝讀寫操做。

type ReadWriter struct {
    *Reader
    *Writer
}
type Reader struct {
    // contains filtered or unexported fields
}
type Scanner struct {
    // contains filtered or unexported fields
}
type Writer struct {
    // contains filtered or unexported fields
}
type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)

相關函數:

func NewReader(rd io.Reader) *Reader
func (b *Reader) ReadString(delim byte) (string, error)
func (b *Reader) ReadByte() (byte, error)
func (b *Reader) ReadBytes(delim byte) ([]byte, error)
func (b *Reader) Read(p []byte) (n int, err error)

func NewWriter(w io.Writer) *Writer
func (b *Writer) Write(p []byte) (nn int, err error)
func (b *Writer) WriteByte(c byte) error
func (b *Writer) WriteRune(r rune) (size int, err error)
func (b *Writer) WriteString(s string) (int, error)
func (b *Writer) Flush() error

ReadString(delim byte)從輸入中讀取內容,直到碰到 delim 指定的字符,而後將讀取到的內容連同 delim 字符一塊兒放到緩衝區。ReadBytes()相似,但ReadByte()僅讀取一個字節。

ReadString()只能讀取字符串,Read()能夠讀取任何數據,包括二進制文件。

os.File實現了io.Reader接口定義的方法,因此可用os.File替換io.Reader傳參。如NewReader(os.File)。

        var inputReader *bufio.Reader
        var input string
        var err error inputReader = bufio.NewReader(os.Stdin) fmt.Println("Please Enter some input:") input, err = inputReader.ReadString('\n') if err == nil { fmt.Printf("The input was: %s\n", input) }
        inputFile, inputError := os.Open("test.txt")
        if inputError != nil {
                fmt.Printf("An error occurred on openning th inputfile\n")
                return
        }

        defer inputFile.Close()
        inputReader := bufio.NewReader(inputFile)
        for {
                inputString, readerError := inputReader.ReadString('\n')
                if readerError == io.EOF {
                        return
                }
                fmt.Printf("The input was: %s", inputString)
        }    
    r := bufio.NewReader(f)
    b := make([]byte, 3) for { _, err := r.Read(b) //每次讀取3個字節 if err != nil { fmt.Println("Error reading file:", err) break } fmt.Println(string(b)) }
    writer := bufio.NewWriter(fileObj)
 defer writer.Flush()
    writer.WriteString(data)

bufio逐行讀取文件

    f, err := os.Open("./test.txt")
    if err != nil { log.Fatal(err) } defer func() { if err = f.Close(); err != nil { log.Fatal(err) } }() s := bufio.NewScanner(f) for s.Scan() { fmt.Println(s.Text()) } err = s.Err() if err != nil { log.Fatal(err) }

相關函數:

func NewScanner(r io.Reader) *Scanner
func (s *Scanner) Scan() bool func (s *Scanner) Text() string

NewScanner returns a new Scanner to read from r. The split function defaults to ScanLines.

5. 判斷文件是否存在

type FileInfo interface {
    Name() string       // base name of the file
    Size() int64        // length in bytes for regular files; system-dependent for others
    Mode() FileMode     // file mode bits
    ModTime() time.Time // modification time
    IsDir() bool        // abbreviation for Mode().IsDir()
    Sys() interface{}   // underlying data source (can return nil)
}

func Lstat(name string) (FileInfo, error)
Lstat returns a FileInfo describing the named file. If the file is a symbolic link, 
the returned FileInfo describes the symbolic link. 

func Stat(name string) (FileInfo, error)
Stat returns a FileInfo describing the named file. 
If there
is an error, it will be of type *PathError.
func FileExist(filename string) bool {
    _, err := os.Stat(filename)
    if os.IsNotExist(err) {
        return false
    }
//    fmt.Println(err)
    return err == nil || os.IsExist(err)
}

6. 遍歷目錄

 須要用到path和path/filepath包。

func Rel(basepath, targpath string) (string, error)
Rel returns a relative path that is lexically equivalent to targpath 
when joined to basepath with an intervening separator.
That is, Join(basepath, Rel(basepath, targpath)) is equivalent to targpath itself. basepath/rel == targpath func Walk(root string, walkFn WalkFunc) error Walk walks the file tree rooted at root, calling walkFn for each file or directory in the tree,
including root. All errors that arise visiting files and directories are filtered by walkFn. type WalkFunc func(path
string, info os.FileInfo, err error) error The path argument contains the argument to Walk as a prefix;
that is, if Walk is called with "dir", which is a directory containing the file "a",
the walk function will be called with argument "dir/a".
The info argument is the os.FileInfo for the named path.
import "path/filepath"
func fileList(dir string) error {
    fullPath, err := filepath.Abs(dir)
    if err != nil {
        return err
    }
    
    callback := func(path string, fi os.FileInfo, err error) error {
        if fi.IsDir() {
            return nil
        }

        rel, err := filepath.Rel(fullPath, path)
        if err != nil {
            return err
        }
        fmt.Println("rel:", rel, "\tbasepath:", fullPath, "\ttargpath:", path)
        return nil
    }

    return filepath.Walk(fullPath, callback)
}

遍歷一個目錄下指定類型文件,使用ioutil.ReadDir()

func ReadDir(dirname string) ([]os.FileInfo, error)
ReadDir reads the directory named by dirname and 
returns a list of directory entries sorted by filename. func Ext(path
string) string Ext returns the file name extension used by path.
The extension
is the suffix beginning at the final dot in the final slash-separated element of path;
it is empty if there is no dot.
package main

import (
    "fmt"
    _"io"
    "io/ioutil"
    "path"
)

func fileList(dir string, ftype string) ( map[int] string,  error) {
    fdir , err := ioutil.ReadDir(dir)
    if err != nil {
        return nil, err
    }

    var list map[int] string = make(map[int]string)
    for n, fi := range fdir {
        fname := fi.Name()
        if ext := path.Ext(fname); ext != ftype{
            continue
        }
        fname_rel := dir + "/"+fname
        list[n] = fname_rel
    }
    
    return list, nil
}

func main(){
    flist, err := fileList(".", ".go") 
    if err != nil {
        fmt.Println(err)
    }

    for i, ff := range flist {
        fmt.Println(i, ":", ff)
    }
}

 

參考:

1.   https://golang.google.cn/pkg/fmt/#Scanln

2.   https://www.kancloud.cn/kancloud/the-way-to-go/72678

3.   https://studygolang.com/subject/2

4.     https://golang.google.cn/pkg/os

5.     golang讀寫文件的幾種方式

6.    go語言功能代碼

相關文章
相關標籤/搜索