Last active
November 7, 2019 10:13
-
-
Save alessiosavi/d1f35e4db31109ffa961d847eb5d9af6 to your computer and use it in GitHub Desktop.
Tail a file in Golang
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"log" | |
"os" | |
"strings" | |
) | |
// JoinStrings use a strings.Builder for concatenate the input string array. | |
// It concatenate the strings among the delimiter in input | |
func JoinStrings(strs []string, delimiter string) string { | |
if len(strs) == 0 { | |
return "" | |
} | |
var sb strings.Builder | |
for i := range strs { | |
sb.WriteString(strs[i]) | |
sb.WriteString(delimiter) | |
} | |
return strings.TrimSuffix(sb.String(), delimiter) | |
} | |
const FILE string = `test.txt` | |
// BUFF_BYTE is how many bytes to move | |
// BUFF_BYTE can be positive or negative | |
const BUFF_BYTE int64 = -1 | |
// Whence is the point of reference for offset | |
// 0 = Beginning of file | |
// 1 = Current position | |
// 2 = End of file | |
const START_POS int = 2 | |
const N_STRING = 100 | |
func Tail(FILE string, BUFF_BYTE int64, START_POS, N_STRING int) string { | |
// list of strings readed | |
var stringsArray []string = make([]string, N_STRING) | |
// Contains the data | |
var buff []byte = make([]byte, -BUFF_BYTE) | |
if !(START_POS >= 0 && START_POS <= 2) { | |
log.Fatal("Wrong argument for Seek ...") | |
} | |
file, err := os.Open(FILE) | |
if err != nil { | |
log.Println("Unable to open file: " + FILE + " ERR: " + err.Error()) | |
log.Fatal(err) | |
} | |
defer file.Close() | |
// Go to end of file | |
_, err = file.Seek(BUFF_BYTE, START_POS) | |
if err != nil { | |
log.Println("Unable to seek to the end of the file: " + FILE + " ERR: " + err.Error()) | |
log.Fatal(err) | |
} | |
var linesReaded int = 0 | |
var nByte int // Number of byte readed | |
var stringBuffer string = "" // Contains the string until we don't found the new line | |
var iteration int64 = 1 | |
var n int64 = -BUFF_BYTE // Just for pass the first check | |
var lastPosition int64 | |
// Until we haven't read all the string | |
for linesReaded < N_STRING { | |
if n >= -BUFF_BYTE { | |
n, err = file.Seek(iteration*BUFF_BYTE, START_POS) | |
if err != nil { | |
log.Println("2) Error during read of file | Lines readed: ", linesReaded, " Byte readed: ", nByte, " Iteration: ", iteration) | |
log.Fatal(err) | |
} | |
lastPosition = n | |
} else { | |
// We have not enought data for fill the buffer, seeking to the start of the file | |
file.Seek(0, 0) | |
buff = make([]byte, lastPosition) | |
_, err = file.Read(buff) | |
if err != nil { | |
log.Println("3) Error during read of file | Lines readed: ", linesReaded, " Byte readed: ", nByte, " Iteration: ", iteration) | |
log.Fatal(err) | |
} | |
stringBuffer = string(buff) + stringBuffer | |
stringsArray[N_STRING-linesReaded-1] = stringBuffer | |
break | |
} | |
// Read the string related to the buffer | |
nByte, err = file.Read(buff) | |
if err != nil { | |
log.Println("1) Error during read of file | Lines readed: ", linesReaded, " Byte readed: ", nByte, " Iteration: ", iteration) | |
log.Fatal(err) | |
} | |
// Append the string in initial position | |
stringBuffer = string(buff) + stringBuffer | |
if strings.Contains(stringBuffer, "\n") { | |
stringsArray[N_STRING-linesReaded-1] = stringBuffer | |
stringBuffer = "" | |
linesReaded++ | |
// Continue to read, we have not found a new line and we have enough file to read | |
} | |
iteration++ | |
} | |
stringsArray = stringsArray[linesReaded-1:] | |
return JoinStrings(stringsArray, "") | |
} | |
func main() { | |
log.Println(Tail(FILE, BUFF_BYTE, START_POS, N_STRING)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment