0

I am trying to write Student Marks to a csv file in GO .

It is printing the desired 10 result per page with Println but is saving only the last value (not all 10) in csv .

This is what I am doing

  1. Visitor visits studentmarks.com/page=1 Marks for 10 students are displayed and it is also saved in CSV

  2. Visitor clicks next page and he is navigated to studentmarks.com/page=2 Marks for another 10 students are displayed and it is also saved in subsequent column/rows in the CSV

and so on

fmt.Fprintf(w, KeyTemplate, key.fname, key.marks, key.lname ) is working fine and displays all 10 results per page but I am unable to save all 10 results in the CSV (with my current code, only the last result is saved).

Here is my snippet of the code that is responsible for printing and saving the results.

func PageRequest(w http.ResponseWriter, r *http.Request) {
    // Default page number is 1
    if len(r.URL.Path) <= 1 {
        r.URL.Path = "/1"
    }

    // Page number is not negative or 0
    page.Abs(page)
    if page.Cmp(one) == -1 {
        page.SetInt64(1)
    }



    // Page header
    fmt.Fprintf(w, PageHeader, pages, previous, next)

    // Marks for UID
    UID, length := compute(start)
    for i := 0; i < length; i++ {
        key := UID[i]


        fmt.Fprintf(w, key.fname, key.marks, key.lname, key.remarks)


      // Save in csv

 csvfile, err := os.Create("marks.csv")
          if err != nil {
                  fmt.Println("Error:", err)
                  return
          }
          defer csvfile.Close()

          records := [][]string{{key.fname, key.marks, key.lname, , key.remarks}}

          writer := csv.NewWriter(csvfile)
          for _, record := range records {
                  err := writer.Write(record)
                  if err != nil {
                          fmt.Println("Error:", err)
                          return
                  }
          }
          writer.Flush()


    // Page Footer
    fmt.Fprintf(w, PageFooter, previous, next)
}

How can I print and save (in csv) all the 10 results using go language?

7
  • Move the statements that creating csv file marks.csv i.e. csvfile, err ... defer... out of for loop, e.g. after calling compute(start). Commented Jun 10, 2017 at 14:20
  • no doesn't help, values are in (key.fname, key.marks, key.lname, key.remarks), the values generated and printed by the program are correct, only thing is that i need to save it successfully in csv . Commented Jun 10, 2017 at 14:37
  • Probably it was not clear from my first comment. You need to move the statements (6 lines) csvfile, err := os.Create("marks.csv") ... defer csvfile.Close() out of for loop. The other statements (from records := ...) should be left as is. Commented Jun 10, 2017 at 14:49
  • it works for page=1,when we go to page=2 it replaces the csv with all values of page=2,it should add rather than deleting previous values . Commented Jun 10, 2017 at 15:26
  • To save all the marks into a same file, open the CSV file with os.O_APPEND mode (as mentioned in the answer). But, please notes that whenever a visitor visits a page, the marks will be added to the CSV file, resulting duplicates marks in the file, e.g. when visitor access page 1 twice, marks from 10 students from page 1 will be added twice to the CSV file. Commented Jun 11, 2017 at 0:07

1 Answer 1

1

The basic problem is that you are calling os.Create. The documentation for os.Create says

Create creates the named file with mode 0666 (before umask), truncating it if it already exists. If successful, methods on the returned File can be used for I/O; the associated file descriptor has mode O_RDWR. If there is an error, it will be of type *PathError.

So each call to os.Create will remove all content from the file you passed. Instead what you want is probably os.OpenFile with the os.O_CREATE, os.O_WRONLY and os.O_APPEND flags. This will make sure that the file will be created, if it doesn't exists, but won't truncate it.

But there is another problem in your code. You are calling defer csvfile.Close() inside the loop. A deferred function will only be executed once the function returns and not after the loop iteration. This can lead to problems, especially since you are opening the same file over and over again.

Instead you should open the file once before the loop so that you only need to close it once. Like this:

package main

import (
    "encoding/csv"
    "fmt"
    "net/http"
    "os"
)

func PageRequest(w http.ResponseWriter, r *http.Request) {
    // Default page number is 1
    if len(r.URL.Path) <= 1 {
        r.URL.Path = "/1"
    }

    // Page number is not negative or 0
    page.Abs(page)
    if page.Cmp(one) == -1 {
        page.SetInt64(1)
    }

    // Page header
    fmt.Fprintf(w, PageHeader, pages, previous, next)

    // Save in csv
    csvfile, err := os.OpenFile("marks.csv", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer csvfile.Close()

    writer := csv.NewWriter(csvfile)
    defer writer.Flush()

    // Marks for UID
    UID, length := compute(start)
    for i := 0; i < length; i++ {
        key := UID[i]

        fmt.Fprintf(w, key.fname, key.marks, key.lname, key.remarks)

        records := [][]string{{key.fname, key.marks, key.lname, key.remarks}}

        for _, record := range records {
            err := writer.Write(record)
            if err != nil {
                fmt.Println("Error:", err)
                return
            }
        }
    }

    // Page Footer
    fmt.Fprintf(w, PageFooter, previous, next)
}
Sign up to request clarification or add additional context in comments.

1 Comment

that will append the results in same CSV,could we save result from each page in different CSV,like - 1.)Visitor visits page 1 Marks for 10 students are saved in CSV in marks1.csv , 2.)Visitor visits page 2 Marks for 10 students saved in CSV in marks2.csv and so on ...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.