I have a text file containing some text data I would like to read in. Unfortunately I can't find the way to do it.
Here is an example
5 4
1 2 - Yogurt
2 0 X Chicken soup
3 1 X Cheese
4 3 X Ham
2
3
4
0
The file is made of three parts. The first part is the header (first line), the second part is a list of records, and the last part is a list of unit64 values.
The header contains only two values, a uint64 followed by a unit16. The second value is the number of records and also the number of values in the third part since these numbers are the same.
A record is a unit64 value, followed by a uint16 value, followed by a single char that can only be X or -, followed by a utf-8 encoded string up to the end of line. The data has be written into the file by using fmt.Fprintf().
The third part contains uint64 values.
I've spending some hours now trying to find out how to read this data out of the text file and can't find a way.
I can only use strconv.ParseUint(str, 0, 64) or uint16(strconv.ParseUint(str, 0, 16)) if str contains only the digits belonging to the number. I looked into bufio to use the Reader but I can get at most lines. I should probably use the bufio.Scanner but I can't determine how to use it from the documentation.
The Rubber duck debugging effect worked again. After asking the question, I found out the answer by my self. Here it is in case other people share the same problem I had.
In the following example I'll simply print out the data read
import (
"bufio"
"fmt"
"log"
"os"
"strings"
)
func loadFile( fileName string ) {
// Open file and instantiate a reader
file, err := os.Open(fileName)
if err != nil {
log.Fatal(err)
}
reader := bufio.NewReader(file)
var {
value0 uint64,
nbrRows uint16
}
// Read header values
if _,err := fmt.Fscanf(reader, "%d %d
", &value0, &nbrRows); err != nil {
log.Fatal(err)
}
// Iterate on the rows
for i := uint16(0); i < nbrRows; i++ {
var {
value1 uint64,
value2 uint16,
value3 string,
value4 string
}
// Read first three row values
if _,err := fmt.Fscanf(reader, "%d %d %s
", &value1, &value2, &value3); err != nil {
log.Fatal(err)
}
// Read remain of line
if value4,err := reader.ReadString('
'); err != nil {
log.Fatal(err)
}
value4 = strings.Trim(value4,"
")
// Display the parsed data
fmt.Printf("%d %d %s '%s'
", value1, value2, value3, value4)
}
// Iterate on the rows containing a single integer value
for i := uint16(0); i < nbrRows; i++ {
var value5 uint64
// Read the value
if _,err := fmt.Fscanf(reader, "%d
", &value5); err != nil {
log.Fatal(err)
}
// Display the parsed data
fmt.Printf("%d
", value5)
}
}
This code assume that the value4 doesn't start and end with spaces or newlines, which is my case. This is because the Trim() call will remove them.