Read and Write a File in Golang

Open a file

The os package allows a Go program to interface with files. The code below shows the pattern.

package main

import (
  "os"
  "log"
)

func main() {
  file, err := os.Open("file1.txt")  // O_RDONLY mode
  if err != nil {
    log.Fatal(err)
  }
  defer file.Close()
}

Open() opens a file with read only flag. There are several modes declared in the package.

const (
  O_RDONLY int = syscall.O_RDONLY // open the file read-only.
  O_WRONLY int = syscall.O_WRONLY // open the file write-only.
  O_RDWR   int = syscall.O_RDWR   // open the file read-write.
  O_APPEND int = syscall.O_APPEND // append data to the file when writing.
  O_CREATE int = syscall.O_CREAT  // create a new file if none exists.
  O_EXCL   int = syscall.O_EXCL   // used with O_CREATE, file must not exist
  O_SYNC   int = syscall.O_SYNC   // open for synchronous I/O.
  O_TRUNC  int = syscall.O_TRUNC  // if possible, truncate file when opened.
)

To open a file with other flags, OpenFile() has to be used. OpenFile() also needs another paramter, permission. A permission value is identical to *NIX systems i.e. rwxrwxrwx. Open() uses 0666 permission value.

// Open as read-only
file, err := os.Open("file.txt")
// Same as above
file, err := os.OpenFile("file.txt", os.O_RDONLY, 0666)
// Open as write-only
file, err := os.OpenFile("file.txt"), os.O_WRONLY, 0666)

fmt.Fscanf()

This is probably the easiest way to deal with text files. Chances are you are writing programs for a programming contest, and you have finished the logic but don’t know how to feed them inputs from files.

The fmt package comes with functions to deal with formatted I/O (stdio, string and file) analogous to C’s printf() and scanf(). The table below shows its function variants.

stdio string file
READ
scan Scan Sscan Fscan
scanf Scanf Sscanf Fscanf
scanln Scanln Sscanln Fscanln
WRITE
print Print Sprint Fprint
printf Printf Sprintf Fprintf
println Println Sprintln Fprintln
  • scan variants scan its input and assign it to its variables (arguments) respectively.
  • scanf variants are similar to ones in C. They scan for values according to its format string. The difference between Golang and C is that Golang treats a newline as a newline while C treats a newline as a space.
  • scanln variants are similar to scan variants except they scan until finding a newline.

  • print variants print each argument by its default format (%v) with a space separating each value.

  • printf variants are identical to ones in C. A format string is defined as the first argument. Following arguments fill out its value in the format string in order.
  • println variants are similar to the print variants except they put a newline at the end.

Here is an example.

// XXX: "input.txt" and "output.txt" must already exist
// XXX: Skip error handling to save space
inputFile, err := os.Open("input.txt")
defer inputFile.Close()
outputFile, err := os.OpenFile("output.txt", os.O_WRONLY, 0666)
defer outputFile.Close()
var a, b int
var itemCount int
itemCount, err = fmt.Fscanf(inputFile, "%d %d\n", &a, &b)
for itemCount > 0 && err == nil {
  fmt.Fprintln(outputFile, b, a)
  itemCount, err = fmt.Fscanln(inputFile, &a, &b)
}

This program swaps numbers in input.txt and writes to output.txt. In C, opening a file in write mode creates a new blank file. In Go, it is much more manual. O_WRONLY flag says “just point to the beginning of the file and start (over)writing”. The following statement has the same behavior as C.

outputFile, err := os.OpenFile("output.txt", 
  os.O_WRONLY | os.O_CREATE | os.O_TRUNC,
  0666)

File.Read()

This is a bare-feet approach to get to a file’s content. Every action is done in bytes via a buffer. For read, you open a file and store everything read to a buffer. For write, you open a file and put your buffer to a file.

// XXX: Skip error handling and file closing to save space
var buffer []bytes
buffer = make([]byte, 100)
inputFile, err := os.Open("input.txt")
n, err := file.Read(buffer)
fmt.Printf("(Bytes read: %v) %v\n", n, buffer)
outputFile, err := os.OpenFile("output.txt", os.O_WRONLY, 0666)
n, err = file.Write(buffer)
fmt.Printf("(Bytes written: %v) %v\n", n, buffer)

ReadAt() and WriteAt() are similar to its siblings but they can start with an offset.

Seek() moves the location pointed by a File variable relative to one of these positions.

SEEK_SET int = 0 // seek relative to the origin of the file
SEEK_CUR int = 1 // seek relative to the current offset
SEEK_END int = 2 // seek relative to the end

ioutil.ReadFile()

Instead of reading little by little in os.Read(), ioutil.ReadFile() reads a whole file into a buffer. err is nil if it successes.

ioutil.WriteFile() also does thing in bulk as ReadFile(). The function behaves like C’s fopen(filename, "w"). It creates a new file if it does not exist and truncates if it exists.

Another thing to notice about this family is that it uses a path string to access a file instead of a File variable.

import "io/ioutil"
// XXX: Skip error handling to save space
inputBytes, err := ioutil.ReadFile("input.txt")
err = ioutil.WriteFile("output.txt", inputBytes, 0666)

In the package, there are other functions to ioutil.TempDir() and ioutil.TempFile().

Scanner.Scan()

bufio package eases buffered operations. That means you just have to open a file for its functions. To read, you have to create a Scanner variable, which reads from a file and store in its private buffer.

// XXX: Skip error handling to save space
inputFile, err := os.Open("input.txt")
inputScanner := bufio.NewScanner(inputFile)
inputScanner.Split(bufio.ScanLines)  // Read until a newline for each Scan() (Default)
for inputScanner.Scan() {
  fmt.Println(inputScanner.Text())   // get the buffered content as string
  fmt.Println(inputScanner.Bytes())  // same content as above but as []byte
}

Writer is a bit decorated []byte buffer. You have to Flush() a buffer to a file mannually. It can be used in combination with fmt.Fprintf().

// XXX: Skip error handling to save space
outputFile, err := os.OpenFile("output.txt", os.O_WRONLY, 0666)
defer outputFile.Close()
outputWriter := bufio.NewWriter(outputFile)
// fmt.Printf("There are %v bytes available", outputWriter.Available())
fmt.Fprintf(outputWriter, "Hello World\n")  // formatted write to the buffer
// fmt.Printf("There are %v bytes available", outputWriter.Available())
outputWriter.WriteString("============\n")  // another way to write to the buffer
// fmt.Printf("There are %v bytes used", outputWriter.Buffered())
outputWriter.Flush()  // Finally write to the file

References

Setting Atom for Golang on Windows

Golang is another programming language I recently become addicted to. I am a C programmer, and Golang is very similar to it but offers more high-level language’s functionalities e.g. built-in complex structs (slice, map), OOP (kind of) and concurrency (goroutine, channel). This shortens development time like one using Python yet has better performance.

I just bought a laptop, and it is pre-installed with Windows. I’m waiting for Ubuntu 16.04 to come out. That means I have to be nice with Windows for the time being. I enrolled a Golang course on Pluralsight. It teaches how to setup an environment using Atom with Gulp.js on Windows. Gulp.js is used to look for changes made under a working project’s directory. Any change made triggers gocode (autocompletion server) to update its database. It works nicely in their videos, but too bad that I couldn’t do it. So, I looked up the internet and found a way to ditch Gulp.js while functioning the same. And here, this article tells how I get along with Go on Atom on Windows.

Setup Atom Editor

  1. Get Atom editor – It’s free!
  2. Get plugins
    • go-plus – adds extra Atom functionality for the go language
    • atom-terminal – open a command prompt in the current file’s directory (`alt-shift-t`)
  3. Create a project root directory e.g. `C:\Users\pipat\Desktop\hello-go`
  4. Configure go-plus’s `%GOPATH%` environment variable to the project root directory
  5. Get Golang tools
    • From the menu bar `Packages > Go Plus > Get Missing Tools`
      • This downloads source code and install it under `%GOPATH%`

This slideshow requires JavaScript.

  1. Configure gocode to watch for changes
    1. Open a cmd (`alt-shift-t`)
    2. Navigate to your `%GOPATH%` directory
    3. Enter `bin\gocode.exe set autobuild true`

gocode-set-autobuild

After these steps, your Atom has Golang autocompletion and linting features. Be sure to change GOPATH in go-plus every time you switch to another working directory.

Continue reading

My minion is a home tutor and a drummer

It has been 2 weeks since the last post. I’m a bit disappointed that my minion did no progress over this period. He did not manage to finish any reading I asked him.

When I asked him “What is the current status?“.

The only answer I got was “I am reading one of our lab graduated student’s thesis“.

Then I asked him “Have you find any part you are interested in?“.

He said “No, I haven’t read that much.“.

Part of this is that I haven’t put pressure on him since it is only the 1st month of this academic year.

He showed up in the office about 2 times a week for a short period, but I don’t mind about office hour as long as he can finish assignments. After a bit of leisure talking with him, I learned that he is a home tutor to a senior high school student preparing for an entrance examination.

He is also a member of Titech folk song club. He is a drummer, and he is doing this role very well. He is going to perform with a singer from a popular band with his other club members in July (he told me in Japanese. not sure if I understand it correctly).

My music skill is comparable to banana.

DIY Signal Handler by Sigaction

In Linux environment, a program is capable of listening and generating signals. A signal is used to inform that an event happened, and it needs attention.The list of signals can be found here. The most simplest example to this is SIGINT, interrupt signal. This signal is sent when you press to quit your program you ran in a terminal. Terminating the program is SIGINT’s default signal handler. This signal handler can be overridden. In the previous post, I showed you an example how to change it to your version by using sigaction function.

In this post I’m going to instruct how to use it.

Continue reading

A Simple Linux Signal Example

I studied about utilizing signals offered by Linux operating system. It allows you to make an event-driven program. You can overwrite the default behavior of Ctrl+C in your program to do something else instead of killing the program.I find it easy and very straightforward. I will give an example here and explanation in the next post.

An this is my inspiration.

And this is the example.

// Hey apple - Linux signal programming example
#include <stdio.h>
#include <signal.h>

unsigned int count_sigint = 0;

void my_sigaction_handler(int signum, siginfo_t* siginfo, void* ucontext) {
    printf("Hey, midget apple!\n");
    count_sigint++;
}

int main(int argc, char* argv[]) {
    struct sigaction my_sigaction;
    my_sigaction.sa_handler = SIG_DFL;
    // Defines a signal handling function for my_sigaction
    my_sigaction.sa_sigaction = my_sigaction_handler;
    sigfillset(&my_sigaction.sa_mask);
    my_sigaction.sa_flags = SA_SIGINFO;
    // Ctrl + c fires SIGINT signal. 
    // Overwrite SIGINT handling behavior by my_sigaction
    sigaction(SIGINT, &my_sigaction, NULL);
    while (count_sigint < 5) {
        printf("Hey, apple!\n");
        sleep(1);
    }
    return 0;
}

Continue reading

Got Temp Root on AQUOS PHONE Xx Softbank 203SH

The story is long, click here to teleport to the guide! It had been very long time until I am finally freed from 2-year carrier contract from Softbank. Phones in Japan are not sim-free i.e. they are tied with a carrier either Docomo, Softbank or au. When you buy a phone, you instantly signed a 2-year contract with them (breaking a contract from them costs you 10,000 Yen). Phones themselves are not expensive because of this long-term contract. It gets huge amount of discount. But, that is just a deceiving trick. The true cost lies in the carrier fee. The fee alone costs about 6,000 Yen/mo. In my case, I had paid 8,000 Yen/mo, because the discount didn’t fully cover my phone price tag. Hence, if I broke a phone and bought a new one, I had to pay 8,000 + (3,000~) Yen/mo. This number is pretty big to me. In April and October, they are seasons for のりかえ or changing a carrier. People usually make a contract in these months, so after 2 years their contract will end in the same month. There is one month to decide whether to continue with the same carrier or changing to another. Most people change to other carriers because of larger discount from のりかえ campaign (Docomo, Softbank, au).

Continue reading

My New Minion

Last Monday, out of the blue, I just got assigned from my professor a new student to my care.

He is a 4th year bachelor student. He entered my lab, because he failed to get into his (all 3) labs of choice. This week I still havn’t known him much. He came to lab for only short period per time. Nevertheless, I will try to develop relationship with him overtime. At least I want to make sure that the working experience with me is better than what I’ve received from my professor.

Our lab is doing about customizing CPUs. We model a CPU by C language and (high-level) synthesize it into Register-Tranfer Level. The RTL is then either burnt to a FPGA chip or fabricate in silicon. These days we are baking a general purpose CPU like the one you are using now. We plan to have Linux running on it.

So, I expect before graduation he will learn about

  1. Processes in creating a CPU and challenging tasks in each level
  2. Various CPU/GPU/FPGA architectures
  3. Linux internals
  4. Git (srsly, this should be taught in Programming 101)

DSC_0153

Today I assigned him to skim through conference presentations and tell me which titles he is interested in. It might shed some light on which tasks I should give to let him develop his skills for his research theme. Hopefully his choices will overlap some of my learning expectation above.

Although this is not a place he wants to be in in the beginning, I found him eager in learning. I met him in a logic synthesis seminar by a professor from UC Berkeley, and he started reading through these thick conference books right away. This gives me hope that I can train him into a skillful engineer.

I will try to update his progress, my mentoring experience and assignments here every week. Stay tuned!