69 lines
1.6 KiB
Go
69 lines
1.6 KiB
Go
package openname
|
|
|
|
import (
|
|
"archive/zip"
|
|
"encoding/gob"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/ray1729/gpx-utils/pkg/placenames"
|
|
)
|
|
|
|
// ProcessFile reads the compressed OS Open Names data set and calls the handler for each record.
|
|
func ProcessFile(filename string, handler func(*Record) error) error {
|
|
r, err := zip.OpenReader(filename)
|
|
if err != nil {
|
|
return fmt.Errorf("error opening %s for reading: %v", filename, err)
|
|
}
|
|
defer r.Close()
|
|
|
|
for _, f := range r.File {
|
|
if !(strings.HasPrefix(f.Name, "DATA/") && strings.HasSuffix(f.Name, ".csv")) {
|
|
continue
|
|
}
|
|
rc, err := f.Open()
|
|
if err != nil {
|
|
return fmt.Errorf("error opening %s: %v", filename, err)
|
|
}
|
|
s, err := NewScanner(rc)
|
|
if err != nil {
|
|
rc.Close()
|
|
return fmt.Errorf("error reading %s: %v", f.Name, err)
|
|
}
|
|
for s.Scan() {
|
|
r := s.Record()
|
|
if r.Type == "populatedPlace" && r.MbrXMax != r.MbrXMin && r.MbrYMax != r.MbrYMin {
|
|
if err := handler(r); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
if err = s.Err(); err != nil {
|
|
rc.Close()
|
|
return fmt.Errorf("error parsing %s: %v", f.Name, err)
|
|
}
|
|
rc.Close()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Save processes the OS OpenNames zip file and outputs bounded places in gob format.
|
|
func Save(inFile string, outFile string) error {
|
|
wc, err := os.OpenFile(outFile, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer wc.Close()
|
|
enc := gob.NewEncoder(wc)
|
|
err = ProcessFile(inFile, func(r *Record) error {
|
|
b := placenames.NamedBoundary{
|
|
Name: r.Name,
|
|
Xmin: r.MbrXMin,
|
|
Ymin: r.MbrYMin,
|
|
Xmax: r.MbrXMax,
|
|
Ymax: r.MbrYMax}
|
|
return enc.Encode(b)
|
|
})
|
|
return err
|
|
}
|