File Operations in Golang

Cihan Ozhan
9 min readNov 8, 2021

File Operations in Golang

I wrote this code in 2016 but re-shared it for newbies.

Let’s get started!

GitHub : https://github.com/cihanozhan/golang-file-samples

Create an Empty File

package main

import (
"log"
"os"
)

var (
newFile *os.File
err error
)

func main() {
newFile, err = os.Create("demo.txt")
if err != nil {
log.Fatal(err)
}
}

Get File Info

package main

import (
"fmt"
"log"
"os"
)

var (
fileInfo *os.FileInfo
err error
)

func main() {
/*
Get File Info
*/
// Returns file information.
// Returns an error if the file doesn't exist.
fileInfo, err := os.Stat("demo.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println("File name: ", fileInfo.Name())
fmt.Println("Size in bytes: ", fileInfo.Size())
fmt.Println("Permissions: ", fileInfo.Mode())
fmt.Println("Last Modified: ", fileInfo.ModTime())
fmt.Println("Is Directory: ", fileInfo.IsDir())
fmt.Println("System interface type: %T\n", fileInfo.Sys())
fmt.Println("System info: %+v\n\n ", fileInfo.Sys())
}

Rename and Move a File

package main

import (
"log"
"os"
)

func main() {

/*
Rename and Move a File
*/

originalPath := "demo.txt"
newPath := "test.txt"
err := os.Rename(originalPath, newPath)
if err != nil {
log.Fatal(err)
}

// Try to do the migration with Rename()
}

Delete a File

package main

import (
"log"
"os"
)

func main() {

/*
Delete a file
*/

err := os.Remove("demo.txt")
if err != nil {
log.Fatal(err)
}
}

Open and Close Files

package main

import (
"log"
"os"
)

func main() {

/*
Open and Close Files
*/

file, err := os.Open("demo.txt")
if err != nil {
log.Fatal(err)
}
file.Close() file, err = os.OpenFile("demo.txt", os.O_APPEND, 0666)
if err != nil {
log.Fatal(err)
}
file.Close()

/*

OpenFile() second parameters types;

os.O_RDONLY : Only read
os.O_WRONLY : Only write
os.O_RDWR : Both read and write
os.O_APPEND : Append to end of file
os.O_CREATE : Create a file if it doesn't exist
os.O_TRUNC : Truncate file

// Can also be used more than once

-> os.O_CREATE|os.O_APPEND
-> os.O_CREATE|os.O_TRUNC|os.O_WRONLY
*/
}

Check if File Exists

package main

import (
"log"
"os"
)

var (
fileInfo *os.FileInfo
err error
)

func main() {

/*
Check if File Exists
*/
fileInfo, err := os.Stat("demo.txt")
if err != nil {
if os.IsNotExist(err) {
log.Fatal("File does not exist")
}
}
log.Println("File does exist. File information : ")
log.Println(fileInfo)
}

Check Read and Write Permissions

package mainimport (
"log"
"os"
)
var (
newFile *os.File
err error
)
func main() {
newFile, err = os.Create("demo.txt")
if err != nil {
log.Fatal(err)
}
}

Trucate a File

package mainimport (
"log"
"os"
)
func main() { /*
Truncate a File
A file must be truncated to 100 bytes.
If the file is less than 100 bytes, the content remains, the rest will be filled with empty bytes.
If the file is over 100 bytes, everything after 100 bytes is lost.
In both cases, the truncation must be performed over 100 bytes.
If the file to be cut is empty, the value zero is used.
*/
err := os.Truncate("demo.txt", 100)
if err != nil {
log.Fatal(err)
}
}

Rename and Move a File

package mainimport (
"log"
"os"
)
func main() { /*
Rename and Move a File
*/
originalPath := "demo.txt"
newPath := "test.txt"
err := os.Rename(originalPath, newPath)
if err != nil {
log.Fatal(err)
}
// Try to do the migration with Rename()
}

Delete a File

package mainimport (
"log"
"os"
)
func main() { /*
Delete a file
*/
err := os.Remove("demo.txt")
if err != nil {
log.Fatal(err)
}
}

Check Read and Write Permissions

package mainimport (
"log"
"os"
)
func main() { /*
Check Read and Write Permissions
*/
// For that; os.IsNotExist
file, err := os.OpenFile("demo.txt", os.O_WRONLY, 0666)
if err != nil {
if os.IsPermission(err) {
log.Println("Error : Write permission denied.")
}
}
file.Close()
// Read permissions test
file, err = os.OpenFile("demo.txt", os.O_RDONLY, 0666)
if err != nil {
if os.IsPermission(err) {
log.Println("Error : Read permission denied.")
}
}
file.Close()
}

Change Permissions, Ownership, and Timestamps

package main

import (
"log"
"os"
"time"
)

func main() {

/*
Change Permissions, Ownership, and Timestamps
*/

// Change Permissions (Linux tarzı)
err := os.Chmod("demo.txt", 0777)
if err != nil {
log.Println(err)

}

// Change Ownership
err = os.Chown("demo.txt", os.Getuid(), os.Getgid())
if err != nil {
log.Println(err)
}

// Change Timestamps
twoDaysFromNow := time.Now().Add(48 * time.Hour)
lastAccessTime := twoDaysFromNow
lastModifyTime := twoDaysFromNow
err = os.Chtimes("demo.txt", lastAccessTime, lastModifyTime)
if err != nil {
log.Println(err)
}
}

Hard Links and Symlinks

package main

import (
"fmt"
"log"
"os"
)

func main() {

/*
Hard Links and Symlinks
*/

err := os.Link("demo.txt", "demo_also.txt")
if err != nil {
log.Fatal(err)
}

fmt.Println("creating a sym")

// Create Symlink
err = os.Symlink("demo.txt", "demo_also.txt")
if err != nil {
log.Fatal(err)
}

// Lstat returns file information.
// Symlink doesn't work on Windows.
fileInfo, err := os.Lstat("demo_sym.txt")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Connection Info: %+v", fileInfo)

// Just change ownership of a symlink.
// But it does not change the ownership of the file it points to.
err = os.Lchown("demo_sym.txt", os.Getuid(), os.Getgid())
if err != nil {
log.Fatal(err)
}
}

Copy a file

package main

import (
"io"
"log"
"os"
)

func main() {

/*
Copy a file
*/

originalFile, err := os.Open("demo.txt")
if err != nil {
log.Fatal(err)
}
defer originalFile.Close()

newFile, err := os.Create("demo_copy.txt")
if err != nil {
log.Fatal(err)
}
defer newFile.Close()

bytesWritten, err := io.Copy(newFile, originalFile)
if err != nil {
log.Fatal(err)
}
log.Printf("Copied %d bytes.", bytesWritten)

// Process file content(commit)
// Free memory to disk(flush)
err = newFile.Sync()
if err != nil {
log.Fatal(err)
}
}

Seek Positions in File

package main

import (
"fmt"
"log"
"os"
)

func main() {

/*
Seek Positions in File
*/

file, _ := os.Open("demo.txt")
defer file.Close()

// How many bytes should the offset move?
// Offset can be negative(-) or positive(+)
var offset int64 = 5

// Where's the reference point for offset?
// 0 = Beginning of file
// 1 = Current position
// 2 = End of file
var whence int = 0
newPosition, err := file.Seek(offset, whence)
if err != nil {
log.Fatal(err)
}
fmt.Println("Just moved to 5: ", newPosition)

// Go back 2 bytes from current position
newPosition, err = file.Seek(-2, 1)
if err != nil {
log.Fatal(err)
}
fmt.Println("Just moved back two: ", newPosition)

// Find the current position by hetting the return value from Seek after moving 0 bytes.
currentPosition, err := file.Seek(0, 1)
fmt.Println("Current position: ", currentPosition)

// Go to the beginning of the file.
newPosition, err = file.Seek(0, 0)
if err != nil {
log.Fatal(err)
}
fmt.Println("Position after seeking 0,0: ", newPosition)
}

Write Bytes to a File

package main

import (
"log"
"os"
)

func main() {

/*
Write Bytes to a File
*/

file, err := os.OpenFile(
"demo.txt",
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
0666)
if err != nil {
log.Fatal(err)
}
defer file.Close()

byteSlice := []byte("Bytes!\n")
bytesWritten, err := file.Write(byteSlice)
if err != nil {
log.Fatal(err)
}
log.Printf("Wrote %d bytes.\n", bytesWritten)
}

Quick Write to File

package main

import (
"io/ioutil"
"log"
)

func main() {

/*
Quick Write to File
*/

err := ioutil.WriteFile("demo.txt", []byte("Hi!\n"), 0666)
if err != nil {
log.Fatal(err)
}
}

Buffer Operations

package main

import (
"bufio"
"log"
"os"
)

func main() {

file, err := os.OpenFile("test.txt", os.O_WRONLY, 0666)
if err != nil {
log.Fatal(err)
}
defer file.Close()

bufferedWriter := bufio.NewWriter(file)

bytesWritten, err := bufferedWriter.Write(
[]byte{65, 66, 67},
)
if err != nil {
log.Fatal(err)
}
log.Printf("Bytes written: %d\n", bytesWritten)

// Also you can use: WriteRune() andWriteByte()
bytesWritten, err = bufferedWriter.WriteString(
"Buffered string\n",
)
if err != nil {
log.Fatal(err)
}
log.Printf("Bytes written: %d\n", bytesWritten)

// Checking how much is stored while waiting for buffer.
unflushedBufferSize := bufferedWriter.Buffered()
log.Printf("Bytes buffered: %d\n", unflushedBufferSize)

// See the amount of buffer available.
bytesAvailable := bufferedWriter.Available()
if err != nil {
log.Fatal(err)
}
log.Printf("Available buffer: %d\n", bytesAvailable)

bufferedWriter.Flush()

// Undo changes made to the buffer that has not yet been written to the file with Flush().
bufferedWriter.Reset(bufferedWriter)

bytesAvailable = bufferedWriter.Available()
if err != nil {
log.Fatal(err)
}
log.Printf("Available buffer: %d\n", bytesAvailable)

// Resizes the buffer.
bufferedWriter = bufio.NewWriterSize(
bufferedWriter,
8000,
)

bytesAvailable = bufferedWriter.Available()
if err != nil {
log.Fatal(err)
}
log.Printf("Available buffer: %d\n", bytesAvailable)
}

Read Exactly n Bytes

package main

import (
"io"
"log"
"os"
)

func main() {

/*
Read Exactly n Bytes
*/
file, err := os.Open("demo.txt")
if err != nil {
log.Fatal(err)
}

byteSlice := make([]byte, 2)
numBytesRead, err := io.ReadFull(file, byteSlice)
if err != nil {
log.Fatal(err)
}
log.Printf("Number of bytes read: %d\n", numBytesRead)
log.Printf("Data read: %s\n", byteSlice)
}

Read At Least n Bytes

package main

import (
"io"
"log"
"os"
)

func main() {

/*
Read At Least n Bytes
*/

file, err := os.Open("demo.txt")
if err != nil {
log.Fatal(err)
}

byteSlice := make([]byte, 512)
minBytes := 8
numBytesRead, err := io.ReadAtLeast(file, byteSlice, minBytes)
if err != nil {
log.Fatal(err)
}
log.Printf("Number of bytes read: %d\n", numBytesRead)
log.Printf("Data read: %s\n", byteSlice)
}

Read All Bytes of File

package main

import (
"fmt"
"io/ioutil"
"log"
"os"
)

func main() {

/*
Read All Bytes of File
*/

file, err := os.Open("demo.txt")
if err != nil {
log.Fatal(err)
}

// Also you can use os.File.Read(), io.ReadFull(), ioutil.ReadAll() andio.ReadAtLeast()
data, err := ioutil.ReadAll(file)
if err != nil {
log.Fatal(err)
}

fmt.Printf("Data as hex: %x\n", data)
fmt.Printf("Data as string: &s\n", data)
fmt.Printf("Number of bytes read:", len(data))
}

Quick Read Whole File to Memory

package main

import (
"io/ioutil"
"log"
)

func main() {

/*
Quick Read Whole File to Memory
*/

data, err := ioutil.ReadFile("demo.txt")
if err != nil {
log.Fatal(err)
}
log.Printf("Data read: %s\n", data)
}

Use Buffered Reader

package main

import (
"bufio"
"fmt"
"log"
"os"
)

func main() {

/*
Use Buffered Reader
*/

file, err := os.Open("test.txt")
if err != nil {
log.Fatal(err)
}
bufferedReader := bufio.NewReader(file)

byteSlice := make([]byte, 5)
byteSlice, err = bufferedReader.Peek(5)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Peeked at 5 bytes: %s\n", byteSlice)

numBytesRead, err := bufferedReader.Read(byteSlice)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Read %d bytes: %s\n", numBytesRead, byteSlice)

myByte, err := bufferedReader.ReadByte()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Read 1 byte: %c\n", myByte)

dataBytes, err := bufferedReader.ReadBytes('\n')
if err != nil {
log.Fatal(err)
}
fmt.Printf("Read bytes: %s\n", dataBytes)

dataString, err := bufferedReader.ReadString('\n')
if err != nil {
log.Fatal(err)
}
fmt.Printf("Read string: %s\n", dataString)
}

Read with a Scanner

package main

import (
"bufio"
"fmt"
"log"
"os"
)

func main() {

/*
Read with a Scanner
*/

file, err := os.Open("test.txt")
if err != nil {
log.Fatal(err)
}
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanWords)

// Sonraki token'ı tara.
success := scanner.Scan()
if success == false {
err = scanner.Err()
if err == nil {
log.Println("Scan completed and reached EOF")
} else {
log.Fatal(err)
}
}

// Bytes() or Text()
fmt.Println("First word found:", scanner.Text())
}

Archive Files

package main

import (
"archive/zip"
"log"
"os"
)

func main() {

/*
Archive Files
*/

outFile, err := os.Create("test.zip")
if err != nil {
log.Fatal(err)
}
defer outFile.Close()

zipWriter := zip.NewWriter(outFile)

var filesToArchive = []struct {
Name, Body string
}{
{"test.txt", "String contents of file"},
{"test2.txt", "\x61\x62\x63\n"},
}

for _, file := range filesToArchive {
fileWriter, err := zipWriter.Create(file.Name)
if err != nil {
log.Fatal(err)
}
_, err = fileWriter.Write([]byte(file.Body))
if err != nil {
log.Fatal(err)
}
}

err = zipWriter.Close()
if err != nil {
log.Fatal(err)
}
}

Extract Archived Files

package main

import (
"archive/zip"
"io"
"log"
"os"
"path/filepath"
)

func main() {

/*
Extract Archived Files
*/
zipReader, err := zip.OpenReader("test.zip")
if err != nil {
log.Fatal(err)
}
defer zipReader.Close()

for _, file := range zipReader.Reader.File {
zippedFile, err := file.Open()
if err != nil {
log.Fatal(err)
}
defer zippedFile.Close()

targetDir := "./"
extractedFilePath := filepath.Join(
targetDir,
file.Name,
)

if file.FileInfo().IsDir() {
log.Println("Creating directory:", extractedFilePath)
os.MkdirAll(extractedFilePath, file.Mode())
} else {
log.Println("Extracting file:", file.Name)

outputFile, err := os.OpenFile(
extractedFilePath,
os.O_WRONLY|os.O_CREATE|os.O_TRUNC,
file.Mode(),
)
if err != nil {
log.Fatal(err)
}
defer outputFile.Close()

_, err = io.Copy(outputFile, zippedFile)
if err != nil {
log.Fatal(err)
}
}
}
}

Compress a File

package main

import (
"compress/gzip"
"log"
"os"
)

func main() {

/*
Compress a File
*/

outputFile, err := os.Create("test.txt.gz")
if err != nil {
log.Fatal(err)
}

gzipWriter := gzip.NewWriter(outputFile)
defer gzipWriter.Close()

_, err = gzipWriter.Write([]byte("Gophers rule!\n"))
if err != nil {
log.Fatal(err)
}

log.Println("Compressed data written to file.")
}

Uncompress a File

package main

import (
"compress/gzip"
"io"
"log"
"os"
)

func main() {

/*
Uncompress a File
*/

gzipFile, err := os.Open("test.txt.gz")
if err != nil {
log.Fatal(err)
}

gzipReader, err := gzip.NewReader(gzipFile)
if err != nil {
log.Fatal(err)
}
defer gzipReader.Close()

outfileWriter, err := os.Create("unzipped.txt")
if err != nil {
log.Fatal(err)
}
defer outfileWriter.Close()

_, err = io.Copy(outfileWriter, gzipReader)
if err != nil {
log.Fatal(err)
}
}

Temporary Files and Directories

package main

import (
"fmt"
"io/ioutil"
"log"
"os"
)

func main() {

/*
Temporary Files and Directories
*/

tempDirPath, err := ioutil.TempDir("", "myTempDir")
if err != nil {
log.Fatal(err)
}
fmt.Println("Temp dir created:", tempDirPath)

tempFile, err := ioutil.TempFile(tempDirPath, "myTempFile.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println("Temp file created:", tempFile.Name())

err = tempFile.Close()
if err != nil {
log.Fatal(err)
}
err = os.Remove(tempFile.Name())
if err != nil {
log.Fatal(err)
}
err = os.Remove(tempDirPath)
if err != nil {
log.Fatal(err)
}
}

Downloading a File Over HTTP

package main

import (
"io"
"log"
"net/http"
"os"
)

func main() {

/*
Downloading a File Over HTTP
*/

newFile, err := os.Create("courses.html")
if err != nil {
log.Fatal(err)
}
defer newFile.Close()

// HTTP GET request cihanozhan.com
url := "http://www.cihanozhan.com/courses"
response, err := http.Get(url)
defer response.Body.Close()

numBytesWritten, err := io.Copy(newFile, response.Body)
if err != nil {
log.Fatal(err)
}
log.Printf("Downloaded %d byte file.\n", numBytesWritten)
}

Good luck!
Cihan Özhan

--

--