Basic operation of documents

Keywords: Go encoding

Read entire file

  • Reading the entire file into memory is one of the most basic file operations. This requires the ReadFile function in the ioutil package.
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
)

func main() {

	fptr := flag.String("path", "test.txt", "Path to the file to be read")
	flag.Parse()

	data, err := ioutil.ReadFile(*fptr)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(string(data))
}
  • The above uses the runtime parameter - path=test1.txt to specify the read file, or the absolute path of the file.

Read files in blocks

  • When the file is very large, especially in the case of insufficient memory, it is meaningless to read the entire file into memory.
  • A better way is to read the file in chunks. This can be done using the bufio package.
  • Using the 'NewReader()' function of bufio package, the Read method can Read the contents of the file into the buffered byte array.
package main

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

func main() {

	// Open file
	f, err := os.Open("test.txt")
	if err != nil {
		fmt.Println(err)
	}
	// Delay closing files
	defer func() {
		if err := f.Close(); err != nil {
			fmt.Println(err)
		}
	}()
	// File reader
	r := bufio.NewReader(f)
	buf := make([]byte, 3) // It's easy to demonstrate the small settings
	str := ""
	for {
		_, err := r.Read(buf)
		if err != nil {
			if err == io.EOF {
				fmt.Println("File read completed!")
			} else {
				fmt.Println(err)
			}
			break
		}
		fmt.Println(string(buf))
		str += string(buf)
	}
	fmt.Println("The complete results are as follows:\n", str)
}

Read file line by line

  • When the file is large, it can also be read line by line.
  • Using the 'NewScanner()' function of bufio package, the Scan method can determine whether there is another line,

The Text method can get the current line, and the Err method can get the error information.

package main

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

func main() {

	// Open file
	f, err := os.Open("test.txt")
	if err != nil {
		fmt.Println(err)
	}
	// Delay closing files
	defer func() {
		if err := f.Close(); err != nil {
			fmt.Println(err)
		}
	}()
	// File reader
	s := bufio.NewScanner(f)
	str := ""
	for s.Scan() {
		fmt.Println(s.Text(), "\n-------Separator--------")
		str += s.Text()
	}
	if s.Err() != nil {
		fmt.Println(s.Err().Error())
	}
	fmt.Println("The complete results are as follows:\n", str)
}

String write to file

  • Use create to create a file with the specified name.

If the file already exists, the create function will truncate the file. This function returns a file descriptor.

package main

import (
	"fmt"
	"os"
)

func main() {

	f, err := os.Create("123.txt")
	if err != nil {
		fmt.Println(err)
	}
	defer func() {
		if err = f.Close(); err != nil {
			fmt.Println(err)
		}
	}()

	_, err = f.WriteString("Hello World!")
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("File written successfully!")
}

Byte write to file

  • Use the Write method to Write byte array data. Generally, it is the decimal encoding of UTF-8 corresponding to the character.
package main

import (
	"fmt"
	"os"
)

func main() {

	f, err := os.Create("123.txt")
	if err != nil {
		fmt.Println(err)
	}

	defer func() {
		if err = f.Close(); err != nil {
			fmt.Println(err)
		}
	}()

	bytes := []byte{104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100}
	_, err = f.Write(bytes)

	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("File write complete")
}

Write file line by line

  • Use fmt.Fprintln function to write file line by line.
package main

import (
	"fmt"
	"os"
)

func main() {

	f, err := os.Create("123.txt")
	if err != nil {
		fmt.Println(err)
	}

	defer func() {
		if err = f.Close(); err != nil {
			fmt.Println(err)
		}
	}()

	lines := []string{"Hello", "GoLang", "World"}

	for _, v := range lines {
		_, err = fmt.Fprintln(f, v)
		if err != nil {
			fmt.Println(err)
		}
	}

	fmt.Println("File write complete.")
}

Append file content

  • The os.OpenFile(name string, flag int, perm FileMode) (*File, error) function can specify the file operation mode.
package main

import (
	"fmt"
	"os"
)

func main() {

	f, err := os.OpenFile("123.txt", os.O_APPEND|os.O_RDONLY, 0644)
	if err != nil {
		fmt.Println(err)
	}

	defer func() {
		if err = f.Close(); err != nil {
			fmt.Println(err)
		}
	}()

	lines := []string{"123", "abc", "!@#"}

	for _, v := range lines {
		_, err = fmt.Fprintln(f, v)
		if err != nil {
			fmt.Println(err)
		}
	}

	fmt.Println("File append write complete.")
}

Write files concurrently

  • Pay attention to race conditions when writing files.
package main

import (
	"fmt"
	"math/rand"
	"os"
	"sync"
)

func main() {

	chNum := make(chan int)
	chExit := make(chan bool)
	wg := sync.WaitGroup{}

	// Producer
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go makeRandom(chNum, &wg)
	}

	// Consumer
	go writeFile(chNum, chExit)

	wg.Wait()
	close(chNum)

	if <-chExit {
		fmt.Println("File written successfully.")
	} else {
		fmt.Println("File write failed.")
	}

}

func makeRandom(chNum chan int, wg *sync.WaitGroup) {

	chNum <- rand.Intn(1000)
	wg.Done()

}

func writeFile(chNum chan int, chExit chan bool) {

	f, err := os.Create("123.txt")
	if err != nil {
		fmt.Println(err)
	}
	defer func() {
		if err = f.Close(); err != nil {
			fmt.Println(err)
		}
	}()

	for val := range chNum {
		_, err = fmt.Fprintln(f, val)
		if err != nil {
			fmt.Println(err)
		}
	}

	chExit <- true
}

Posted by dannymc1983 on Thu, 09 Apr 2020 10:21:26 -0700