// makeTreeFromTreeFile takes in a file in the same format TREE.writeToFile() // puts out, and remakes a HuffTree from it. func makeTreeFromTreeFile(file *os.File) (t *huffNode, err error) { bytes := make([]byte, 1) _, err = file.Read(bytes) if err != nil { return nil, err } length := int(bytes[0] + 1) // Now we read in all the characters and their associated bit strings, // and make a tree out of them root := huffNode{char: 1} for i := 0; i < length; i++ { _, err = file.Read(bytes) if err != nil { return nil, err } char := bytes[0] _, err = file.Read(bytes) if err != nil { return nil, err } numBits := int(bytes[0]) br, err := bitIO.NewReaderOnFile(file) if err != nil { return nil, err } current := &root for j := 0; j < numBits; j++ { bit, err := br.ReadBit() if err != nil { return nil, err } if bit == 0 { if current.left == nil { current.left = &huffNode{char: 1} } current = current.left } else { if current.right == nil { current.right = &huffNode{char: 1} } current = current.right } } current.char = char } return &root, nil }
// writeDecodedText decompresses the bits in the passed file, and puts the decompressed // text into a new file described by toFile. If toFile exists before this is called, // it will be truncated. Returns a nil error on success, non-nil error otherwise. func (t *huffNode) writeDecodedText(fromFile *os.File, toFile string, length uint64) (err error) { // Set up a BitReader on the file to decodes reader, err := bitIO.NewReaderOnFile(fromFile) if err != nil { return err } // Decode our bits toWrite := []byte{} current := t // until we've written as many bytes as are encoded... for uint64(len(toWrite)) < length { bit, err := reader.ReadBit() // Check for errors if err != nil { return err } if bit == 0 { current = current.left } else if bit == 1 { current = current.right } else { // Should never happen return errors.New("Got invalid bit") } if current.left == nil && current.right == nil { // We're at a leaf node, write out its character toWrite = append(toWrite, current.char) current = t } } // We've terminated, write it all out return ioutil.WriteFile(toFile, toWrite, 0644) }