Go language file operation

Posted by csousley on Tue, 01 Feb 2022 01:38:07 +0100

Opening and closing of files

  • Like C language, the operation of files in Go language is also through a FILE structure
type file struct {
	pfd     poll.FD
	name    string
	dirinfo *dirInfo 
}
type File struct {
	*file // os specific
}
  • Open function
    • func Open(name string) (file *File, err error)
    • Open opens a file for reading
  • Close function
    • func (f *File) Close() error
    • Close closes the file f
package main
import (
	"fmt"
	"os"
)

func main() {
	// 1. Open a file
	// Note: if the file does not exist, it will not be created and an error will be reported
	// Note: Open can only read, not write
	fp, err := os.Open("d:/lnj.txt")
	if err != nil{
		fmt.Println(err)
	}else{
		fmt.Println(fp)
	}

	// 2. Close a file
	defer func() {
		err = fp.Close()
		if err != nil {
			fmt.Println(err)
		}
	}()
}

File reading

  • Read function (read without buffer)
    • func (f *File) Read(b []byte) (n int, err error)
    • The Read method reads up to len(b) bytes of data from f and writes it to B,
package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	// 1. Open a file
	// Note: if the file does not exist, it will not be created and an error will be reported
	// Note: Open can only read, not write
	fp, err := os.Open("d:/lnj.txt")
	if err != nil{
		fmt.Println(err)
	}else{
		fmt.Println(fp)
	}

	// 2. Close a file
	defer func() {
		err = fp.Close()
		if err != nil {
			fmt.Println(err)
		}
	}()

	// 3. Read data of specified bytes
	// Note: \ n will also be read in
	//buf := make([]byte, 50)
	//count, err := fp.Read(buf)
	//if err != nil {
	//	fmt.Println(err)
	//}else{
	//	fmt.Println(count)
	//	fmt.Println(string(buf))
	//}

	// 4. Read all contents of the file until the end of the file
	buf := make([]byte, 10)
	for{
		count, err := fp.Read(buf)
		// Note: this line of code should be put before judging EOF, otherwise it will be read less than one line
		fmt.Print(string(buf[:count]))
		if err == io.EOF {
			break
		}
	}
}
  • ReadBytes and ReadString functions (read with buffer)
    • func (b *Reader) ReadBytes(delim byte) (line []byte, err error)
    • ReadBytes reads until delim bytes are encountered for the first time
    • func (b *Reader) ReadString(delim byte) (line string, err error)
    • ReadString reads until delim bytes are encountered for the first time
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func main() {
	// 1. Open a file
	// Note: if the file does not exist, it will not be created and an error will be reported
	// Note: Open can only read, not write
	fp, err := os.Open("d:/lnj.txt")
	if err != nil{
		fmt.Println(err)
	}else{
		fmt.Println(fp)
	}

	// 2. Close a file
	defer func() {
		err = fp.Close()
		if err != nil {
			fmt.Println(err)
		}
	}()

	// 3. Read a row of data
	// Create read buffer, default size 4096
	//r :=bufio.NewReader(fp)
	//buf, err := r.ReadBytes('\n')
	//buf, err := r.ReadString('\n')
	//if err != nil{
	//	fmt.Println(err)
	//}else{
	//	fmt.Println(string(buf))
	//}

	// 4. Read all contents of the file until the end of the file
	r :=bufio.NewReader(fp)
	for{
		//buf, err := r.ReadBytes('\n')
		buf, err := r.ReadString('\n')
		fmt.Print(string(buf))
		if err == io.EOF{
			break
		}
	}
}
  • ReadFile function
    • func ReadFile(filename string) ([]byte, error)
    • Reads data from the file specified by filename and returns all contents of the file
    • Not suitable for reading large files
package main

import (
	"fmt"
	"io/ioutil"
)

func main() {

	filePath := "d:/lnj.txt"
	buf, err := ioutil.ReadFile(filePath)
	if err !=nil {
		fmt.Println(err)
	}else{
		fmt.Println(string(buf))
	}
}

File creation and writing

  • Create function
    • func Create(name string) (file *File, err error)
    • Create creates a file named name using mode 0666 (anyone can read and write, not executable)
    • If the file exists, the original file will be overwritten
  • Write function
    • func (f *File) Write(b []byte) (n int, err error)
    • Writes the specified byte array to a file
  • WriteString function
    • func (f *File) WriteString(s string) (ret int, err error)
    • Writes the specified string to a file
package main

import (
	"fmt"
	"os"
)

func main() {

	// 1. Create a file
	fp, err := os.Create("d:/lnj.txt")
	if err != nil{
		fmt.Println(err)
	}
	// 2. Close the open file
	defer func() {
		err := fp.Close()
		if err != nil {
			fmt.Println(err)
		}
	}()
	// 2. Write data to the file
	// Note: Windows line feed is \ r\n
	bytes := []byte{'l','n','j','\r','\n'}
	fp.Write(bytes)
	
	fp.WriteString("www.it666.com\r\n")
	fp.WriteString("www.itzb.com\r\n")
	// Note: Go language adopts UTF-8 encoding, and one Chinese occupies 3 bytes
	fp.WriteString("Li Nanjiang")
}
  • OpenFile function
    • func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
    • First parameter: open path
    • Second parameter: open mode
    const (
      O_RDONLY int = syscall.O_RDONLY // Open file in read-only mode
      O_WRONLY int = syscall.O_WRONLY // Open file in write only mode
      O_RDWR   int = syscall.O_RDWR   // Open file in read-write mode
      O_APPEND int = syscall.O_APPEND // Append data to the end of the file when writing
      O_CREATE int = syscall.O_CREAT  // If it does not exist, a new file will be created
      O_EXCL   int = syscall.O_EXCL   // And o_ For use with create, the file must not exist
      O_SYNC   int = syscall.O_SYNC   // Open file for synchronizing I/O
      O_TRUNC  int = syscall.O_TRUNC  // If possible, empty the file when opening
    )
    
    • Third parameter: specify permission
      • 0 does not have any permissions
      • 1. Execution permission (if it is an executable program, it can be run)
      • 2. Write permission
      • 3. Write permission and execution permission
      • 4. Read permission
      • 5. Read permission and execution permission
      • 6. Read and write permissions
      • 7. Read permission, write permission and execution permission
    const (
      // A single character is an abbreviation of an attribute used by the String method for formatting.
      ModeDir        FileMode = 1 << (32 - 1 - iota) // d: Catalogue
      ModeAppend                                     // a: Can only be written, and can only be written to the end
      ModeExclusive                                  // l: For execution
      ModeTemporary                                  // T: Temporary files (not backup files)
      ModeSymlink                                    // 50: Symbolic links (not shortcut files)
      ModeDevice                                     // D: Equipment
      ModeNamedPipe                                  // p: Named pipe (FIFO)
      ModeSocket                                     // S: Unix domain socket
      ModeSetuid                                     // u: Indicates that the file has the permission of its creator user id
      ModeSetgid                                     // g: Indicates that the file has permissions for its creator group id
      ModeCharDevice                                 // c: Character device, ModeDevice must be set
      ModeSticky                                     // t: Only root / creator can delete / move files
      // Overwrites all type bits (used to get type bits through &), which should not be set for ordinary files
      ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice
      ModePerm FileMode = 0777 // Override all Unix permission bits (used to get type bits through &)
    )
    
  • Write without buffer
package main

import (
	"fmt"
	"os"
)

func main() {

	// Note: the third parameter has no effect on Windows
	// -RW RW RW - (666) all users have file read and write permissions.
	//-rwxrwxrwx (777) all users have read, write and execute permissions.
	// 1. Open the file
	//fp, err := os.OpenFile("d:/lnj.txt", os.O_CREATE|os.O_RDWR, 0666)
	fp, err := os.OpenFile("d:/lnj.txt", os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		fmt.Println(err)
	}
	// 2. Close the open file
	defer func() {
		err := fp.Close()
		if err != nil {
			fmt.Println(err)
		}
	}()

	// Note:
	// If o_ When the rdwr mode is opened, the opened file has content and will be overwritten from the front
	// If o_ When the append mode is opened, the opened file has content and will be appended at the end
	// 3. Write data to the file
	bytes := []byte{'l','n','j','\r','\n'}
	fp.Write(bytes)
	fp.WriteString("www.it666.com\r\n")
}
  • Write with buffer
package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {

	// 1. Open the file
	fp, err := os.OpenFile("d:/lnj.txt", os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		fmt.Println(err)
	}
	// 2. Close the open file
	defer func() {
		err := fp.Close()
		if err != nil {
			fmt.Println(err)
		}
	}()

	// 3. Create buffer
	w := bufio.NewWriter(fp)

	// 4. Write data to buffer
	bytes := []byte{'l','n','j','\r','\n'}
	w.Write(bytes)
	w.WriteString("www.it666.com\r\n")

	// 5. Flush the data in the buffer to the file
	w.Flush()
}
  • WriteFile function
package main

import (
	"fmt"
	"io/ioutil"
)

func main() {

	// 1. Write data to the specified file
	data := []byte{'l','n','j','\r','\n'}
	err := ioutil.WriteFile("d:/abc.txt", data, 0666)
	if err != nil {
		fmt.Println(err)
	}else{
		fmt.Println("Write successful")
	}
}

Determine whether the file exists

  • Stat function
    • func Stat(name string) (fi FileInfo, err error)
  • Return value: FileInfo
type FileInfo interface {
    Name() string       // Name of the file (without extension)
    Size() int64        // The return value of ordinary file indicates its size; The meaning of the return value of other files is different from each system
    Mode() FileMode     // Mode bit of file
    ModTime() time.Time // Modification time of file
    IsDir() bool        // Equivalent to mode () IsDir()
    Sys() interface{}   // Underlying data source (nil can be returned)
}
  • Return value: error
    • The return value error equals nil, indicating that the file exists
    • The return value error is not equal to nil, which can be further judged by IsNotExist. If true is returned, it means that the file does not exist
    • The return value is error. If other errors are returned, it is uncertain whether the file exists
package main

import (
	"fmt"
	"os"
)

func main() {

	info, err := os.Stat("d:/lnj.txt")
	if err == nil {
		fmt.Println("File exists")
		fmt.Println(info.Name())
	}else if os.IsNotExist(err) {
		fmt.Println("file does not exist")
	}else{
		fmt.Println("uncertain")
	}
}

practice

  • Copy a text file to another file
    • Try to use other methods learned above to realize
package main

import (
	"fmt"
	"io/ioutil"
)

func main() {

	// 1. Read a file
	buf, err := ioutil.ReadFile("d:/lnj.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	// 2. Write the read data to another file
	err =ioutil.WriteFile("d:/abc.txt", buf, 0666)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("copy complete")

}
  • Copy a picture / video file to another file
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func main() {

	// 1. Define the path of the copied file
	scrPath := "D:/a.png"
	destPath := "E:/b.png"
	// 2. Open the copied file
	fr, err := os.Open(scrPath)
	if err != nil {
		fmt.Println(err)
		return
	}
	// 3. Close open file
	defer func() {
		err := fr.Close()
		if err != nil{
			fmt.Println(err)
		}
	}()
	// 4. Create read buffer
	r := bufio.NewReader(fr)

	// 1. Create a write file
	fw, err := os.Create(destPath)
	if err != nil {
		fmt.Println(err)
		return
	}
	// 2. Close open file
	defer func() {
		err := fw.Close()
		if err != nil{
			fmt.Println(err)
		}
	}()
	// 3. Create write buffer
	w := bufio.NewWriter(fw)
	// 4. Use the system copy function to complete the copy
	count, err := io.Copy(w, r)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(count)
	fmt.Println("copy complete")
}
  • Check the document yourself to traverse the folder
    • For example: give a folder path, get all the files under the folder, and save all the file paths to the slice

Topics: Go