Проект: Чтение файла и подсчет байтов

Buffer, файл I/O, обработка сбоев ссылок и освобождение памяти.

Wave Foundation

готов

Создайте файл input.txt в рабочем каталоге, содержащий Wave, за которым следует одна новая строка LF. Тогда файл содержит 5 байт. В случае CRLF он содержит 6 байт; спецификация UTF-8 добавляет дополнительные байты. Проверьте кодировку файла редактора и окончания строк.

Сохраните программу как main.wave и запустите ее как wavec run main.wave из того же каталога. Относительные пути указываются относительно текущего рабочего каталога.

import("std::buffer::alloc")::{
    Buffer, buffer_init, buffer_free
};
import("std::fs::file")::{
    read_to_end
};

fun main() -> i32 {
    var data: Buffer;
    if (buffer_init(&data, 0) < 0) {
        return 1;
    }

    var count: i64 = read_to_end("input.txt", &data);
    if (count < 0) {
        println("read failed={}", count);
        buffer_free(&data);
        return 2;
    }

    var lines: i64 = 0;
    for (var i: i64 = 0; i < data.len; i += 1) {
        if (deref data.data[i] == 10) {
            lines += 1;
        }
    }

    println("bytes={} LF={}", count, lines);
    if (buffer_free(&data) < 0) {
        return 3;
    }

    return 0;
}

Результат выполнения:

bytes=5 LF=1

Действия и обязанности

read_to_end открывает и закрывает файл, но Buffer ответственность за освобождение лежит на вызывающей стороне. Отключается как для успешного, так и для неудачного чтения. Поскольку это данные, состоящие из нескольких байтов, мы не предполагаем, что это строка, заканчивающаяся на NUL.

LF Количество строк и количество строк, о которых думают люди, не всегда совпадают. Если последняя строка не содержит LF, она не включается в подсчет LF для этой программы. Также проверьте наличие ошибок чтения, переименовав файл. Конкретные номера ошибок могут различаться в зависимости от вашей среды.

Расширенные упражнения и комментарии

Если вы хотите обрабатывать очень большие файлы, замените его массивом фиксированного размера и итерацией io_read. Обрабатывает только положительные диапазоны возвращаемых значений и завершается на 0. Вы можете накапливать количество байтов и количество LF без необходимости хранить весь файл в памяти. Если вы открыли его самостоятельно, он также закроет дескриптор на любом пути выхода.

См. fs и io. · См. Buffer.

Следите за процессом обработки

  1. Инициализируйте бункер Buffer. Содержимого файла пока нет.
  2. read_to_end читает файл и увеличивает необходимое пространство.
  3. Если чтение прошло успешно, проверяются байты в диапазоне data.len.
  4. Всякий раз, когда мы встречаем значение 10 байта LF, мы увеличиваем lines.
  5. Распечатайте результаты и отпустите Buffer.

data.cap — это зарезервированное пространство для хранения, а data.len — допустимая длина данных. Если вы измените условие повтора на cap, байты, которых не было в файле, будут прочитаны, поэтому используйте len. count — это количество байтов, добавленных в этом вызове к read_to_end. Этот пример начинается с пустого Buffer, поэтому count и data.len равны.

Измените ввод для проверки

input.txt Содержание bytes LF причина
пустой файл 0 0 Нет байтов для чтения
Wave 4 0 Нет окончательного разрыва строки
Wave + LF 5 1 Данные до последнего LF
A + LF + B + LF 4 2 Считай два LF
Wave + CRLF 6 1 CR также равен 1 байту, но учитывается только LF.

Чтобы считать файлы без LF в последней строке строкой, добавьте 1 к количеству строк, если файл не пуст и последний байт не равен 10. Прежде чем вы сможете получить доступ к последнему элементу, вы должны сначала проверить, равен ли data.len 0.

Расширить до больших файлов

Текущий метод архивирования всего контента удобен для последующего перечитывания или извлечения данных. Если вам нужно только количество байтов и счетчик LF, имеет смысл повторно использовать буфер фиксированного размера.

В цикле io_read в примере Чтение файла в буфер фиксированного размера просто посчитайте LF по количеству возвращенных байтов. Его можно обработать с использованием памяти, равной размеру буфера, а не всей длине файла. Если чтение возвращает 0, все закончено; если он отрицательный, это ошибка.