文件
简介
在golang中,os包下有File的结构体,封装这对文件的操作。
文件操作常用方法
打开和关闭
案例演示:
package main
import (
"fmt"
"io"
"os"
)
func main(){
// 打开文件
file, err := os.Open("d:/test.txt")
if err != nil {
panic(err)
}
fmt.Println("打开文件")
//按字节读取
bs := make([] byte,3)
for {
_, err = file.Read(bs)
if err == io.EOF { break}
fmt.Print(string(bs))
}
//关闭文件
errclose := file.Close()
if errclose != nil {
panic(errclose)
}
fmt.Println()
fmt.Println("关闭文件")
}
test.txt内容如下
hello world 你好小明
内容读取
常见的读取内容有以下三种方式
package main
import (
"bufio"
"fmt"
"io"
"io/ioutil"
"os"
)
func main() {
//1、一次性读取文件内容,还有一个 ReadAll的函数,也能读取
// ReadFile将文件打开和关闭封装在一起,所以最后不用手动关闭
data, err := ioutil.ReadFile("./util/file.go")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(data))
//2、bufio包下缓冲区的读取
file, err := os.Open("d:/test.txt") //打开
if err != nil { fmt.Println(err); return }
defer file.Close() //关闭
line := bufio.NewReader(file)
for {
content, _, err := line.ReadLine()
if err == io.EOF { break }
fmt.Println(string(content))
}
//3、按照字节数读取
file,err= os.Open("./util/file.go")
if err!=nil{ fmt.Println(err); return }
defer file.Close()
//读取数据
bs := make([] byte,4)
for {
_, err = file.Read(bs)
if err == io.EOF { break}
fmt.Print(string(bs))
}
}
文件内容有中文,第三种按字节读取会有问题,推荐使用第二种,带缓冲区的读取。
将test.txt内容修改如下
hello world
你好
小明
案例演示
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
// 打开文件
file, err := os.Open("d:/test.txt")
if err != nil {
panic(err)
}
defer file.Close()
// 缓冲区默认4096字节
reader := bufio.NewReader(file)
for {
content, _, err := reader.ReadLine()
if err == io.EOF { break }//文件末尾
fmt.Println(string(content))
}
}
使用ReadString读取
// 打开文件
file, err := os.Open("d:/test.txt")
if err != nil {
panic(err)
}
defer file.Close()
// 缓冲区默认4096字节
reader := bufio.NewReader(file)
for {
readString, err := reader.ReadString('\n')
if err == io.EOF { break }//文件末尾
fmt.Println(readString)
}
注意: 如果发现输出的内容少了最后一行,那是因为最后一行少了换行符,只要回车加一空行就行。
也可以使用如下方法避免少一行的问题
改进方法一
// 打开文件
file, err := os.Open("d:/test.txt")
if err != nil {
panic(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
文件写入
简单写入
文件写入涉及到的方法有os.OpenFile以及io.WriteString
其中文件模式
const (
O_RDONLY int = syscall.O_RDONLY // 只读模式打开文件
O_WRONLY int = syscall.O_WRONLY // 只写模式打开文件
O_RDWR int = syscall.O_RDWR // 读写模式打开文件
O_APPEND int = syscall.O_APPEND // 写操作时将数据附加到文件尾部
O_CREATE int = syscall.O_CREAT // 如果不存在将创建一个新文件
O_EXCL int = syscall.O_EXCL // 和O_CREATE配合使用,文件必须不存在
O_SYNC int = syscall.O_SYNC // 打开文件用于同步I/O
O_TRUNC int = syscall.O_TRUNC // 如果可能,打开时清空文件
)
FileMode如下图
FileMode只在Linux和UNIX系统下有效,,windows下无效。
在bufio包下有带缓冲区写入的方法(推荐使用)
案例一: 创建新文件,并写入"hello 小明"
filePath := "d:/w1.txt"
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
panic(err)
}
defer file.Close()
str := "hello 小明"
writer := bufio.NewWriter(file)
writer.WriteString(str)
// writer先写入到缓存,最后需要刷新缓存到文件
writer.Flush()
案例二: 打开一个存在的文件,覆盖里面的内容,写入5句 “hello world”
filePath := "d:/w1.txt"
//os.O_WRONLY 写模式,os.O_TRUNC打开会清空文件
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_TRUNC, 0666)
if err != nil {
panic(err)
}
defer file.Close()
str := "hello world\r\n"
writer := bufio.NewWriter(file)
for i := 0; i < 5; i++{
writer.WriteString(str)
}
// writer先写入到缓存,最后需要刷新缓存到文件
writer.Flush()
案例三: 打开一个文件,在原文件基础上追加内容 “星期一”
filePath := "d:/w1.txt"
file, err := os.OpenFile(filePath, os.O_WRONLY | os.O_APPEND, 0666)
if err != nil {
panic(err)
}
defer file.Close()
str := "星期一"
writer := bufio.NewWriter(file)
writer.WriteString(str)
// writer先写入到缓存,最后需要刷新缓存到文件
writer.Flush()
案例四: 打开一个文件,将原文件内容输出到终端,并追加5句"北京 北京"
filePath := "d:/w1.txt"
//os.O_RDWR 读写模式,os.O_APPEND 追加内容
file, err := os.OpenFile(filePath, os.O_RDWR|os.O_APPEND, 0666)
if err != nil {
panic(err)
}
defer file.Close()
//先读取原内容,显示在终端
/* 此方法,可能会造成最后一行显示不出
reader := bufio.NewReader(file)
for{
str, err := reader.ReadString('\n')
if err == io.EOF {
break;
}
fmt.Print(str)
}*/
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
str := "北京 北京\r\n"
writer := bufio.NewWriter(file)
for i := 0; i < 5; i++{
writer.WriteString(str)
}
// writer先写入到缓存,最后需要刷新缓存到文件
writer.Flush()
案例五: 将A文件内容写入到B文件
fileSource := "d:/sour.txt"
fileDest := "d:/dest.txt"
//读取原文件
data, err := ioutil.ReadFile(fileSource)
if err != nil {
panic(err)
}
//写入内容
errWrite := ioutil.WriteFile(fileDest, data, 0666)
if errWrite != nil {
panic(errWrite)
}
注意: 在写入之前会 清空B文件内容
判断文件/文件夹是否存在
golang判断文件或文件夹是否存在的方法为使用os.Stat()
1)如果返回的错误为nil说明文件或文件夹存在
2)如果返回的错误类型使用 os. IsNotExist()判断为true,说明文件或文件夹不存在
3)如果返回的错误为其它类型,则不确定是否存在
由以上三点写一个方法判断
func PathExists(path string) (bool,error){
_, err := os.Stat(path)
if err == nil {//文件存在
return true,nil
}
if os.IsNotExist(err){//文件不存在
return false,nil
}
return false,err
}
使用
path := "d:/"
exists, err := PathExists(path)
if err == nil {
if exists {
fmt.Println("文件存在")
} else {
fmt.Println("文件不存在")
}
}else{
fmt.Println(err)
}
资源拷贝
案例: 将 D盘下 “壁纸.jpg” 拷贝到E盘图片文件下
用到 io包下的copy方法
package main
import (
"bufio"
"io"
"os"
)
func main() {
//将 d:/壁纸.jpg 拷贝到 e:/图片/abc.jpg
destFileName := "e:/图片/abc.jpg"
srcFileName := "d:/壁纸.jpg"
CopyFile(destFileName,srcFileName)
}
/**
* 文件拷贝的方法,将srcFileName拷贝到destFileName
*/
func CopyFile(destFileName string,srcFileName string)(writtern int64,err error){
// 打开原文件
srcFile, err := os.Open(srcFileName)
if err != nil {
panic(err)
}
defer srcFile.Close()
// 构建Reader
reader := bufio.NewReader(srcFile)
//打开目的文件
destFile, err := os.OpenFile(destFileName, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
panic(err)
}
defer destFile.Close()
writer := bufio.NewWriter(destFile)
written, err := io.Copy(writer, reader)
writer.Flush()
return written, err
}