Skip to content

Instantly share code, notes, and snippets.

@jpetitcolas
Last active July 27, 2020 12:40
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save jpetitcolas/28893445d8062d7081d5 to your computer and use it in GitHub Desktop.
Save jpetitcolas/28893445d8062d7081d5 to your computer and use it in GitHub Desktop.
How to parse a binary file in Go? Snippet based on MoPaQ SC2 replay parsing. Related blog post: http://www.jonathan-petitcolas.com/2014/09/25/parsing-binary-files-in-go.html
package main
import (
"bytes"
"encoding/binary"
"fmt"
"log"
"os"
)
type Header struct {
UserDataMaxSize uint32
HeaderOffset uint32
UserDataSize uint32
_ [5]byte
Starcraft2 [22]byte
}
func main() {
path := "replay.SC2Replay"
file, err := os.Open(path)
if err != nil {
log.Fatal("Error while opening file", err)
}
defer file.Close()
fmt.Printf("%s opened\n", path)
formatName := readNextBytes(file, 4)
fmt.Printf("Parsed format: %s\n", formatName)
if string(formatName) != "MPQ\x1b" {
log.Fatal("Provided replay file is not in correct format. Are you sure this is a SC2 replay file?")
}
header := Header{}
data := readNextBytes(file, 39) // 3 * uint32 (4) + 5 * byte (1) + 22 * byte (1) = 43
buffer := bytes.NewBuffer(data)
err = binary.Read(buffer, binary.LittleEndian, &header)
if err != nil {
log.Fatal("binary.Read failed", err)
}
fmt.Printf("Parsed data:\n%+v\n", header)
}
func readNextBytes(file *os.File, number int) []byte {
bytes := make([]byte, number)
_, err := file.Read(bytes)
if err != nil {
log.Fatal(err)
}
return bytes
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment