我们依旧按照前几章节的流程来做
1. 创建文件夹step-5
$ mkdir step-5
2. 创建main.go
$touch main.go
3. 复制源代码到main.go
4. 然后执行
$ go mod init
$ go mod tidy
复制step-3目录下的src_checkLines.txt过来
$ cp ../step-3/src_checkLines.txt .
源代码
如下源代码,完整展示了预期流程。
流程示意图如下
package main
import (
"bufio"
"bytes"
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"gopkg.in/iconv.v1"
"io"
"io/ioutil"
"os"
"strings"
)
type Report struct {
ID uint `gorm:"primary_key"`
CheckLine string `gorm:"column:check_line;type:longtext"`
}
func (rep Report) TableName() string {
return "foo_reports"
}
// 创建新的数据库,名字叫 golang_development,使用utf8编码
// CREATE DATABASE IF NOT EXISTS golang_development default charset utf8 COLLATE utf8_general_ci;
func main() {
const (
conn = "mysql://root:root@tcp(127.0.0.1:13306)/golang_development?autocommit=true&charset=utf8"
)
DBEngine := strings.Replace(conn, "mysql://", "", -1)
db, err := gorm.Open("mysql", DBEngine)
if err != nil {
panic("failed to connect database")
}
defer db.Close()
db.AutoMigrate(&Report{})
db.Exec("delete from " + (Report{}).TableName())
srcCheckLines, _ := ReadLines("./src_checkLines.txt", nil)
for _, checkLine := range srcCheckLines {
utf8Line := toUTF8(checkLine)
db.Create(&Report{
CheckLine: utf8Line,
})
}
var repList []Report
if err := db.Find(&repList).Error; err != nil {
panic(err)
}
dstCheckLines := make([]string, 0, len(repList))
for _, rep := range repList {
fmt.Printf("checkLine: %sn", rep.CheckLine)
dstCheckLines = append(dstCheckLines, rep.CheckLine)
}
var buffer bytes.Buffer
for _, checkLine := range dstCheckLines {
gbkLine := toGBK(checkLine)
buffer.Write([]byte(gbkLine))
buffer.WriteByte(byte(0x0D))
buffer.WriteByte(byte(0x0A))
}
ioutil.WriteFile("./dst-checkLines.txt", buffer.Bytes(), 0644)
}
func toGBK(str string) string {
cd, err := iconv.Open("gbk", "utf-8") // convert utf-8 to gbk
if err != nil {
fmt.Println("iconv.Open failed!")
return ""
}
defer cd.Close()
return cd.ConvString(str)
}
func toUTF8(str string) string {
cd, err := iconv.Open("utf-8", "gbk") // convert utf-8 to gbk
if err != nil {
fmt.Println("iconv.Open failed!")
return ""
}
defer cd.Close()
return cd.ConvString(str)
}
//ReadLinesFilter 文本行过滤器
type ReadLinesFilter func(btline []byte) bool
//ReadLines 从文件中读取文本行列表
//
// 支持错误处理
// 支持自定义文本行过滤器
func ReadLines(path string, filter ReadLinesFilter) (lines []string, err error) {
var (
file *os.File
part []byte
prefix bool
)
if file, err = os.Open(path); err != nil {
return
}
defer file.Close()
reader := bufio.NewReader(file)
//@todo:
buffer := bytes.NewBuffer(make([]byte, 0))
for {
if part, prefix, err = reader.ReadLine(); err != nil {
break
}
buffer.Write(part)
if !prefix {
if filter != nil {
if filter(buffer.Bytes()) {
lines = append(lines, buffer.String())
}
} else {
lines = append(lines, buffer.String())
}
buffer.Reset()
}
}
if err == io.EOF {
err = nil
}
return
}
注意此时step-5
目录下
- GBK编码源文件
src_checkLines.txt
- GBK编码目标文件
dst_checkLines.txt
(即将产生) - 源代码
main.go
- mod文件
go.mod
- 签名文件
go.sum
我们连起来跑一下,输出文件内容,而且创建了GBK编码目标文件 dst_checkLines.txt
验证数据库
- 使用如下命令登录MySQL控制台,注意其中的编码格式GBK
$ mysql -u root --password=root --default-character-set=gbk -D golang_development
2. 列举该数据库下的所有表,输入 show tables
3. 查看表结构
desc foo_reports
4. 查看记录
select * from foo_reports;
确认所有记录已经正常存入MySQL数据库。
GBK输出
1. 在Shell窗口中切换到step-5
目录
2. 执行go run main.go
3.查看输出文件
$ cat dst-checkLines.txt
因为是UTF8编码的Terminal,所以汉字不能正常显示。
我们再次使用vscode打开该文件,并切换到GBK编码。
如何切换GBK编码,请参考Step3
章节。
到此,我们完整实现了预期流程
- 从GBK编码源文件中读取,写入UTF8编码的MySQL数据库;
- 从UTF8编码的MySQL数据库读取,写入GBK编码的目标文件。