1

I'm coding a little Go program. It reads files in a directory line by line, it only reads lines with a certain prefix, normalizes the data and outputs to one of two files, depending on whether the normalized record has certain number of elements.

Data is being outputted to the Data file, but errors are not being outputted to the Errors file.

Debugging I see no issue.

Any help is much appreciated.

Thanks,

Martin

package main

import (
    "bufio"
    "fmt"
    "io/ioutil"
    "log"
    "os"
    "strings"
)

func main() {

    //Output file - Data
    if _, err := os.Stat("allData.txt"); os.IsNotExist(err) {

        var file, err = os.Create("allData.txt")

        if err != nil {
            fmt.Println(err)
            return
        }
        defer file.Close()
    }

    file, err := os.OpenFile("allData.txt", os.O_WRONLY|os.O_APPEND, 0644)
    if err != nil {
        panic(err)
    }

    w := bufio.NewWriter(file)

    //Output file - Errors
    if _, err := os.Stat("errorData.txt"); os.IsNotExist(err) {

        var fileError, err = os.Create("errorData.txt")

        if err != nil {
            fmt.Println(err)
            return
        }
        defer fileError.Close()
    }

    fileError, err := os.OpenFile("errorData.txt", os.O_WRONLY|os.O_APPEND, 0644)
    if err != nil {
        panic(err)
    }

    z := bufio.NewWriter(fileError)

    //Read Directory
    files, err := ioutil.ReadDir("../")
    if err != nil {
        log.Fatal(err)
    }

    //Build file path
    for _, f := range files {
        fName := string(f.Name())
        sPath := string("../" + fName)
        sFile, err := os.Open(sPath)
        if err != nil {
            fmt.Println(err)            
            return
        }

        //Create scanner
        scanner := bufio.NewScanner(sFile)
        scanner.Split(bufio.ScanLines)
        var lines []string
        // This is the buffer now
        for scanner.Scan() {
            lines = append(lines, scanner.Text())
        }
        for _, line := range lines {

            sRecordC := strings.HasPrefix((line), "DATA:")

            if sRecordC {
                splitted := strings.Split(line, " ")
                splittedNoSpaces := deleteEmpty(splitted)

                if len(splittedNoSpaces) == 11 {
                    splittedString := strings.Join(splittedNoSpaces, " ")
                    sFinalRecord := string(splittedString + "\r\n")
                    if _, err = fmt.Fprintf(w, sFinalRecord); err != nil {
                    }
                }
                if len(splittedNoSpaces) < 11 {
                    splitted := strings.Split(line, " ")
                    splittedNoSpaces := deleteEmpty(splitted)
                    splittedString := strings.Join(splittedNoSpaces, " ")
                    sFinalRecord := string(splittedString + "\r\n")
                    if _, err = fmt.Fprintf(z, sFinalRecord); err != nil {
                    }

                    err = fileError.Sync()
                    if err != nil {
                        log.Fatal(err)
                    }
                }
            }
        }
    }
    err = file.Sync()
    if err != nil {
        log.Fatal(err)
    }
}

//Delete Empty array elements
func deleteEmpty(s []string) []string {
    var r []string
    for _, str := range s {
        if str != "" {
            r = append(r, str)
        }
    }
    return r
}
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Martin
  • 121
  • 1
  • 7
  • 1
    Don't check for existence before creating, just use the `os.O_CREATE` flag, see https://stackoverflow.com/questions/35558787/create-an-empty-text-file/35558965#35558965, You're also not Flushing your bufio.Writers. – JimB Mar 15 '18 at 21:30
  • @JimB : You rock! Thank you so much. – Martin Mar 15 '18 at 21:42

1 Answers1

3

Don't open the file multiple times, and don't check for the file's existence before creating it, just use the os.O_CREATE flag. You're also not deferring the correct os.File.Close call, because it's opened multiple times.

When using a bufio.Writer, you should always call Flush() to ensure that all data has been written to the underlying io.Writer.

JimB
  • 104,193
  • 13
  • 262
  • 255