ReadString('\n')
或者ReadBytes('\n')
打开文件和关闭文件
func Open(name string) (file * File, err error)
以O_RDONLY只读模式打开文件
func ( * File)Close() error
关闭文件
读文件
读取文件内容并显示在终端(带缓冲区的方式)
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
file, err := os.Open("C:\\Users\\zhouzy1\\Desktop\\my_study_notes\\go学习\\代码\\study_go\\day1\\abc.txt")
if err != nil {
fmt.Println("打开文件错误:",err)
}
// 打开文件一定记得最后关闭
defer file.Close()
// 默认缓冲区大小为4096
reader := bufio.NewReader(file)
for {
str, err := reader.ReadString('\n')
fmt.Print(str)
if err == io.EOF {
// 文件结束符为EOF
break
}
}
}
一次性读取文件所有内容至缓冲区中,适用于文件不大的情况:
package main
import (
"fmt"
"io/ioutil"
)
func main() {
file := "C:\\Users\\zhouzy1\\Desktop\\my_study_notes\\go学习\\代码\\study_go\\day1\\abc.txt"
content, err := ioutil.ReadFile(file)
if err != nil {
fmt.Printf("read file err=%v", err)
}
fmt.Printf("%v", string(content))
}
按行读取文件
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
path := "C:\\Users\\zhouzy1\\Desktop\\my_study_notes\\go学习\\代码\\study_go\\day1\\abc.txt"
f, err := os.Open(path)
if err != nil {
fmt.Println("err = ", err)
return
}
defer f.Close()
r := bufio.NewReader(f)
for {
buf, err := r.ReadBytes('\n')
if err != nil {
if err == io.EOF {
break
}
fmt.Println("err = ", err)
}
fmt.Printf("buf = #%s#\n", string(buf))
}
}
写文件
os.OpenFile(name string, flag int, perm FileMode) (file * File, err error)
以指定模式,指定权限打开文件
打开或者创建文件并写入内容
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
filePath := "a.txt"
file, err := os.OpenFile(filePath, os.O_WRONLY | os.O_CREATE, 0666)
if err != nil {
fmt.Printf("open file err=%v\n", err)
return
}
defer file.Close()
str := "hello go!"
writer := bufio.NewWriter(file)
for i := 0; i < 5; i++ {
writer.WriteString(str)
}
// 使用的缓冲区写入,flush后才会将缓冲区的内容写入文件
writer.Flush()
}
打开文件,写入并覆盖原有内容
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
filePath := "a.txt"
file, err := os.OpenFile(filePath, os.O_WRONLY | os.O_TRUNC, 0666)
if err != nil {
fmt.Printf("open file err=%v\n", err)
return
}
defer file.Close()
str := "覆盖原有内容!"
writer := bufio.NewWriter(file)
for i := 0; i < 5; i++ {
writer.WriteString(str)
}
// 使用的缓冲区写入,flush后才会将缓冲区的内容写入文件
writer.Flush()
}
打开文件,追加内容
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
filePath := "a.txt"
file, err := os.OpenFile(filePath, os.O_WRONLY | os.O_APPEND, 0666)
if err != nil {
fmt.Printf("open file err=%v\n", err)
return
}
defer file.Close()
str := "追加内容!\r\n"
writer := bufio.NewWriter(file)
for i := 0; i < 5; i++ {
writer.WriteString(str)
}
// 使用的缓冲区写入,flush后才会将缓冲区的内容写入文件
writer.Flush()
}
打开文件,读取文件内容,并追加内容
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
filePath := "a.txt"
file, err := os.OpenFile(filePath, os.O_RDWR | os.O_APPEND, 0666)
if err != nil {
fmt.Printf("open file err=%v\n", err)
return
}
defer file.Close()
reader := bufio.NewReader(file)
for {
str, err := reader.ReadString('\n')
if err == io.EOF {
break
}
fmt.Print(str)
}
str := "追加内容!\r\n"
writer := bufio.NewWriter(file)
for i := 0; i < 5; i++ {
writer.WriteString(str)
}
// 使用的缓冲区写入,flush后才会将缓冲区的内容写入文件
writer.Flush()
}
读取一个文件的内容写入另一个文件
package main
import (
"fmt"
"io/ioutil"
)
func main() {
file1Path := "a.txt"
file2Path := "b.txt"
data, err := ioutil.ReadFile(file1Path)
if err != nil {
fmt.Printf("read file err = %v\n", err)
return
}
err = ioutil.WriteFile(file2Path, data, 0666)
if err != nil {
fmt.Printf("write file error = %v\n", err)
}
}
package main
import (
"fmt"
"os"
)
func main() {
file1Path := "a.txt"
file2Path := "not_exit_file.txt"
fileInfo, err := os.Stat(file1Path)
_, err2 := os.Stat(file2Path)
// 如果err 为nil 说明文件一定存在
if err == nil {
fmt.Println("文件存在")
}
fmt.Printf("%T\n", fileInfo)
// 文件名
fmt.Println(fileInfo.Name())
// 文件大小
fmt.Println(fileInfo.Size())
// 是否是目录
fmt.Println(fileInfo.IsDir())
// 修改时间
fmt.Println(fileInfo.ModTime())
// 如果err 不为nil 需要通过os.IsNotExist判断错误类型为不存在
// 否则可能为别的错误类型
if os.IsNotExist(err2) {
fmt.Println("文件不存在2")
}
}
os.Args
存储所有的命令行参数package main
import (
"flag"
"fmt"
)
func main() {
var user string
var pwd string
var host string
var port int
flag.StringVar(&user, "u", "", "用户名默认为空")
flag.StringVar(&pwd, "p", "", "密码默认为空")
flag.StringVar(&host, "h", "localhost", "主机名默认为localhost")
flag.IntVar(&port, "port", 3306, "端口默认为3306")
flag.Parse()
fmt.Printf("user=%v pwd=%v host=%v port=%v",
user, pwd, host, port)
}
package main
import (
"fmt"
"io"
"os"
)
func main() {
/**
seek(offset, whence), 设置指针光标的位置
第一个参数:偏移量
第二个参数:如何设置
0: seekStart 表示相对于文件开始
1: seekCurrent 表示相对于当前偏移量
2: seek end 表示相对于结束
const (
SeekStart = 0
SeekCurrent = 1
SeekEnd = 2
)
随机读取文件:
可以设置指针光标的位置
*/
file, _ := os.OpenFile("a.txt", os.O_RDWR, 0)
defer file.Close()
bs := []byte{
0, 1}
file.Read(bs)
fmt.Println(string(bs))
file.Seek(4, io.SeekStart)
file.Read(bs)
fmt.Println(string(bs))
file.Seek(2, 0)
file.Read(bs)
fmt.Println(string(bs))
file.Seek(3, io.SeekCurrent)
file.Read(bs)
fmt.Println(string(bs))
file.Seek(0, io.SeekEnd)
file.WriteString("ABC")
}
实现断点续传,主要要记录读写文件位置,实现思路:在读写文件的同时,建立一个临时文件用于同步读写数据的位置,当需要断点续传的时候,从临时文件中获取指定位置,然后通过Seek()
方法定位读写位置,继续读写。
package main
import (
"fmt"
"io"
"os"
"strconv"
)
func main() {
/*
断点续传:
复制文件a.png 复制到b.png
*/
srcFile := "a.png"
destFile := "b.png"
tmpFIle := destFile + "tmp.txt"
file1, _ := os.Open(srcFile)
file2, _ := os.OpenFile(destFile, os.O_CREATE | os.O_WRONLY, os.ModePerm)
file3, _ := os.OpenFile(tmpFIle, os.O_CREATE | os.O_RDWR, os.ModePerm)
defer file1.Close()
defer file2.Close()
// 1. 读取临时文件中的数据,根据seek
file3.Seek(0, io.SeekStart)
bs := make([]byte, 100, 100)
n1, err := file3.Read(bs)
fmt.Println(n1)
countStr := string(bs[:n1])
fmt.Println(countStr)
count, _ := strconv.ParseInt(countStr, 10, 64)
fmt.Println(count)
// 2. 设置读,写的偏移量
file1.Seek(count, 0)
file2.Seek(count, 0)
data := make([]byte, 1024, 1024)
n2 := -1
n3 := -1
total := int(count)
for {
// 3.读取数据
n2, err = file1.Read(data)
if err == io.EOF {
fmt.Println("文件复制完毕")
file3.Close()
os.Remove(tmpFIle)
break
}
// 将数据写入目标文件
n3, _ = file2.Write(data[:n2])
total += n3
// 将复制总量,存储到临时文件中
file3.Seek(0, io.SeekStart)
file3.WriteString(strconv.Itoa(total))
if total > 1024{
panic("异常断开")
}
}
}
写入JSON文件
package main
import (
"encoding/json"
"fmt"
"os"
)
type Website struct {
Name string `xml:"name, attr"`
Url string
Course []string
}
func main() {
info := []Website{
{
"Golang", "http://清华尹成大神/golang/",
[]string{
"http://清华尹成大神/cplus/", "http://清华尹成大神/linux_tutorial/"}},
{
"Java", "http://清华尹成大神/java/",
[]string{
"http://清华尹成大神/socket/", "http://清华尹成大神/python/"}},
}
filePtr, err := os.Create("info.json")
if err != nil {
fmt.Println("err:", err.Error())
return
}
defer filePtr.Close()
encoder := json.NewEncoder(filePtr)
err = encoder.Encode(info)
if err != nil {
fmt.Println("编码错误", err.Error())
}else {
fmt.Println("success")
}
}
读取JSON文件
package main
import (
"encoding/json"
"fmt"
"os"
)
type Website struct {
Name string `xml:"name, attr"`
Url string
Course []string
}
func main() {
filePtr, err := os.Open("info.json")
if err != nil {
fmt.Println("文件打开失败【err:%s】", err.Error())
return
}
defer filePtr.Close()
var info []Website
// 创建json解码器
decoder := json.NewDecoder(filePtr)
err = decoder.Decode(&info)
if err != nil {
fmt.Println("解码失败", err.Error())
} else {
fmt.Println("解码成功")
fmt.Println(info)
}
}
写入xml文件
package main
import (
"encoding/xml"
"fmt"
"os"
)
type Website struct {
Name string `xml:"name, attr"`
Url string
Course []string
}
func main() {
info := Website{
"清华尹成大神网", "http://清华尹成大神/golang/",
[]string{
"Go语言入门教程", "Golang入门教程"}}
f, err := os.Create("info.xml")
if err != nil {
fmt.Println("文件创建失败", err.Error())
return
}
defer f.Close()
// 序列化到文件中
encoder := xml.NewEncoder(f)
err = encoder.Encode(info)
if err != nil {
fmt.Println("编码错误:", err.Error())
return
} else {
fmt.Println("编码成功")
}
}
读XML文件
package main
import (
"encoding/xml"
"fmt"
"os"
)
type Website struct {
Name string `xml:"name, attr"`
Url string
Course []string
}
func main() {
f, err := os.Open("info.xml")
if err != nil {
fmt.Println("文件打开失败", err.Error())
return
}
defer f.Close()
info := Website{
}
// 创建xml解码器
decoder := xml.NewDecoder(f)
err = decoder.Decode(&info)
if err != nil {
fmt.Println("解码错误:", err.Error())
return
} else {
fmt.Println("解码成功")
fmt.Println(info)
}
}
创建gob文件
package main
import (
"encoding/gob"
"fmt"
"os"
)
func main() {
info := map[string]string{
"name": "清华大声",
"website": "badidu.com",
}
name := "demo.gob"
File, _ := os.OpenFile(name, os.O_RDWR|os.O_CREATE,0777)
defer File.Close()
enc := gob.NewEncoder(File)
if err := enc.Encode(info); err != nil {
fmt.Println(err)
}
}
读取gob文件
package main
import (
"encoding/gob"
"fmt"
"os"
)
func main() {
var M map[string]string
File, _ := os.Open("demo.gob")
D := gob.NewDecoder(File)
D.Decode(&M)
fmt.Println(M)
}
写自定义二进制文件
package main
import (
"bytes"
"encoding/binary"
"fmt"
"os"
)
type Website struct {
Url int32
}
func main() {
file, err := os.Create("output.bin")
for i := 1; i <= 10; i++ {
info := Website{
Url: int32(i)}
if err != nil {
fmt.Println("文件创建失败")
return
}
defer file.Close()
var bin_buf bytes.Buffer
binary.Write(&bin_buf, binary.LittleEndian, info)
b := bin_buf.Bytes()
_, err = file.Write(b)
if err != nil {
fmt.Println("编码失败", err.Error())
return
}
}
fmt.Println("编码成功")
}
读二进制文件
package main
import (
"bytes"
"encoding/binary"
"fmt"
"os"
)
type Website struct {
Url int32
}
func main() {
file, err := os.Open("output.bin")
defer file.Close()
if err != nil {
fmt.Println("文件打开失败", err.Error())
return
}
m := Website{
}
for i := 1; i <= 10; i++ {
data := readNextBytes(file, 4)
buffer := bytes.NewBuffer(data)
err = binary.Read(buffer, binary.LittleEndian, &m)
if err != nil {
fmt.Println("二进制文件读取失败", err)
return
}
fmt.Println(i)
}
}
func readNextBytes(file *os.File, number int) []byte {
bytes := make([]byte, number)
_, err := file.Read(bytes)
if err != nil {
fmt.Println("解码失败",err)
}
return bytes
}
创建zip归档文件
package main
import (
"archive/zip"
"bytes"
"fmt"
"os"
)
func main() {
// 使用buffer创建压缩文档
buf := new(bytes.Buffer)
w := zip.NewWriter(buf)
// 将文件加入压缩文档
var files = []struct{
Name, Body string
}{
{
"Golang.txt", "清华大神"},
}
for _, file := range files {
f, err := w.Create(file.Name)
if err != nil {
fmt.Println(err)
}
_, err = f.Write([]byte(file.Body))
if err != nil {
fmt.Println(err)
}
}
// 关闭压缩文档
err := w.Close()
if err != nil {
fmt.Println(err)
}
// 将压缩文档内容写入文件
f, err := os.OpenFile("file.zip", os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
fmt.Println(err)
}
buf.WriteTo(f)
}
读取zip归档文件
package main
import (
"archive/zip"
"fmt"
"io"
"os"
)
func main() {
// 打开一个zip格式文件
r, err := zip.OpenReader("file.zip")
if err != nil {
fmt.Printf(err.Error())
}
defer r.Close()
// 迭代压缩文件中的文件,打印文件中的内容
for _,f := range r.File {
fmt.Printf("文件名:%s\n", f.Name)
rc, err := f.Open()
if err != nil {
fmt.Printf(err.Error())
}
_, err = io.CopyN(os.Stdout, rc, int64(f.UncompressedSize64))
if err != nil {
fmt.Printf(err.Error())
}
rc.Close()
}
}
打包tar文件
package main
import (
"archive/tar"
"fmt"
"io"
"os"
)
func main() {
// 创建tar文件
f, err := os.Create("./output.tar")
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
tw := tar.NewWriter(f)
defer tw.Close()
// 获取文件相关信息
fileInfo, err := os.Stat("./main.go")
if err != nil {
fmt.Println(err)
}
hdr, err := tar.FileInfoHeader(fileInfo, "")
if err != nil {
fmt.Println(err)
}
err = tw.WriteHeader(hdr)
if err != nil {
fmt.Println(err)
}
f1, err := os.Open("./main.go")
if err != nil {
fmt.Println(err)
return
}
m, err := io.Copy(tw, f1)
if err != nil {
fmt.Println(err)
}
fmt.Println(m)
}
解压tar归档文件
package main
import (
"archive/tar"
"fmt"
"io"
"os"
)
func main() {
// 创建tar文件
f, err := os.Create("./output.tar")
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
tw := tar.NewWriter(f)
defer tw.Close()
// 获取文件相关信息
fileInfo, err := os.Stat("./main.go")
if err != nil {
fmt.Println(err)
}
hdr, err := tar.FileInfoHeader(fileInfo, "")
if err != nil {
fmt.Println(err)
}
err = tw.WriteHeader(hdr)
if err != nil {
fmt.Println(err)
}
f1, err := os.Open("./main.go")
if err != nil {
fmt.Println(err)
return
}
m, err := io.Copy(tw, f1)
if err != nil {
fmt.Println(err)
}
fmt.Println(m)
}
使用json tag 指定字段名
type Person struct {
Name string `json:"name"`
Age int64
Weight float64
}
忽略某个字段
type Person struct {
Name string `json:"name"`
Age int64
Weight float64 `json:"-"`
}
忽略空值字段
type Person struct {
Name string `json:"name"`
Age int64 `json:"age,omitempty"`
Weight float64 `json:"-"`
}
忽略嵌套结构体空值字段
type Profile struct {
Website string `json:"website"`
Slogan string `json:"slogan"`
}
type User struct {
Name string `json:"name"`
Email string `json:"email,omitempty"`
*Profile `json:"profile,omitempty"`
}
不修改原结构体忽略空值字段
type User struct {
Name string `json:"name"`
Password string `json:"password"`
}
type PublicUser struct {
*User
Password *struct{
} `json:"password,omitempty"`
}
优雅处理字符串格式的数字
package main
import (
"encoding/json"
"fmt"
)
func main() {
type Card struct {
ID int64 `json:"id,string"`
Score float64 `json:"score,string"`
}
jsonStr := `{"id": "12345", "score": "88.5"}`
var c Card
if err := json.Unmarshal([]byte(jsonStr), &c); err != nil {
fmt.Printf("json.Unmarsha jsonStr failed, err:%v\n", err)
return
}
fmt.Printf("c:%#v\n", c)
}
整数变浮点数
JSON协议没有整型和浮点型之分,统称为number。JSON反序列化后都会转为float64:
package main
import (
"encoding/json"
"fmt"
)
func main() {
var m = make(map[string]interface{
}, 1)
m["count"] = 1
b, err := json.Marshal(m)
if err != nil {
fmt.Printf("marshal failed, err:%v\n", err)
}
fmt.Printf("str:%#v\n", string(b))
var m2 map[string]interface{
}
err = json.Unmarshal(b, &m2)
if err != nil{
fmt.Printf("unmarshal failed, err:%v\n", err)
return
}
fmt.Printf("value:%v\n", m2["count"]) //1
fmt.Printf("type::%T\n", m2["count"]) // float64
}
想要更合理的处理数字需要使用decoder:
package main
import (
"bytes"
"encoding/json"
"fmt"
)
func main() {
var m = make(map[string]interface{
}, 1)
m["count"] = 1
b, err := json.Marshal(m)
if err != nil {
fmt.Printf("marshal failed, err:%v\n", err)
}
fmt.Printf("str:%#v\n", string(b))
var m2 map[string]interface{
}
// 使用decoder方式反序列化,指定使用number类型
decoder := json.NewDecoder(bytes.NewReader(b))
decoder.UseNumber()
err = decoder.Decode(&m2)
if err != nil{
fmt.Printf("unmarshal failed, err:%v\n", err)
return
}
fmt.Printf("value:%v\n", m2["count"])
fmt.Printf("type::%T\n", m2["count"])
// 将m2["count"]转为json.Number之后调用Int64()方法获得int64类型的值
count, err := m2["count"].(json.Number).Int64()
if err != nil {
fmt.Printf("parse to int64 failed, err:%v\n", err)
return
}
fmt.Printf("type:%T\n", int(count)) //int
}
使用匿名结构体添加字段
package main
import (
"encoding/json"
"fmt"
)
func main() {
type UserInfo struct {
ID int `json:"id"`
Name string `json:"name"`
}
u1 := UserInfo{
ID: 12345,
Name: "zzy",
}
// 使用匿名结构体内嵌User并添加额外字段Token
b, err := json.Marshal(struct {
*UserInfo
Token string `json:"token"`
}{
&u1,
"9asd2d35asd",
})
if err != nil {
fmt.Printf("json.Marsha failed, err:%v\n", err)
return
}
fmt.Printf("str:%s\n", b)
// str:{"id":12345,"name":"zzy","token":"9asd2d35asd"}
}
使用匿名结构体组合多个结构体
package main
import (
"encoding/json"
"fmt"
)
func main() {
type Comment struct {
Content string
}
type Image struct {
Title string `json:"title"`
URL string `json:"url"`
}
c1 := Comment {
Content: "永远不要高估自己",
}
i1 := Image{
Title: "赞赏码",
URL: "demo.com",
}
b, err := json.Marshal(struct {
*Comment
*Image
}{
&c1, &i1})
if err != nil {
fmt.Printf("json.Marshal failed, err:%v\n", err)
return
}
fmt.Printf("str:%s\n", b)
// 反序列化
jsonStr := `{"Content":"永远不要高估自己","title":"赞赏码","url":"https://www.liwenzhou.com/images/zanshang_qr.jpg"}`
var (
c2 Comment
i2 Image
)
if err := json.Unmarshal([]byte(jsonStr), &struct {
*Comment
*Image
}{
&c2, &i2});err != nil {
fmt.Printf("json.Unmarshal failed, err:%v\n", err)
return
}
fmt.Printf("c2:%#v i2%$v\n", c2, i2)
}
处理不确定层级的json
package main
import (
"encoding/json"
"fmt"
)
func main() {
type sendMsg struct {
User string `json:"user"`
Msg string `json:"msg"`
}
jsonStr := `{"sendMsg":{"user":"q1mi","msg":"永远不要高估自己"},"say":"Hello"}`
// 定义一个map, value 类型为json.RawMessage, 方便后续更灵活的处理
var data map[string]json.RawMessage
if err := json.Unmarshal([]byte(jsonStr), &data); err != nil {
fmt.Printf("1json.Unmarshal jsonStr failed, err: %v\n",err)
return
}
var msg sendMsg
if err := json.Unmarshal(data["sendMsg"], &msg); err != nil {
fmt.Printf("json.Unmarshal failed, err:%v\n", err)
return
}
fmt.Printf("msg:%#v\n", msg)
}