文件的读写是编程语言的常见操作之一,这里讲一些Goang 读取文件的相关操作。
读取文件
读取文件有三种方式:
- 将文件整个读入内存
- 按字节数读取
- 按行读取
具体实现如下:
1、将文件整个读入内存
package main
import (
"os"
"io/ioutil"
"fmt"
)
func main() {
file, err := os.Open("D:/gopath/src/golang_development_notes/example/log.txt")
if err != nil {
panic(err)
}
defer file.Close()
content, err := ioutil.ReadAll(file)
fmt.Println(string(content))
}
或者
package main
import (
"os"
"io/ioutil"
"fmt"
)
func main() {
filepath := "D:/gopath/src/golang_development_notes/example/log.txt"
content ,err :=ioutil.ReadFile(filepath)
if err !=nil {
panic(err)
}
fmt.Println(string(content))
}
将文件整个读入内存,效率比较高,占用内存也最高。
2、按字节读取文件
package main
import (
"bufio"
"fmt"
"io"
"io/ioutil"
"os"
)
func main() {
filepath := "D:/gopath/src/golang_development_notes/example/log.txt"
fi, err := os.Open(filepath)
if err != nil {
panic(err)
}
defer fi.Close()
r := bufio.NewReader(fi)
chunks := make([]byte, 0)
buf := make([]byte, 1024) //一次读取多少个字节
for {
n, err := r.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
fmt.Println(string(buf[:n]))
break
if 0 == n {
break
}
chunks = append(chunks, buf[:n]...)
}
fmt.Println(string(chunks))
}
或
package main
import (
"fmt"
"io"
"os"
)
func main() {
file := "D:/gopath/src/golang_development_notes/example/log.txt"
f, err := os.Open(file)
if err != nil {
panic(err)
}
defer f.Close()
chunks := make([]byte, 0)
buf := make([]byte, 1024)
for {
n, err := f.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
if 0 == n {
break
}
chunks = append(chunks, buf[:n]...)
}
fmt.Println(string(chunks))
}
3、按行读取
<pre class="hljs language-stata">package main
import (
<span class="hljs-string">"bufio"</span>
<span class="hljs-string">"fmt"</span>
<span class="hljs-string">"io"</span>
<span class="hljs-string">"io/ioutil"</span>
<span class="hljs-string">"os"</span>
<span class="hljs-string">"strings"</span>
)
func main() {
filepath := <span class="hljs-string">"D:/gopath/src/golang_development_notes/example/log.txt"</span>
<span class="hljs-keyword">file</span>, <span class="hljs-keyword">err</span> := os.OpenFile(filepath, os.O_RDWR, 0666)
<span class="hljs-keyword">if</span> <span class="hljs-keyword">err</span> != nil {
fmt.Println(<span class="hljs-string">"Open file error!"</span>, <span class="hljs-keyword">err</span>)
<span class="hljs-keyword">return</span>
}
defer <span class="hljs-keyword">file</span>.<span class="hljs-keyword">Close</span>()
stat, <span class="hljs-keyword">err</span> := <span class="hljs-keyword">file</span>.Stat()
<span class="hljs-keyword">if</span> <span class="hljs-keyword">err</span> != nil {
panic(<span class="hljs-keyword">err</span>)
}
<span class="hljs-keyword">var</span> size = stat.Size()
fmt.Println(<span class="hljs-string">"file size="</span>, size)
buf := bufio.NewReader(<span class="hljs-keyword">file</span>)
<span class="hljs-keyword">for</span> {
<span class="hljs-keyword">line</span>, <span class="hljs-keyword">err</span> := buf.ReadString('\<span class="hljs-keyword">n</span>')
<span class="hljs-keyword">line</span> = strings.TrimSpace(<span class="hljs-keyword">line</span>)
fmt.Println(<span class="hljs-keyword">line</span>)
<span class="hljs-keyword">if</span> <span class="hljs-keyword">err</span> != nil {
<span class="hljs-keyword">if</span> <span class="hljs-keyword">err</span> == io.EOF {
fmt.Println(<span class="hljs-string">"File read ok!"</span>)
<span class="hljs-keyword">break</span>
} <span class="hljs-keyword">else</span> {
fmt.Println(<span class="hljs-string">"Read file error!"</span>, <span class="hljs-keyword">err</span>)
<span class="hljs-keyword">return</span>
}
}
}
}</pre>
写入文件
有以下写入方式
1、ioutil.WriteFile
package main
import (
"io/ioutil"
)
func main() {
content := []byte("测试1\n测试2\n")
err := ioutil.WriteFile("test.txt", content, 0644)
if err != nil {
panic(err)
}
}
这种方式每次都会覆盖 test.txt内容,如果test.txt文件不存在会创建。
2、os
package main
import (
"fmt"
"io"
"os"
)
func checkFileIsExist(filename string) bool {
if _, err := os.Stat(filename); os.IsNotExist(err) {
return false
}
return true
}
func main() {
var wireteString = "测试1\n测试2\n"
var filename = "./test.txt"
var f *os.File
var err1 error
if checkFileIsExist(filename) { //如果文件存在
f, err1 = os.OpenFile(filename, os.O_APPEND, 0666) //打开文件
fmt.Println("文件存在")
} else {
f, err1 = os.Create(filename) //创建文件
fmt.Println("文件不存在")
}
defer f.Close()
n, err1 := io.WriteString(f, wireteString) //写入文件(字符串)
if err1 != nil {
panic(err1)
}
fmt.Printf("写入 %d 个字节n", n)
}
此种方法可以在文件内容末尾添加新内容。
3、
package main
import (
"fmt"
"os"
)
func checkFileIsExist(filename string) bool {
if _, err := os.Stat(filename); os.IsNotExist(err) {
return false
}
return true
}
func main() {
var str = "测试1\n测试2\n"
var filename = "./test.txt"
var f *os.File
var err1 error
if checkFileIsExist(filename) { //如果文件存在
f, err1 = os.OpenFile(filename, os.O_APPEND, 0666) //打开文件
fmt.Println("文件存在")
} else {
f, err1 = os.Create(filename) //创建文件
fmt.Println("文件不存在")
}
defer f.Close()
n, err1 := f.Write([]byte(str)) //写入文件(字节数组)
fmt.Printf("写入 %d 个字节n", n)
n, err1 = f.WriteString(str) //写入文件(字符串)
if err1 != nil {
panic(err1)
}
fmt.Printf("写入 %d 个字节n", n)
f.Sync()
}
此种方法可以在文件内容末尾添加新内容。
4、bufio
package main
import (
"bufio"
"fmt"
"os"
)
func checkFileIsExist(filename string) bool {
if _, err := os.Stat(filename); os.IsNotExist(err) {
return false
}
return true
}
func main() {
var str = "测试1\n测试2\n"
var filename = "./test.txt"
var f *os.File
var err1 error
if checkFileIsExist(filename) { //如果文件存在
f, err1 = os.OpenFile(filename, os.O_APPEND, 0666) //打开文件
fmt.Println("文件存在")
} else {
f, err1 = os.Create(filename) //创建文件
fmt.Println("文件不存在")
}
defer f.Close()
if err1 != nil {
panic(err1)
}
w := bufio.NewWriter(f) //创建新的 Writer 对象
n, _ := w.WriteString(str)
fmt.Printf("写入 %d 个字节n", n)
w.Flush()
}
此种方法可以在文件内容末尾添加新内容。
对比几种读取文件效率
package main
import (
"bufio"
"fmt"
"io"
"io/ioutil"
"os"
"time"
)
func read0(path string) string {
file, err := os.Open(path)
if err != nil {
panic(err)
}
defer file.Close()
content, err := ioutil.ReadAll(file)
return string(content)
}
func read1(path string) string {
content, err := ioutil.ReadFile(path)
if err != nil {
panic(err)
}
return string(content)
}
func read2(path string) string {
fi, err := os.Open(path)
if err != nil {
panic(err)
}
defer fi.Close()
r := bufio.NewReader(fi)
chunks := make([]byte, 0)
buf := make([]byte, 1024) //一次读取多少个字节
for {
n, err := r.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
if 0 == n {
break
}
chunks = append(chunks, buf[:n]...)
}
return string(chunks)
}
func read3(path string) string {
fi, err := os.Open(path)
if err != nil {
panic(err)
}
defer fi.Close()
chunks := make([]byte, 0)
buf := make([]byte, 1024)
for {
n, err := fi.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
if 0 == n {
break
}
chunks = append(chunks, buf[:n]...)
}
return string(chunks)
}
func main() {
file := "D:/gopath/src/example/example/log.txt"
start := time.Now()
read0(file)
t0 := time.Now()
fmt.Printf("Cost time %v\n", t0.Sub(start))
read1(file)
t1 := time.Now()
fmt.Printf("Cost time %v\n", t1.Sub(t0))
read2(file)
t2 := time.Now()
fmt.Printf("Cost time %v\n", t2.Sub(t1))
read3(file)
t3 := time.Now()
fmt.Printf("Cost time %v\n", t3.Sub(t2))
}