Go语言中的文件处理,重点在于文件而非目录或者通用的文件系统,特别是如何读写标准格式(如 XML 和 JSON 格式)的文件以及自定义的纯文本和二进制格式文件。
Go语言的所有特性,现在我们可以灵活地使用 Go语言提供的所有工具。我们会充分利用这种灵活性并利用闭包来避免重复性的代码,同时在某些情况下充分利用 Go语言对面向对象的支持,特别是对为函数添加方法的支持。
看下面的例子,通过open打开一个文件,默认打开的文件是指针,我们需要通过读取打开文件的内容,才可以看到文件中具体是什么。
package main
import (
"fmt"
"os"
)
func main() {
//fmt.Println(os.Getwd()) //查看当我文件路径
path := "golang-learn/README.md"
content , err := os.Open(path)
if err != nil { //判断文件是否存在,如果不存在返回错误信息
fmt.Println("文件错误",err)
}
fmt.Println("www.wulaoer.org",content)
}
打印结果
www.wulaoer.org &{0xc000064180}
下面使用NewReader函数读取文件内容,如果文件内容比较多,就需要循环读取,直到文件文件读取完,结束,不过默认NewReader函数每次读取的缓存是4096,如果缓存过大会影响服务的整体性能。
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
//fmt.Println(os.Getwd())
path := "golang-learn/README.md"
file, err := os.Open(path)
if err != nil {
fmt.Printf("文件错误")
}
defer file.Close() //打开文件后一定要记得关闭
read := bufio.NewReader(file) // 如果文件内容比较大可以循环读取,默认换成为4096
for {
str,err := read.ReadString('\n') //读到换行就结束,如果读取的文件中含有换行就不能完整读取了。
//str = strings.TrimSpace(str)//如果文件中有换行,就需要再判断之前打印即可,这样就能读取整个文件内容
//fmt.Println(str)
if err == io.EOF {
break //结束退出
}
fmt.Print(str)
}
}
打印结果
# golang-learn 记录学习golang的知识点 可以看看www.wulaoer.org
这里需要注意,如果文件中有空行,在使用ReadString('\n') 的时候就会在读取到空行的时候结束文件,其实在这个空行后还是有文件内容的,所以在这个时候不能判断文件是否结尾。如果文件比较小,可以使用ioutil读取,ioutil和open的区别是ioutil返回的是byte,需要进行转换一下方可。
package main
import (
"fmt"
"io/ioutil"
)
func main() {
//fmt.Println(os.Getwd())
path := "golang-learn/README.md"
content, err := ioutil.ReadFile(path) //ioutil.ReadFile中已经封存了Open和Close,所以不需要Close文件
if err != nil {
fmt.Println("文件错误",err)
}
//fmt.Printf("%v",content)
fmt.Printf(string(content))//读取的内容是[]byte类型,所以需要string转换一下
}
打印结果
# golang-learn 记录学习golang的知识点 可以看看www.wulaoer.org
golang写入操作
写操作需要先拥有文件的读写权限,可以给文件定义权限,然后打开文件,在再文件中进行写入操作,写入操作又以下四种,第一种是在文件底部追加,第二种是覆盖现有文件内容,第三种是在文件制定位置插入,第四种是对没有的文件进行创建并写入操作,下面针对以上四种情况分别举例说明:
第一种在文件底部进行追加写入,这时我们需要用到文件的读写权限,或者文件的写权限,在golang中文件的读写模式用到O_RDWR,写模式是O_APPEND,
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
//fmt.Println(os.Getwd())
path := "golang-learn/README.md"
content, err := os.OpenFile(path,os.O_RDWR | os.O_APPEND, 0655)
if err != nil {
fmt.Println("文件错误",err)
return
}
defer content.Close()
str := "hello golang www.wulaoer.org \r\n"
write := bufio.NewWriter(content)
//for i := 0; i < 5; i++ {
// write.WriteString(str)
//}
write.WriteString(str)
write.Flush()//刷新缓存写入到文件中
con, err := os.Open(path)
defer con.Close()
reader := bufio.NewReader(con)
for {
strs,err := reader.ReadString('\n')
if err == io.EOF {
break
}
fmt.Print(strs)
}
}
在OpenFile中path是路径,后面跟的是打开模式,最后就是操作,最后的0655是定义的文件的权限,在文件操作中golang有以下几种操作方式:
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.为同步I/O打开。 O_TRUNC int = syscall.O_TRUNC // truncate regular writable file when opened.打开时截断常规可写文件 )
前面三种模式在操作文件时必须使用其中的一种,后面五种是对文件操作的控制行文,上面的例子中使用到了文件的追加,追加只能在文件结尾追加。那么覆盖文件就需要把原文件内容清理,然后在写入新的内容,这样就相当于覆盖了,看下面的例子:
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
//fmt.Println(os.Getwd())
path := "golang-learn/index4.html"
content, err := os.OpenFile(path,os.O_WRONLY | os.O_TRUNC, 0655)
//content, err := os.OpenFile(path,os.O_RDWR | os.O_TRUNC | os.O_CREATE, 0655)//两者都有覆盖的意思
if err != nil {
fmt.Println("文件错误",err)
return
}
defer content.Close()
str := "hello golang www.wulaoer.org \r\n"
write := bufio.NewWriter(content)
write.WriteString(str)
write.Flush()//刷新缓存写入到文件中
}
两者写意思相同,只是在打开模式不一样,不用区别对待,文件的操作一定要给予一定的权限,后面权限的四位中的三位655分别代表用户权限,组权限,其他权限,在写入时必须有写入权限。但是如果需要在文件的指定位置写入,又该如何写入呢?看下面的代码?
package main
import (
"fmt"
"io"
"os"
)
func main() {
//fmt.Println(os.Getwd())
path := "golang-learn/index.html"
srcfile,err := os.OpenFile(path,os.O_RDWR,0644)
if err != nil {
fmt.Println("open file filed %v",err)
return
}
tmpfile,err := os.OpenFile("./123.tmp",os.O_CREATE | os.O_WRONLY | os.O_TRUNC,0644)
if err != nil {
fmt.Printf("open file filed %v",err)
return
}
var b [10]byte //定义文件的需要插入的定位符
n,err := srcfile.Read(b[:])
if err != nil {
fmt.Printf("read file failed,err:%v\n",err)
return
}
tmpfile.Write(b[:n])
tmpfile.WriteString("www.wulaoer.org")
var x [1024]byte //这里的定义是每次读取数据的大小
for {
n,err := srcfile.Read(x[:])
if err == io.EOF {
tmpfile.Write(x[:n])
break
}
if err != nil {
fmt.Printf("read from file failed,err:%v\n",err)
return
}
tmpfile.Write(x[:n])
}
tmpfile.Close()
srcfile.Close()
ok := os.Rename("./123.tmp",path)//把临时文件名修改成原文件名
if ok == nil {
fmt.Printf(" sucnss")
} else {
fmt.Printf("error")
}
}
这里使用的占位符的方式插入,如果插入的文件比较大,在插入时就需要计算一下占位符的问题,这个这里就先不叙述了,后期有时间会对这个问题单独一篇文章说明,下面看第四个问题如果对于不存在的文件如何写入呢?需要直接创建,然后在写入,如下:
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
//fmt.Println(os.Getwd())
path := "golang-learn/index4.html"
content, err := os.OpenFile(path,os.O_WRONLY | os.O_CREATE | os.O_EXCL, 0655) //创建新文件并插入内容
if err != nil {
fmt.Println("文件错误",err)
return
}
defer content.Close()
str := "hello golang www.wulaoer.org \r\n"
write := bufio.NewWriter(content)
write.WriteString(str)
write.Flush()//刷新缓存写入到文件中
}

您可以选择一种方式赞助本站
支付宝扫一扫赞助
微信钱包扫描赞助
赏