Reading a File Line by Line

Reading a file is very easy to do in Odin, but sometimes you just want to read the file line-by-line. Below we will show some approaches for this.

Iterator Approach

Reading the entire file at once and then split line by line with an iterator.

This is the preferred approach in general on most modern machines.

package line_by_line

import "core:os"
import "core:strings"

read_file_by_lines_in_whole :: proc(filepath: string) {
	data, ok := os.read_entire_file(filepath, context.allocator)
	if !ok {
		// could not read file
		return
	}
	defer delete(data, context.allocator)

	it := string(data)
	for line in strings.split_lines_iterator(&it) {
		// process line
	}
}

Buffered IO Approach

Reading the file a chunk at a time and then copy a string from the buffer.

This is useful for when you have a general io.Reader which cannot read everything at once.

import "core:bufio"

read_file_by_lines_with_buffering :: proc(filepath: string) {
	f, ferr := os.open(filepath)
	if ferr != 0 {
		// handle error appropriately
		return
	}
	defer os.close(f)

	r: bufio.Reader
	buffer: [1024]byte
	bufio.reader_init_with_buf(&r, {os.stream_from_handle(f)}, buffer[:])
	// NOTE: bufio.reader_init can be used if you want to use a dynamic backing buffer
	defer bufio.reader_destroy(&r)

	for {
		// This will allocate a string because the line might go over the backing
		// buffer and thus need to join things together
		line, err := bufio.reader_read_string(&r, '\n', context.allocator)
		if err != nil {
			break
		}
		defer delete(line, context.allocator)
		line = strings.trim_right(line, "\r")

		// process line
	}
}