How to read a csv file in golang

in #programming7 years ago

A few days ago I discovered how easy and practical it is to read a file in csv format with golang.

Then I'll share the recipe.

Let's start

First step

For this example download the MX.zip (MX.txt csv file) file of GeoNames site.

The GeoNames geographical database covers all countries and contains over eleven million placenames that are available for download free of charge.

A sample of the file looks like this:

MX      20000   Zona Centro     Aguascalientes  AGU     Aguascalientes  001     Aguascalientes  01      21.8734 -102.2806       1
MX      20008   Delegación de La Secretaria de Comercio y Fomento Industrial    Aguascalientes  AGU     Aguascalientes  001     Aguascalientes  01      21.8734 -102.2806       1
MX      20009   Palacio de Gobierno del Estado de Aguascalientes        Aguascalientes  AGU     Aguascalientes  001     Aguascalientes  01      21.8734 -102.2806       1
MX      20010   Ramon Romo Franco       Aguascalientes  AGU     Aguascalientes  001     Aguascalientes  01      21.9644 -102.3192       1
MX      20010   Colinas del Rio Aguascalientes  AGU     Aguascalientes  001     Aguascalientes  01      21.9644 -102.3192       1
MX      20010   San Cayetano    Aguascalientes  AGU     Aguascalientes  001     Aguascalientes  01      21.9644 -102.3192       1
MX      20010   Olivares Santana        Aguascalientes  AGU     Aguascalientes  001     Aguascalientes  01      21.9644 -102.3192       1
MX      20010   Las Brisas      Aguascalientes  AGU     Aguascalientes  001     Aguascalientes  01      21.9644 -102.3192       1
MX      20016   La Fundición    Aguascalientes  AGU     Aguascalientes  001     Aguascalientes  01      21.9644 -102.3192       3
MX      20016   Colinas de San Ignacio  Aguascalientes  AGU     Aguascalientes  001     Aguascalientes  01      21.9644 -102.3192 

If you open the file with vim editor, with the following command:
:set list
you can see that data fields are separated by ^I (vim tabulador)

Second step

I'm going to use the encoding/csv package that belongs to the go standart library.

The full version of the code is here

const (
    FILE           = "./MX.txt"
    FILE_DELIMITER = '\t'
    TOTAL_ROWS     = 5
)

func main() {

    file, err := os.Open(FILE)
    printError(err)
    defer file.Close()

    reader := csv.NewReader(file)
    reader.Comma = FILE_DELIMITER

    rows, err := reader.ReadAll()
    printError(err)

    fmt.Printf("\nrows type: %T\n\n", rows)

    d := new(Document)

    for n, col := range rows {
        d.colonia = col[2]
        d.ciudad = col[3]
        d.delegacion = col[5]
        n++
        if n <= TOTAL_ROWS {
            fmt.Printf("%v,%v,%v;\n", d.colonia, d.ciudad, d.delegacion)
        }
    }

}

The next line tells golang that data fields are separated by \t (tabulador) rather than by whitespace.
reader.Comma = FILE_DELIMITER

Now reader.ReadAll() function returns a [][]string data type.
rows, err := reader.ReadAll()

This allows me to store in each element of the array the values of the columns of each line of the file. And this way I can only use the columns of data that I need.

for n, col := range rows {
    d.colonia = col[2]
    d.ciudad = col[3]
    d.delegacion = col[5]

Finally the condition if I use it to stop reading the file on line 5 (TOTAL_ROWS), because the whole file has 144513 records! And I just need a few for this example :)

if n <= TOTAL_ROWS {
    fmt.Printf("%v,%v,%v;\n", d.colonia, d.ciudad, d.delegacion)
}

Maybe in the next post I'll take part of this example to show how to read and load those 144513 records on an ElasticSearch server :)

Sort:  

Congratulations @elsanto! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of upvotes received

Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!

Congratulations @elsanto! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of upvotes

Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!

Congratulations @elsanto! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of upvotes received

Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!