Golang - 文件操作


打开文件

Open - 常用于只读

package main

import (
	"fmt"
	"os"
)

func main() {
	// 打开文件, os.Open(fileName)
	f, err := os.Open("a.txt")

	// defer 关闭
	f.Close()

	if err != nil {
		panic(err)
	}
}

OpenFile - 非只读

参数介绍
os.O_CREATE创建
os.O_RDONLY只读,通常直接使用os.Open方法
os.O_WRONLY只写
os.O_RDWR读写
os.O_TRUNC清空文件
os.O_APPEND追加
package main

import (
	"fmt"
	"os"
)

func main() {
	// 创建文件, 只写, 清空, 文件权限 0644, 如果不是创建, 权限可以写为 0
	f, err := os.OpenFile("a.txt", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)

	// defer 关闭
	f.Close()

	if err != nil {
		panic(err)
	}
}


源码

func OpenFile(name string, flag int, perm FileMode) (*File, error) {
	testlog.Open(name)
	return openFileNolog(name, flag, perm)
}

func Open(name string) (*File, error) {
	// 调用 OpenFile 方法, 模式固定为 后边两个参数固定为 O_RDONLY 和 0
	return OpenFile(name, O_RDONLY, 0)
}


读文件

Read([]byte) - 按照字节读取

package main

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

func main() {
	// 打开文件
	f, err := os.Open("a.txt")

	defer f.Close()

	if err != nil {
		panic(err)
	}

	// 创建一个切片, 作为 Read 方法的参数, 存放读取出来的字符
	x := make([]byte, 3)
	// 这个切片用于将每次/读取的字符拼接
	y := make([]byte, 0, 10)

	for {
		// 根据切片大小, 把读出来的文件, 放到切片中
		// 文本长度 > 切片长度, n 是切片长度
		// 切片长度 > 文本长度, n 是文本的实际长度
		n, err := f.Read(x)

		if err == io.EOF { // io.EOF 切片无内容时触发
			break
		}

		// 如果切片读取出现问题时, 打印报错
		if err != nil {
			panic(err)
		}

		// 每次将切片 x 中的内容, 放入 y 中
		// [:n] 是因为, 如果切片长度>文本长度, 此时创建切片会默认补齐后边的位数, 元素和前边相同, 所以需要舍弃文本长度后边的元素
		y = append(y, x[:n]...)
	}
	fmt.Println(string(y))
}



bufio.NewReader - 逐行读取

  • bufil 也有 Read() 方法, 使用示例与上一个例子类似
  • 本例中, 展示 ReadString()
package main

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

func main() {
	f, err := os.Open("a.txt")

	defer f.Close()

	if err != nil {
		panic(err)
	}

	r := bufio.NewReader(f)

	for {
		s, err := r.ReadString('\n')

		if err == io.EOF {
			fmt.Println(s)
			break
		}

		if err != nil {
			panic(err)
		}

		fmt.Println(s)
	}
}


ioutil.ReadFile - 读取全文

  • ReadFile 内部就是用 ReadAll() 实现的
package main

import (
	"fmt"
	"io/ioutil"
)

func main() {
	// ReadFile 方法内部实现了, 打开文件和 defer 关闭
	content, err := ioutil.ReadFile("a.txt")

	if err != nil {
		panic(err)
	}

	fmt.Println(string(content))
}


写文件

WriteString() 和 Write()

  • WriteString 的参数是 string
  • Write 的参数是 []byte(string)
package main

import "os"

func myWrite1(content string) {
	// 不是新建的情况下, 可以把文件权限写为 0
	f, err := os.OpenFile("a.txt", os.O_WRONLY|os.O_APPEND, 0)

	defer f.Close()

	if err != nil {
		panic(err)
	}

	f.WriteString(content)
}

func myWrite2(b []byte) {
	f, err := os.OpenFile("a.txt", os.O_WRONLY|os.O_APPEND, 0)

	defer f.Close()

	if err != nil {
		panic(err)
	}

	f.Write(b)
}

func main() {
	myWrite1("myWrite1\n")
	myWrite2([]byte("myWrite2\n"))
}


bufio.NewWriter

package main

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

func myWrite3(s string) {
	f, err := os.OpenFile("a.txt", os.O_WRONLY|os.O_APPEND, 0)

	defer f.Close()

	if err != nil {
		fmt.Println(err)
		return
	}

	w := bufio.NewWriter(f)

	// 先记录, 相当于写入缓存
	w.WriteString(s)
	
	// 从缓存写入
	w.Flush()
}

func myWrite4(b byte) {
	f, err := os.OpenFile("a.txt", os.O_WRONLY|os.O_APPEND, 0)

	defer f.Close()

	if err != nil {
		fmt.Println(err)
		return
	}

	w := bufio.NewWriter(f)

	// 先记录, 相当于写入缓存
	w.Write(b)
	
	// 从缓存写入
	w.Flush()
}

func main() {
	myWrite3("myWrite3\n")
	myWrite4('\n')
}


ioutil.WriteFile

  • 新建/覆盖一个文件的内容
  • WriteFile 内部使用的参数是 os.O_WRONLY|os.O_CREATE|os.O_TRUNC
package main

import (
	"fmt"
	"io/ioutil"
)

func main() {
	s := "myWrite5"

	// 参数: 文件名, 要写入的字符串, 文件的权限
	err := ioutil.WriteFile("a.txt", []byte(s), 0644)

	if err != nil {
		panic(err)
	}
}


练习

copyFile

package main

import (
	"io"
	"os"
)

func main() {
	// 打开原文件
	f1, err := os.Open("b.txt")

	defer f1.Close()

	if err != nil {
		panic(err)
	}

	// 打开新文件
	f2, err := os.OpenFile("a.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)

	defer f2.Close()

	if err != nil {
		panic(err)
	}

	// 读取原文件
	x := make([]byte, 10)

	for {
		n, err := f1.Read(x)

		if err == io.EOF {
			break
		}

		if err != nil {
			panic(err)
		}

		// 按字符写入新文件
		f2.Write(x[:n])
	}
}


实现cat命令

package main

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

// cat命令实现
func cat(r *bufio.Reader) {
	for {
		buf, err := r.ReadBytes('\n') //注意是字符
		if err == io.EOF {
			break
		}
		fmt.Fprintf(os.Stdout, "%s", buf)
	}
}

func main() {
	flag.Parse() // 解析命令行参数
	if flag.NArg() == 0 {
		// 如果没有参数默认从标准输入读取内容
		cat(bufio.NewReader(os.Stdin))
	}
	// 依次读取每个指定文件的内容并打印到终端
	for i := 0; i < flag.NArg(); i++ {
		f, err := os.Open(flag.Arg(i))
		if err != nil {
			fmt.Fprintf(os.Stdout, "reading from %s failed, err:%v\n", flag.Arg(i), err)
			continue
		}
		cat(bufio.NewReader(f))
	}
}


读取大文件

package main

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"

	"github.com/axgle/mahonia"
)

// 处理异常
func checkErr(err error, pos string) {
	if err != nil {
		fmt.Printf("err: %v, pos: %v\n", err, pos)
	}
}

// ConverEncoding 处理编码
// srcStr 待处理的数据
// encoding 目前的编码
// go get github.com/axgle/mahonia
func ConverEncoding(srcStr, encoding string) string {
	// 创建编码处理器
	enc := mahonia.NewDecoder(encoding)
	// 调用编码处理器的方法进行转码
	utfStr := enc.ConvertString(srcStr)
	return utfStr
}

// 方式一: 读取全文, 占用内存可能过大
func readData1() {
	contentBytes, err := ioutil.ReadFile("数据/kaifang.txt")
	checkErr(err, "readData1.ioutil.ReadFile")

	contentStr := string(contentBytes)
	lineStrs := strings.Split(contentStr, "\n\r")
	for _, lineStr := range lineStrs {
		r := ConverEncoding(lineStr, "GBK")
		fmt.Println(r)
	}
}

// 方式二: 缓冲区读取文件
func readData2() {
	f, err := os.Open("数据/kaifang.txt")
	checkErr(err, "readData2.Open")
	defer f.Close()

	r := bufio.NewReader(f)

	for {
		lineBytes, _, err := r.ReadLine()

		if err == io.EOF {
			break
		}

		checkErr(err, "readData2.ReadLine")

		lineStr := string(lineBytes)
		r := ConverEncoding(lineStr, "GBK")

		fmt.Println(r)
	}
}

func main() {
	// readData1() // 会卡住
	readData2()
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值