1

I am new to golang, and I am trying to fetch 1 csv file to another new csv file, but i need only 2 records from the old csv file.

How would you fetch only the first two records of that file?

Here is what I have tried so far (also in the play.golang.org):

package main

import (
    "encoding/csv"
    "fmt"
    "io"
    "os"
)

func main() {

    //SELECTING THE FILE TO EXTRACT.......

    csvfile1, err := os.Open("data/sample.csv")
    if err != nil {
        fmt.Println(err)
        return
    }

    defer csvfile1.Close()

    reader := csv.NewReader(csvfile1)

    for i := 0; i < 3; i++ {
        record, err := reader.Read()
        if err == io.EOF {
            break
        } else if err != nil {
            fmt.Println(err)
            return
        }
        csvfile2, err := os.Create("data/SingleColomReading.csv")
        if err != nil {
            fmt.Println(err)
            return
        }
        defer csvfile2.Close()

        records := []string{
            record,
        }
        writer := csv.NewWriter(csvfile2)
        //fmt.Println(writer)
        for _, single := range records {

            er := writer.Write(single)
            if er != nil {
                fmt.Println("error", er)
                return
            }

            fmt.Println(single)

            writer.Flush()
            //fmt.Println(records)
            //a:=strconv.Itoa(single)
            n, er2 := csvfile2.WriteString(single)
            if er2 != nil {
                fmt.Println(n, er2)
            }

        }
    }
}
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
A.H
  • 129
  • 2
  • 10
  • Maybe run your code through gofmt first. And then explain what your exact problem is. And remove all the excessive full stops. –  Oct 18 '14 at 08:35

2 Answers2

4

Fixing your program,

package main

import (
    "encoding/csv"
    "fmt"
    "io"
    "os"
)

func main() {
    csvfile1, err := os.Open("data/sample.csv")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer csvfile1.Close()
    reader := csv.NewReader(csvfile1)
    csvfile2, err := os.Create("data/SingleColomReading.csv")
    if err != nil {
        fmt.Println(err)
        return
    }
    writer := csv.NewWriter(csvfile2)

    for i := 0; i < 2; i++ {
        record, err := reader.Read()
        if err != nil {
            if err == io.EOF {
                break
            }
            fmt.Println(err)
            return
        }
        err = writer.Write(record)
        if err != nil {
            fmt.Println(err)
            return
        }
    }
    writer.Flush()
    err = csvfile2.Close()
    if err != nil {
        fmt.Println(err)
        return
    }
}

However, since you are only interested in copying records (lines) as a whole and not individual fields of a record, you could use bufio.Scanner, as @VonC suggested. For example,

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    csvfile1, err := os.Open("data/sample.csv")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer csvfile1.Close()
    scanner := bufio.NewScanner(csvfile1)
    csvfile2, err := os.Create("data/SingleColomReading.csv")
    if err != nil {
        fmt.Println(err)
        return
    }
    writer := bufio.NewWriter(csvfile2)

    nRecords := 0
    for scanner.Scan() {
        n, err := writer.Write(scanner.Bytes())
        if err != nil {
            fmt.Println(n, err)
            return
        }
        err = writer.WriteByte('\n')
        if err != nil {
            fmt.Println(err)
            return
        }
        if nRecords++; nRecords >= 2 {
            break
        }
    }
    if err := scanner.Err(); err != nil {
        fmt.Println(err)
        return
    }
    err = writer.Flush()
    if err != nil {
        fmt.Println(err)
        return
    }
    err = csvfile2.Close()
    if err != nil {
        fmt.Println(err)
        return
    }
}
Community
  • 1
  • 1
peterSO
  • 158,998
  • 31
  • 281
  • 276
3

It owuld be easier to:

  • read your csv file into a string array (one line per element), for the two first lines only

    var lines []string
    scanner := bufio.NewScanner(file)
    nblines := 0
    for scanner.Scan() {
        lines = append(lines, scanner.Text())
        if nblines++; nblines >= 2 {
            break
        }
    }
    
  • Then you can use a range lines to write those two lines in the destination file.
    lines includes at most 2 elements.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • hai, thanks bro, but it is not working.can u write full program for me. – A.H Oct 19 '14 at 05:40
  • @VonC: Idiomatically, write `nblines = nblines + 1` as `nblines++`. There is no need to save lines in a slice when copying lines, write the lines as they are read. `bufio.Scanner` strips the end-of-line from lines as they are read. Put it back as lines are written. – peterSO Oct 19 '14 at 12:58
  • @Harish: See my revised answer. – peterSO Oct 19 '14 at 12:59