go 字符串壓縮 lzw

語言: CN / TW / HK

LZW

LZW算法又叫“串表壓縮算法”就是通過建立一個字符串表,用較短的代碼來表示較長的字符串來實現壓縮。算是一種無損壓縮.LZW壓縮算法是Unisys的專利,有效期到2003年,所以對它的使用已經沒有限制了

go 示例:

package main

import (
	"bytes"
	"compress/lzw"
	"encoding/base64"
	"fmt"
	"io"
)

func main() {

	str := `<shapes name="mxgraphf:.downloads">
<shape aspect="variable" h="66" name="ts" strokewidth="inherit" w="75">
    <connections/>
    <foreground>
        <save/>
        <strokecolor color="#000000"/>
        <miterlimit limit="10"/>
        <path>
            <move x="0" y="33"/>
            <line x="15" y="33"/>
            <move x="60" y="43"/>
            <line x="75" y="43"/>
            <move x="60" y="23"/>
            <line x="75" y="23"/>
            <move x="51" y="3"/>
            <line x="75" y="3"/>
            <move x="51" y="63"/>
            <line x="75" y="63"/>
            <move x="18" y="33"/>
            <line x="51.354" y="24.479"/>
        </path>
        <stroke/>
        <restore/>
        <rect/>
        <stroke/>
        <strokecolor color="#000000"/>
        <fillcolor color="#ffffff"/>
        <ellipse h="6" w="6" x="54" y="40"/>
        <fillstroke/>
        <ellipse h="6" w="6" x="54" y="20"/>
        <fillstroke/>
        <ellipse h="6" w="6" x="45" y="0"/>
        <fillstroke/>
        <ellipse h="6" w="6" x="45" y="60"/>
        <fillstroke/>
        <ellipse h="6" w="6" x="15" y="30"/>
        <fillstroke/>
        <fillcolor color="#000000"/>
        <miterlimit limit="10"/>
        <path>
            <move x="50.161" y="21.995"/>
            <line x="56.797" y="23.205"/>
            <line x="52.026" y="27.356"/>
            <close/>
        </path>
        <fillstroke/>
    </foreground>
</shape>
</shapes>`

	//壓縮
	fmt.Println("=======壓縮開始=========")
	fmt.Println()
	compreStr := compress(str)
	fmt.Println()
	fmt.Println()
	//解壓
	fmt.Println("======開始解壓========")
	fmt.Println()
	uncompress(compreStr)

}

func uncompress(str string) string {
	//base64 解碼
	fmt.Println("base64長度:",len(str))
	byteData, err := base64.StdEncoding.DecodeString(str)
	if err != nil {
		panic(err)
	}
	fmt.Println("壓縮數據長度:",len(byteData))
	reader := bytes.NewReader(byteData)
	readCloser := lzw.NewReader(reader, lzw.LSB, 8)
	defer readCloser.Close()

	outBuffer := bytes.NewBuffer([]byte{})
	_, err = io.Copy(outBuffer, readCloser)
	if err != nil {
		panic(err)
	}
	fmt.Println("源數據長度:", len(outBuffer.Bytes()))
	result := string(outBuffer.Bytes())
	fmt.Println(result)
	return result
}

func compress(str string) string {
	originData := []byte(str)
	fmt.Println("源數據長度:", len(originData))
	outBuffer := bytes.NewBuffer([]byte{})

	/*
		參數列表:
		1)w  輸出壓縮數據的io.Wrier
		2)order lzw數據流的位順序,有LSB和MSB
		3)litWidth  字面碼的位數,必須在[2,8]範圍內,一般位8
		返回值:一個io.WriteCloser,可以將壓縮的數據寫入其下層的w,調用者使用後要將其關閉
		功能説明:
		NewWriter創建一個新的io.WriterCloser。它將數據壓縮後寫入w。調用者要在寫入結束之後調用返回io.WriterCloser的Close函數關閉。litWidth是字面碼的位數,必須在[2,8]範圍內,一般為8。
	*/
	writer := lzw.NewWriter(outBuffer, lzw.LSB, 8)
	defer writer.Close()
	_, err := writer.Write(originData)
	if err != nil {
		panic(err)
	}

	//輸出壓縮數據
	fmt.Println("壓縮數據長度:", len(outBuffer.Bytes()))
	base64Str := base64.StdEncoding.EncodeToString(outBuffer.Bytes())
	fmt.Println("base64 長度:", len(base64Str))
	fmt.Println(base64Str)
	fmt.Println(string(outBuffer.Bytes()))
	return base64Str
}


源數據長度: 1463
壓縮數據長度: 642
base64 長度: 856

參閲1