Where Is a String Stored in Armsim When Reading a File
Welcome to tutorial no. 35 in Golang tutorial series.
File reading is one of the about common operations performed in any programming language. In this tutorial, we volition learn about how files can be read using Get.
This tutorial has the following sections.
- Reading an unabridged file into memory
- Using an absolute file path
- Passing the file path every bit a command line flag
- Bundling the file inside the binary
- Reading a file in small chunks
- Reading a file line past line
Reading an entire file into memory
Ane of the most basic file operations is reading an entire file into memory. This is done with the help of the ReadFile office of the ioutil package.
Permit's read a file and print its contents.
I have created a folder filehandling inside my Documents directory past running mkdir ~/Documents/filehandling.
Create a Go module named filehandling past running the following control from the filehandling directory.
get mod init filehandling I have a text file test.txt which will exist read from our Go program filehandling.go. test.txt contains the post-obit string
Hello Earth. Welcome to file handling in Become. Here is my directory structure.
├── Documents │ └── filehandling │ ├── filehandling.go | ├── go.mod │ └── test.txt Let's become to the code right away. Create a file filehandling.become with the post-obit contents.
package chief import ( "fmt" "io/ioutil" ) func main() { information, err := ioutil.ReadFile("examination.txt") if err != cipher { fmt.Println("File reading error", err) return } fmt.Println("Contents of file:", string(data)) } Please run this programme from your local environment as it's not possible to read files in the playground.
Line no. 9 of the plan above reads the file and returns a byte slice which is stored in data. In line no. 14 we catechumen data to a string and display the contents of the file.
Please run this programme from the location where test.txt is present.
If exam.txt is located at ~/Documents/filehandling, then run this program using the post-obit steps,
cd ~/Documents/filehandling/ go install filehandling If you are not aware of how to run a Go plan, please visit https://golangbot.com/hi-earth-gomod/ to know more. If yous desire to learn more nearly packages and Get modules, delight visit https://golangbot.com/go-packages/
This program will print,
Contents of file: Hullo World. Welcome to file treatment in Go. If this programme is run from any other location, for instance, attempt running the program from ~/Documents/
cd ~/Documents/ filehandling It volition print the post-obit error.
File reading mistake open test.txt: no such file or directory The reason is Become is a compiled linguistic communication. What go install does is, it creates a binary from the source code. The binary is independent of the source code and it tin can be run from whatever location. Since test.txt is not found in the location from which the binary is run, the program complains that it cannot find the file specified.
There are iii means to solve this problem,
- Using absolute file path
- Passing the file path every bit a control line flag
- Bundling the text file along with the binary
Permit'due south discuss them one past one.
1. Using accented file path
The simplest mode to solve this problem is to pass the absolute file path. I have modified the program and changed the path to an absolute one in line no. ix. Please change this path to the accented location of your examination.txt.
package primary import ( "fmt" "io/ioutil" ) func main() { data, err := ioutil.ReadFile("/habitation/naveen/Documents/filehandling/test.txt") if err != nada { fmt.Println("File reading error", err) return } fmt.Println("Contents of file:", string(data)) } At present the program can be run from any location and information technology will print the contents of exam.txt.
For example, it will piece of work fifty-fifty when I run information technology from my home directory
cd ~/Documents/filehandling become install cd ~ filehandling The program will print the contents of test.txt
This seems to be an easy mode just comes with the pitfall that the file should exist located in the path specified in the program else this method will fail.
2. Passing the file path equally a command line flag
Another way to solve this problem is to pass the file path as a command line statement. Using the flag parcel, we can become the file path every bit input argument from the command line then read its contents.
Permit'southward first understand how the flag bundle works. The flag package has a Cord part. This role accepts iii arguments. The first is the proper noun of the flag, second is the default value and the third is a short description of the flag.
Let'south write a small program to read the file proper name from the command line. Replace the contents of filehandling.go with the following,
package primary import ( "flag" "fmt" ) func main() { fptr := flag.String("fpath", "test.txt", "file path to read from") flag.Parse() fmt.Println("value of fpath is", *fptr) } Line no. 8 of the plan in a higher place, creates a string flag named fpath with default value test.txt and description file path to read from using the String function. This role returns the address of the string variable that stores the value of the flag.
flag.Parse() should exist called before whatsoever flag is accessed by the program.
Nosotros print the value of the flag in line no. 10
When this programme is run using the control
filehandling -fpath=/path-of-file/test.txt we pass /path-of-file/exam.txt every bit the value of the flag fpath.
This programme outputs
value of fpath is /path-of-file/test.txt If the program is run using just filehandling without passing any fpath, it volition print
value of fpath is test.txt since test.txt is the default value of fpath.
Now that we know how to read the file path from the command line, allow's go alee and finish our file reading program.
parcel main import ( "flag" "fmt" "io/ioutil" ) func primary() { fptr := flag.String("fpath", "exam.txt", "file path to read from") flag.Parse() data, err := ioutil.ReadFile(*fptr) if err != nil { fmt.Println("File reading fault", err) return } fmt.Println("Contents of file:", string(information)) } The program above reads the content of the file path passed from the command line. Run this program using the command
filehandling -fpath=/path-of-file/examination.txt Please replace /path-of-file/ with the absolute path of test.txt. For instance, in my case, I ran the command
filehandling --fpath=/abode/naveen/Documents/filehandling/test.txt and the program printed.
Contents of file: Hello Earth. Welcome to file handling in Get. 3. Bundling the text file along with the binary
The above option of getting the file path from the command line is skilful but in that location is an fifty-fifty better way to solve this problem. Wouldn't information technology be awesome if we are able to bundle the text file along with our binary? This is what we are going to exercise next.
There are various packages that help the states accomplish this. Nosotros volition be using packr v2 because information technology'southward quite simple and I accept been using it for my projects without whatever issues.
The first step is to install the packr.
Type the following control in the command prompt from the ~/Documents/filehandling/ directory to install the package
cd ~/Documents/filehandling/ go get -u github.com/gobuffalo/packr/v2/... packr converts static files such as .txt to .go files which are then embedded directly into the binary. Packer is intelligent enough to fetch the static files from deejay rather than from the binary during development. This prevents the need for re-compilation during development when but static files change.
A programme will make united states understand things ameliorate. Supplant the contents of filehandling.go with the following,
package main import ( "fmt" "github.com/gobuffalo/packr/v2" ) func principal() { box := packr.New("fileBox", "../filehandling") information, err := box.FindString("test.txt") if err != nil { fmt.Println("File reading error", err) return } fmt.Println("Contents of file:", data) } In line no. x of the programme higher up, we are creating a New Box named box. A box represents a folder whose contents volition be embedded in the binary. In this case, I am specifying the filehandling folder which contains test.txt. In the next line, we read the contents of the file using the FindString method and print it.
Run the program using the following commands.
cd ~/Documents/filehandling go install filehandling and the programme volition print the contents of examination.txt.
Since we are in the development stage now, the file volition be read from disk. Try changing the contents of test.txt and run filehandling again. You can see that the plan prints the updated contents of exam.txt without the need for any recompilation. Perfect :).
Packr is also capable of finding the absolute path of the box. Because of this, the program will work from any directory. It doesn't need test.txt to be nowadays in the electric current directory. Let's cd to a different directory and try running the program again.
cd ~/Documents filehandling Running the above commands also will print the contents of test.txt.
Now let's move to the side by side step and bundle test.txt to our binary. We use the packr2 command to do this.
Run the packr2 command from filehandling directory.
cd ~/Documents/filehandling/ packr2 This command will search the source code for new boxes and generate Go files that contain our exam.txt text file converted to bytes and this can be bundled along with the Go binary. This command will generate a file chief-packr.go and a package packrd. These 2 are needed to bundle the static file along with the binary.
After running the higher up control, compile and run the program again. The plan will print the contents of test.txt.
go install filehandling When running go install you might get the following error.
build filehandling: cannot load Users/naveen/Documents/filehandling/packrd: malformed module path "Users/naveen/Documents/filehandling/packrd": missing dot in get-go path chemical element This might happen considering packr2 doesn't know that we are using Go Modules. If you go this mistake, effort setting become modules to on explicitly by running the command export GO111MODULE=on. Subsequently setting Go modules to on, the generated files have to be cleaned and regenerated.
packr2 clean packr2 go install filehandling Now the contents of test.txt will be printed and information technology is being read from the binary.
If you doubt whether the file is served from within the binary or from disk, I suggest that y'all delete examination.txt and run the command filehandling again. You can see that test.txt's contents are printed. Awesome :D Nosotros have successfully embedded static files to our binary.
Reading a file in small chunks
In the last section, nosotros learned how to load an entire file into retention. When the size of the file is extremely big it doesn't make sense to read the entire file into memory especially if y'all are running low on RAM. A more optimal style is to read the file in small-scale chunks. This can be done with the help of the bufio package.
Let's write a program that reads our test.txt file in chunks of 3 bytes. Run packr2 clean to remove the files generated past packr in the previous section. Yous might also want to recreate test.txt in instance you deleted it. Replace the contents of filehandling.become with the following,
package main import ( "bufio" "flag" "fmt" "log" "bone" ) func main() { fptr := flag.Cord("fpath", "test.txt", "file path to read from") flag.Parse() f, err := bone.Open(*fptr) if err != nil { log.Fatal(err) } defer func() { if err = f.Shut(); err != zero { log.Fatal(err) } }() r := bufio.NewReader(f) b := make([]byte, iii) for { n, err := r.Read(b) if err != nada { fmt.Println("Error reading file:", err) suspension } fmt.Println(string(b[0:n])) } } In line no. 15 of the program above, we open the file using the path passed from the control line flag.
In line no. 19, we defer the file endmost.
Line no. 24 of the program above creates a new buffered reader. In the adjacent line, we create a byte piece of length and capacity 3 into which the bytes of the file volition be read.
The Read method in line no. 27 reads upwards to len(b) bytes i.eastward upward to 3 bytes and returns the number of bytes read. Nosotros store the bytes returned in a variablen. In line no. 32, the slice is read from index 0 to n-1, i.east up to the number of bytes returned by the Read method and printed.
In one case the end of the file is reached, it will return an EOF error. The residue of the plan is straight forward.
If we run the program above using the commands,
cd ~/Documents/filehandling go install filehandling -fpath=/path-of-file/test.txt the following will be output
Hel lo Wor ld. We lco me to fil e h and lin g i n G o. Error reading file: EOF In the department, we volition discuss how to read a file line past line using Go. This can washed using the bufio package.
Delight replace the contents in exam.txt with the following
Howdy World. Welcome to file handling in Become. This is the second line of the file. We take reached the end of the file. The following are the steps involved in reading a file line by line.
- Open the file
- Create a new scanner from the file
- Scan the file and read it line by line.
Replace the contents of filehandling.go with the following
package main import ( "bufio" "flag" "fmt" "log" "os" ) func main() { fptr := flag.String("fpath", "test.txt", "file path to read from") flag.Parse() f, err := bone.Open(*fptr) if err != nil { log.Fatal(err) } defer func() { if err = f.Shut(); err != nil { log.Fatal(err) } }() southward := bufio.NewScanner(f) for s.Browse() { fmt.Println(s.Text()) } err = southward.Err() if err != aught { log.Fatal(err) } } In line no. fifteen of the programme in a higher place, we open up the file using the path passed from the command line flag. In line no. 24, we create a new scanner using the file. The scan() method in line no. 25 reads the next line of the file and the string that is read volition be available through the text() method.
After Scan returns false, the Err() method volition return whatever error that occurred during scanning. If the error is Cease of File, Err() will return nada.
If nosotros run the programme above using the commands,
cd ~/Documents/filehandling become install filehandling -fpath=/path-of-file/examination.txt the contents of the file will be printed line by line every bit shown below.
Hello World. Welcome to file handling in Go. This is the 2d line of the file. We take reached the stop of the file. This brings usa to the end of this tutorial. Hope you enjoyed information technology. Please leave your comments.
Next tutorial - Writing Files
Like my tutorials? Please show your support by donating. Your donations will help me create more awesome tutorials.
Source: https://golangbot.com/read-files/
0 Response to "Where Is a String Stored in Armsim When Reading a File"
Post a Comment