Golang Os.create and Read File Return 0
Welcome to tutorial no. 35 in Golang tutorial series.
File reading is one of the nearly mutual operations performed in any programming language. In this tutorial, we volition learn well-nigh how files can be read using Go.
This tutorial has the following sections.
- Reading an unabridged file into memory
- Using an absolute file path
- Passing the file path as a command line flag
- Bundling the file inside the binary
- Reading a file in modest chunks
- Reading a file line by line
Reading an entire file into retentiveness
One of the most bones file operations is reading an entire file into memory. This is done with the help of the ReadFile function of the ioutil package.
Let's read a file and print its contents.
I have created a folder filehandling within my Documents directory past running mkdir ~/Documents/filehandling.
Create a Become module named filehandling by running the following command from the filehandling directory.
go mod init filehandling I take a text file test.txt which volition be read from our Get plan filehandling.go. test.txt contains the following string
Hullo World. Welcome to file handling in Go. Here is my directory structure.
├── Documents │ └── filehandling │ ├── filehandling.get | ├── go.mod │ └── test.txt Allow's go to the lawmaking correct away. Create a file filehandling.get with the following contents.
package main import ( "fmt" "io/ioutil" ) func main() { data, err := ioutil.ReadFile("test.txt") if err != nada { fmt.Println("File reading fault", err) return } fmt.Println("Contents of file:", string(information)) } Please run this program from your local surroundings every bit it's not possible to read files in the playground.
Line no. 9 of the program to a higher place reads the file and returns a byte slice which is stored in data. In line no. 14 we convert data to a string and display the contents of the file.
Please run this program from the location where exam.txt is present.
If test.txt is located at ~/Documents/filehandling, so run this program using the post-obit steps,
cd ~/Documents/filehandling/ go install filehandling If you are non enlightened of how to run a Get programme, please visit https://golangbot.com/hullo-world-gomod/ to know more. If you want to learn more than almost packages and Become modules, please visit https://golangbot.com/go-packages/
This program will impress,
Contents of file: Hello World. Welcome to file handling in Go. If this plan is run from whatever other location, for example, effort running the programme from ~/Documents/
cd ~/Documents/ filehandling It will impress the following mistake.
File reading error open test.txt: no such file or directory The reason is Get is a compiled language. 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 exist run from any location. Since test.txt is non plant in the location from which the binary is run, the program complains that it cannot notice the file specified.
There are three ways to solve this problem,
- Using absolute file path
- Passing the file path as a command line flag
- Bundling the text file along with the binary
Let'south hash out them ane by one.
ane. Using accented file path
The simplest way to solve this problem is to pass the accented file path. I take modified the program and changed the path to an accented one in line no. nine. Please change this path to the absolute location of your examination.txt.
package master import ( "fmt" "io/ioutil" ) func principal() { information, err := ioutil.ReadFile("/home/naveen/Documents/filehandling/test.txt") if err != null { fmt.Println("File reading error", err) return } fmt.Println("Contents of file:", string(data)) } At present the programme can be run from any location and information technology volition impress the contents of test.txt.
For example, it will work even when I run it from my dwelling house directory
cd ~/Documents/filehandling go install cd ~ filehandling The program will print the contents of test.txt
This seems to be an easy way but comes with the pitfall that the file should exist located in the path specified in the programme else this method will fail.
ii. Passing the file path every bit a command line flag
Some other way to solve this problem is to pass the file path as a command line argument. Using the flag package, nosotros tin become the file path as input argument from the control line and then read its contents.
Let's first understand how the flag package works. The flag package has a String function. This function accepts 3 arguments. The first is the proper noun of the flag, second is the default value and the third is a brusk clarification of the flag.
Allow's write a small program to read the file proper name from the control line. Replace the contents of filehandling.go with the following,
bundle principal 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. viii of the program higher up, creates a string flag named fpath with default value test.txt and clarification file path to read from using the String function. This function returns the address of the string variable that stores the value of the flag.
flag.Parse() should be called earlier any flag is accessed by the program.
We print the value of the flag in line no. 10
When this program is run using the command
filehandling -fpath=/path-of-file/exam.txt we pass /path-of-file/test.txt equally the value of the flag fpath.
This program outputs
value of fpath is /path-of-file/examination.txt If the programme is run using just filehandling without passing whatsoever fpath, it volition print
value of fpath is test.txt since examination.txt is the default value of fpath.
Now that we know how to read the file path from the command line, let'southward go ahead and finish our file reading program.
package principal import ( "flag" "fmt" "io/ioutil" ) func main() { fptr := flag.String("fpath", "test.txt", "file path to read from") flag.Parse() information, err := ioutil.ReadFile(*fptr) if err != nil { fmt.Println("File reading error", err) return } fmt.Println("Contents of file:", string(data)) } The plan above reads the content of the file path passed from the command line. Run this programme using the control
filehandling -fpath=/path-of-file/test.txt Delight replace /path-of-file/ with the absolute path of test.txt. For example, in my case, I ran the command
filehandling --fpath=/abode/naveen/Documents/filehandling/examination.txt and the program printed.
Contents of file: Hullo World. Welcome to file treatment in Go. 3. Bundling the text file along with the binary
The above option of getting the file path from the command line is proficient simply there is an fifty-fifty better way to solve this problem. Wouldn't it be awesome if nosotros are able to package the text file along with our binary? This is what we are going to do side by side.
There are diverse packages that help the states achieve this. Nosotros will be using packr v2 considering it's quite simple and I have been using it for my projects without any issues.
The first step is to install the packr.
Type the following command in the command prompt from the ~/Documents/filehandling/ directory to install the bundle
cd ~/Documents/filehandling/ go get -u github.com/gobuffalo/packr/v2/... packr converts static files such equally .txt to .go files which are then embedded directly into the binary. Packer is intelligent enough to fetch the static files from disk rather than from the binary during development. This prevents the need for re-compilation during development when simply static files change.
A program volition make us sympathise things improve. Replace the contents of filehandling.become with the post-obit,
package main import ( "fmt" "github.com/gobuffalo/packr/v2" ) func main() { box := packr.New("fileBox", "../filehandling") data, err := box.FindString("test.txt") if err != aught { fmt.Println("File reading mistake", err) return } fmt.Println("Contents of file:", data) } In line no. 10 of the plan above, we are creating a New Box named box. A box represents a folder whose contents will be embedded in the binary. In this instance, I am specifying the filehandling folder which contains test.txt. In the adjacent line, we read the contents of the file using the FindString method and print information technology.
Run the plan using the following commands.
cd ~/Documents/filehandling go install filehandling and the program volition impress the contents of test.txt.
Since we are in the development stage now, the file will be read from disk. Try changing the contents of exam.txt and run filehandling over again. You lot tin encounter that the program prints the updated contents of exam.txt without the need for whatever recompilation. Perfect :).
Packr is also capable of finding the absolute path of the box. Because of this, the program will work from whatever directory. It doesn't need test.txt to be present in the electric current directory. Let's cd to a different directory and try running the plan once more.
cd ~/Documents filehandling Running the above commands likewise will print the contents of examination.txt.
Now let's move to the next pace and package exam.txt to our binary. We use the packr2 command to do this.
Run the packr2 control from filehandling directory.
cd ~/Documents/filehandling/ packr2 This control will search the source code for new boxes and generate Go files that contain our test.txt text file converted to bytes and this can exist bundled along with the Go binary. This command will generate a file main-packr.get and a bundle packrd. These two are needed to bundle the static file forth with the binary.
Afterward running the to a higher place command, compile and run the programme once more. The programme will print the contents of exam.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 first path element This might happen considering packr2 doesn't know that we are using Become Modules. If you get this mistake, endeavor setting go modules to on explicitly by running the command export GO111MODULE=on. Subsequently setting Become modules to on, the generated files take to exist cleaned and regenerated.
packr2 clean packr2 go install filehandling Now the contents of test.txt volition be printed and it is beingness read from the binary.
If you doubtfulness whether the file is served from within the binary or from disk, I suggest that you delete test.txt and run the command filehandling again. You tin see that test.txt'southward contents are printed. Awesome :D Nosotros take successfully embedded static files to our binary.
Reading a file in modest chunks
In the terminal department, we learned how to load an unabridged file into memory. When the size of the file is extremely large it doesn't brand sense to read the entire file into memory especially if you are running depression on RAM. A more optimal way is to read the file in small chunks. This can be done with the assistance of the bufio package.
Permit'southward write a program that reads our exam.txt file in chunks of iii bytes. Run packr2 clean to remove the files generated by packr in the previous section. You might also want to recreate test.txt in case you deleted it. Supercede the contents of filehandling.get with the post-obit,
package main import ( "bufio" "flag" "fmt" "log" "os" ) func main() { fptr := flag.String("fpath", "examination.txt", "file path to read from") flag.Parse() f, err := bone.Open(*fptr) if err != nil { log.Fatal(err) } defer func() { if err = f.Close(); err != nil { log.Fatal(err) } }() r := bufio.NewReader(f) b := brand([]byte, 3) for { n, err := r.Read(b) if err != zilch { fmt.Println("Fault reading file:", err) interruption } fmt.Println(string(b[0:n])) } } In line no. 15 of the program above, we open the file using the path passed from the command line flag.
In line no. 19, nosotros defer the file closing.
Line no. 24 of the programme higher up creates a new buffered reader. In the next line, nosotros create a byte slice of length and capacity 3 into which the bytes of the file will be read.
The Read method in line no. 27 reads up to len(b) bytes i.e up to 3 bytes and returns the number of bytes read. We store the bytes returned in a variablenorth. 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.
One time the end of the file is reached, it volition render an EOF error. The rest of the plan is direct forward.
If nosotros run the program to a higher place using the commands,
cd ~/Documents/filehandling become install filehandling -fpath=/path-of-file/test.txt the following will exist output
Hel lo Wor ld. We lco me to fil e h and lin g i north Yard o. Error reading file: EOF In the section, we will discuss how to read a file line by line using Go. This tin done using the bufio package.
Please replace the contents in test.txt with the following
Hi World. Welcome to file treatment in Go. This is the 2d line of the file. Nosotros have reached the end of the file. The post-obit are the steps involved in reading a file line by line.
- Open up the file
- Create a new scanner from the file
- Scan the file and read it line by line.
Replace the contents of filehandling.get with the post-obit
package main import ( "bufio" "flag" "fmt" "log" "bone" ) func primary() { fptr := flag.String("fpath", "test.txt", "file path to read from") flag.Parse() f, err := os.Open(*fptr) if err != nil { log.Fatal(err) } defer func() { if err = f.Close(); err != nil { log.Fatal(err) } }() s := bufio.NewScanner(f) for s.Browse() { fmt.Println(s.Text()) } err = s.Err() if err != goose egg { log.Fatal(err) } } In line no. 15 of the program above, we open the file using the path passed from the command line flag. In line no. 24, we create a new scanner using the file. The browse() method in line no. 25 reads the next line of the file and the cord that is read will be bachelor through the text() method.
Later Scan returns false, the Err() method will return any error that occurred during scanning. If the error is Stop of File, Err() will return nil.
If we run the program above using the commands,
cd ~/Documents/filehandling go install filehandling -fpath=/path-of-file/exam.txt the contents of the file will be printed line by line equally shown beneath.
Hello World. Welcome to file treatment in Get. This is the second line of the file. We have reached the end of the file. This brings us to the end of this tutorial. Hope you enjoyed it. Please leave your comments.
Side by side tutorial - Writing Files
Similar my tutorials? Please show your support by donating. Your donations volition help me create more awesome tutorials.
Source: https://golangbot.com/read-files/
0 Response to "Golang Os.create and Read File Return 0"
Postar um comentário