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
	}
}