Reading Files Into Arrays
04/05/21 08:22 Filed in: GO
Last time I learned how to read a text file. I continue my investigation of reading text files by loading a file full of numbers into an array. Along the way I learn about converting numbers.
Here is the code I have for reading a text file.
I'll use this as the starting point.
I still need to open and close the file, but I need to handle (no pun intended) reading the text file differently. Instead of reading lines of text, I want to read lines of floating point numbers as text, and convert them. I'll swap out the readFile function.
This is the shell of the function. Right now, I'm hard-coding the fact that this will return 5 numbers. I'll fix this once I get the basic logic working. This function will return two things. First, it will return the array of 5 numbers as floating point.
[5]float64
In GO, the size of the array comes first, followed by the data type to be returned; in this case float64.
I'll still need a scanner to read through the file, and the for loop to read through the file. This is the same logic as in readFile.
Inside the loop, I want to get a line of text. This again is similar to readFile, where I use scanner.Text(), but instead of passing the text to Println, I need to convert the line into a number. I can do this with a function in strconv named ParseFloat(). This function takes two argument, and returns two things. Here is the signature:
ParseFloat(s string, bits int) (float64, error) // bits is the precision and can only be 32, or 64.
I'm going to use 64 bits, so my actual call will be:
num, error = strconv.ParseFloat(scanner.Text(),64)
But, because I want to store the values in an array, I need an array:
var nums [5]float64 // declare an array of 5 float64 numbers
And a counter to index into the array
i := 0 // index into nums
I can now change my call to ParseFloat to use the array.
num[i], error = strconv.ParseFloat(scanner.Text(),64)
error is a type in GO. I need to declare a variable of type error. I'll call it err.
var err error
Each time through the loop, I need to increment the index, of course.
i++
Putting this all together the code becomes:
The final piece is handling any errors and returning the values. There are two places where an error can occur. First, in the call to ParseFloat.
if error != nil {
return nums, err // return the array and the error
}
And in the scanning itself:
if scanner.Err() != nil {
return nums, scanner.Err() // return the array and the error
}
Finally if there are no errors
return nums, err
I can refactor these bits of code as:
if scanner.Err() != nil {
err = scanner.Err()
}
return nums, err
Even, if there is an error in both the scanning and the conversion, we can only return a single error. If there is no error, then err will still be nil.
Lastly I need to change main to call my new function:
This goes through a file of 5 numbers I'm calling nums.txt.
The final program looks like this:
And when I run it I get:
There is, however, a problem. GO arrays are fixed to the size they are declared. So, this program fails if there are more than 5 numbers in nums.txt. Next time, I'll take a look at something called a "slice" that can help solve this problem.
Here is the code I have for reading a text file.
I'll use this as the starting point.
I still need to open and close the file, but I need to handle (no pun intended) reading the text file differently. Instead of reading lines of text, I want to read lines of floating point numbers as text, and convert them. I'll swap out the readFile function.
This is the shell of the function. Right now, I'm hard-coding the fact that this will return 5 numbers. I'll fix this once I get the basic logic working. This function will return two things. First, it will return the array of 5 numbers as floating point.
[5]float64
In GO, the size of the array comes first, followed by the data type to be returned; in this case float64.
I'll still need a scanner to read through the file, and the for loop to read through the file. This is the same logic as in readFile.
Inside the loop, I want to get a line of text. This again is similar to readFile, where I use scanner.Text(), but instead of passing the text to Println, I need to convert the line into a number. I can do this with a function in strconv named ParseFloat(). This function takes two argument, and returns two things. Here is the signature:
ParseFloat(s string, bits int) (float64, error) // bits is the precision and can only be 32, or 64.
I'm going to use 64 bits, so my actual call will be:
num, error = strconv.ParseFloat(scanner.Text(),64)
But, because I want to store the values in an array, I need an array:
var nums [5]float64 // declare an array of 5 float64 numbers
And a counter to index into the array
i := 0 // index into nums
I can now change my call to ParseFloat to use the array.
num[i], error = strconv.ParseFloat(scanner.Text(),64)
error is a type in GO. I need to declare a variable of type error. I'll call it err.
var err error
Each time through the loop, I need to increment the index, of course.
i++
Putting this all together the code becomes:
The final piece is handling any errors and returning the values. There are two places where an error can occur. First, in the call to ParseFloat.
if error != nil {
return nums, err // return the array and the error
}
And in the scanning itself:
if scanner.Err() != nil {
return nums, scanner.Err() // return the array and the error
}
Finally if there are no errors
return nums, err
I can refactor these bits of code as:
if scanner.Err() != nil {
err = scanner.Err()
}
return nums, err
Even, if there is an error in both the scanning and the conversion, we can only return a single error. If there is no error, then err will still be nil.
Lastly I need to change main to call my new function:
This goes through a file of 5 numbers I'm calling nums.txt.
The final program looks like this:
And when I run it I get:
There is, however, a problem. GO arrays are fixed to the size they are declared. So, this program fails if there are more than 5 numbers in nums.txt. Next time, I'll take a look at something called a "slice" that can help solve this problem.