ccbi二进制文件整数以及string压缩方法总结 agile Posted on Aug 14 2019 golang cocos2d-x cocosbuilder ### 阅读cocosbuild源码过程中,发现在生成ccbi文件时,对于不大于65536的整数,可以通过*[Elias Gamma Coding](https://blog.csdn.net/sonikk/article/details/8716529)*方法来压缩。以下是该方法在golang的具体实现 --- **写整数到文件中** ```golang func (write CCBWriteFunc) writeInt(d int, sign bool) error { var temp = make([]byte, 8) var str bytes.Buffer for i := 0; i < 8; i++ { temp[i] = 0 } var tempBit, tempByte int var putBit = func(b bool) { if b { temp[tempByte] |= 1 << uint(tempBit) } tempBit++ if tempBit >= 8 { tempByte++ tempBit = 0 } } var flushBits = func() error { numBytes := tempByte if tempBit != 0 { numBytes++ } return write(temp[:numBytes]) } var num int64 if sign { var dl = int64(d) var bijection int64 if d < 0 { bijection = (-dl) * 2 } else { bijection = dl*2 + 1 } num = bijection } else { num = int64(d) + 1 } if num <= 0 { log.Fatal("Trying to store negative int as unsigned") } l := int(math.Log2(float64(num))) for a := 0; a < l; a++ { putBit(false) str.WriteString("0") } putBit(true) str.WriteString("1") for a := l - 1; a >= 0; a-- { if (num & (1 << (uint(a)))) != 0 { putBit(true) str.WriteString("1") } else { putBit(false) str.WriteString("0") } } return flushBits() } ``` **从文件中读取整数** ```golang func (read CCBReaderFunc) readInt(pSigned bool) (int, error) { bytes := make([]byte, 1) readNew := true _currentBit := 0 var getBit = func() (bool, error) { var bit bool if readNew { if err := read(bytes); err != nil { return false, err } readNew = false } if bytes[0]&(1<<(uint(_currentBit))) != 0 { bit = true } else { bit = false } _currentBit++ if _currentBit >= 8 { _currentBit = 0 bytes = make([]byte, 1) readNew = true } return bit, nil } var alignBits = func() { if _currentBit > 0 { _currentBit = 0 } } var numBit int64 = 0 for { if bit, err := getBit(); err != nil { return 0, err } else { if !bit { numBit++ } else { break } } } //fmt.Printf("numbit:%v", numBit) var current int64 = 0 for a := numBit - 1; a >= 0; a-- { if bit, err := getBit(); err == nil && bit { current |= int64(1 << uint(a)) } else if err != nil { return 0, err } } current |= int64(1 << uint(numBit)) var num int if pSigned { s := int(current % 2) if s != 0 { num = int(current / 2) } else { num = int(-current / 2) } } else { num = int(current - 1) } alignBits() return num, nil } ``` **文本的压缩写进文件** ```golang func (write CCBWriteFunc) writeString(str string) error { ll := len(str) bytesLen := make([]byte, 2) bytesLen[0] = byte((uint(ll) >> 8) & 0xff) bytesLen[1] = byte(uint(ll) & 0xff) if err := write(bytesLen); err != nil { return fmt.Errorf("write string len err:%v", err) } return write([]byte(str)) } ``` **从文件中读取文本** ```golang func (read CCBReaderFunc) readString() (string, error) { var ret string var b0, b1 byte var numBytes int var err error if b0, err = read.readByte(); err != nil { return ret, fmt.Errorf("read utf8 error:%v", err) } if b1, err = read.readByte(); err != nil { return ret, fmt.Errorf("read utf8 error:%v", err) } numBytes = (int(b0) << 8) | int(b1) strBytes := make([]byte, numBytes) if err = read(strBytes); err != nil { return ret, fmt.Errorf("read utf8 str error:%v", err) } else { ret = string(strBytes) } return ret, nil } ``` golang 格式化时间总结 《算法4》深入理解红黑树