初识Go语言23-常用标准库【编码】

文章目录


编码

  json是go标准库里自带的序列化工具,使用了反射,效率比较低。
  easyjson只针对预先定义好的json结构体对输入的json字符串进行纯字符串的截取,并将对应的json字段赋值给结构体。easyjson -all xxx.go 生成go文件中定义的结构体对应的解析,xxx.go所在的package不能是main。

func easyjson.Marshal(v easyjson.Marshaler) ([]byte, error)
func easyjson.Unmarshal(data []byte, v easyjson.Unmarshaler) error

  sonic是字节跳动开源的json序列化工具包,号称性能强过easyjson、jsoniter,使用起来非常方便。

import "github.com/bytedance/sonic"

// Marshal
output, err := sonic.Marshal(&data) 
// Unmarshal
err := sonic.Unmarshal(input, &data) 

  base64经常在http环境下用来传输较长的信息。任意byte数组都可以采用base64编码转为字符串,并且可以反解回byte数组。编码和解码的方法是公开、确定的, base64不属于加密算法。

func (*base64.Encoding).EncodeToString(src []byte) string
func (*base64.Encoding).DecodeString(s string) ([]byte, error)

  compress包下实现了zlib、bzip、gip、lzw等压缩算法。

writer := zlib.NewWriter(fout)//压缩
writer.Write(bytes)
reader, err := zlib.NewReader(fin) //解压
io.Copy(os.Stdout, reader)   //把reader流里的内容拷贝给标准输出流,即文件解压后的内容打印到控制台
func compressDemo() error {
    
    
	fin, err := os.Open("aa.go")
	if err != nil {
    
    
		return err
	}
	defer fin.Close()

	stat, _ := fin.Stat()
	fmt.Printf("压缩前文件的大小 %d B\n", stat.Size())

	fout, err := os.OpenFile("go.zlib", os.O_CREATE|os.O_WRONLY, 0777)
	if err != nil {
    
    
		return err
	}

	defer fout.Close()

	bs := make([]byte, 1024)
	writer := zlib.NewWriter(fout)
	for {
    
    
		n, err := fin.Read(bs)
		if err == nil {
    
    
			writer.Write(bs[:n])
		} else {
    
    
			if err == io.EOF {
    
    
				break
			} else {
    
    
				fmt.Println(err)
				break
			}
		}
	}

	writer.Close()

	fin, err = os.Open("go.zlib")
	if err != nil {
    
    
		return err
	}
	defer fin.Close()

	stat, _ = fin.Stat()
	fmt.Printf("压缩后文件的大小 %d B\n", stat.Size())

	reader, err := zlib.NewReader(fin)
	if err != nil {
    
    
		return err
	}
	io.Copy(os.Stdout, reader)
	reader.Close()
	fin.Close()

	return nil
}

homework

1. 把字符串1998-10-01 08:10:00解析成time.Time,再格式化成字符串199810010810
2. 我们是每周六上课,输出我们未来4次课的上课日期(不考虑法定假日)
3. 把一个目录下的所有.txt文件合一个大的.txt文件,再对这个大文件进行压缩
4. 自己实现一个BufferedFileWriter
	format1 := "2006-01-02 15:04:05"
	format2 := "20060102150405"

	s := "1998-10-01 08:10:00"
	loc, _ := time.LoadLocation("Asia/Shanghai")

	t, _ := time.ParseInLocation(format1, s, loc)
	fmt.Println(t)

	t2 := t.Format(format2)
	fmt.Println(t2)
2. 我们是每周六上课,输出我们未来4次课的上课日期(不考虑法定假日)

func getDay() {
    
    
	now := time.Now()
	sub := 6 - int(now.Weekday())
	interval := sub
	if sub == 0 {
    
    
		interval = 7
	}
	Satuday := now.Add(24 * time.Duration(interval) * time.Hour)
	fmt.Println(Satuday.Format("2006-01-02"))
	for i := 0; i < 3; i++ {
    
    
		Satuday = Satuday.Add(24 * 7 * time.Hour)
		fmt.Println(Satuday.Format("2006-01-02"))
	}
}
3. 把一个目录下的所有.txt文件合一个大的.txt文件,再对这个大文件进行压缩
func readFile(inPath string, writer *bufio.Writer, writer2 *zlib.Writer) {
    
    
	if fin, err := os.Open(inPath); err != nil {
    
    
		fmt.Println(err)
		return
	} else {
    
    
		defer fin.Close()

		reader := bufio.NewReader(fin)
		for {
    
    
			if line, err := reader.ReadString('\n'); err != nil {
    
    
				if err == io.EOF {
    
    
					if len(line) > 0 {
    
     //文件最后一行末尾没有换行符
						writer.WriteString(line)
						writer.WriteString("\n")
						writer2.Write([]byte(line))
						writer2.Write([]byte{
    
    '\n'})
					}
				}
				break
			} else {
    
    
				writer.WriteString(line)
				writer2.Write([]byte(line))
			}
		}
	}
}

func mergeFile(dir string) {
    
    
	fout, err := os.OpenFile("big.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, os.ModePerm)
	if err != nil {
    
    
		fmt.Println(err)
		return
	}
	defer fout.Close()

	writer := bufio.NewWriter(fout)

	fout2, err := os.OpenFile("big.zlib", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, os.ModePerm)
	if err != nil {
    
    
		fmt.Println(err)
		return
	}
	defer fout2.Close()

	writer2 := zlib.NewWriter(fout2) //需要切片,先转成切片在压缩

	if files, err := ioutil.ReadDir(dir); err != nil {
    
     //ReadDir只能读一级子目录
		fmt.Println(err)
		return
	} else {
    
    
		for _, file := range files {
    
    
			if file.IsDir() {
    
    
				continue
			}
			baseName := file.Name()
			if strings.HasSuffix(baseName, ".txt") {
    
    
				inPath := filepath.Join(dir, baseName)
				readFile(inPath, writer, writer2)
			}
		}
	}
	writer.Flush()
	writer2.Flush()
}
4. 自己实现一个BufferedFileWriter
type BufferedFileWriter struct {
    
    
	buffer      [1024]byte
	endPos      int // 当前写到buffer的什么位置了,切片的len是固定的,所以没法用len来求出写到什么位置
	fileHandler *os.File
}

func NewBufferedFileWriter(fd *os.File) *BufferedFileWriter {
    
    
	return &BufferedFileWriter{
    
    
		fileHandler: fd,
	}
}

func (writer *BufferedFileWriter) Flush() {
    
    
	if writer.endPos > 0 {
    
    
		writer.fileHandler.Write(writer.buffer[:writer.endPos])
		writer.endPos = 0
	}
}

func (writer *BufferedFileWriter) Write(content []byte) {
    
    
	if len(content) >= 1024 {
    
    
        writer.Flush()
		writer.fileHandler.Write(content)
	} else {
    
    
		if writer.endPos+len(content) >= 1024 {
    
    
			writer.Flush()
			writer.Write(content)
		} else {
    
    
			copy(writer.buffer[writer.endPos:], content)
			writer.endPos += len(content)
		}
	}
}

func (writer *BufferedFileWriter) WriterString(content string) {
    
    
	writer.Write([]byte(content))
}

func testBufferWriter() {
    
    
	fout, err := os.OpenFile("shiyi.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, os.ModePerm)
	if err != nil {
    
    
		fmt.Println(err)
		return
	}
	defer fout.Close()

	writer := NewBufferedFileWriter(fout)
	for i := 0; i < 5; i++ {
    
    
		writer.WriterString("1666\n")
	}
	writer.Flush()
}

猜你喜欢

转载自blog.csdn.net/m0_52896752/article/details/129796115