fs и io: передача файлов и байтов
Описывает время жизни файла, полное чтение, частичную передачу и состояния после сбоя.
Wave Foundation
Выберите файл API.
Удобная функция std::fs::file получает путь и выполняет необходимое открытие и закрытие. Функции, возвращающие дескриптор, должны быть закрыты вызывающей стороной.
| декларация | Результаты успеха и меры предосторожности |
|---|---|
open_read(path: str) -> i64 |
Открыть дескриптор. Отрицательные числа являются ошибками. |
create(path: str) -> i64 |
Создайте или удалите существующее содержимое файла. Возвращает дескриптор владельца |
open_append(path: str) -> i64 |
Открыть или создать для добавления |
size(path: str) -> i64 |
Количество байтов. Отрицательные числа являются ошибками. |
read_into(path: str, dst: ptr<u8>, dst_cap: i64) -> i64 |
Количество байт во всем файле. Недостаток мощности – ошибка |
read_to_end(path: str, dst_buffer: ptr<Buffer>) -> i64 |
Добавьте файл после существующего Buffer и верните дополнительную сумму. |
write(path: str, src: ptr<u8>, len: i64) -> i64 |
Количество записанных байтов, заменяющих существующий контент |
append(path: str, src: ptr<u8>, len: i64) -> i64 |
Количество байт, добавленных в конец |
remove(path: str) -> i64 |
статус удаления. неудача отрицательная |
false из exists(path) сам по себе не может отличить отсутствующие файлы от ошибок разрешений. Обязательно проверьте фактический результат открытия, так как состояние может меняться между проверкой существования и открытием.
Низкий уровень I/O
std::io::fd
io_read(fd: i64, buf: ptr<u8>, len: i64) -> i64
io_write(fd: i64, buf: ptr<u8>, len: i64) -> i64
io_read_exact(fd: i64, buf: ptr<u8>, len: i64) -> i64
io_write_all(fd: i64, buf: ptr<u8>, len: i64) -> i64
io_close(fd: i64) -> i64
Положительный результат io_read — это количество прочитанных байтов, а 0 в запросе положительной длины — это EOF. io_write может быть записано меньше, чем требуется. Если требуется полная передача, используйте функцию exact/all. Тем не менее, мы не предполагаем, что сбой возвращает внешнее состояние, поскольку некоторые передачи могли произойти до ошибки.
io_read_exact является ошибкой, если EOF встречается до требуемой длины. read_into возвращает IO_ERR_NO_SPACE, если буфер заполнен и некоторые байты, возможно, уже записаны. Функция чтения не добавляет автоматически NUL в конец строки.
Buffer и обработка ошибок
В случае сбоя read_to_end восстанавливает исходный len, но его емкость и адрес данных могли измениться. Вызывающий объект должен освободить Buffer после успеха или неудачи. API записи файлов не гарантируют атомарную замену файлов.
Из Практика чтения файлов вы можете запустить программу из import для выпуска. Учитывайте различия в путях/разрешениях в Linux/macOS/Windows/FreeBSD и ограничениях доступных каталогов в WASI. Он не интерпретирует значение дескриптора напрямую как необработанный дескриптор другого OS.
Чтение больших файлов в маленькие буферы
Операции, которые не требуют размещения всего файла в памяти, могут обрабатываться с помощью фиксированных буферов и итераций чтения. Следующая программа печатает содержимое input.txt и подсчитывает общее количество прочитанных байтов. Сохраните по одному Wave и LF во входном файле.
import("std::fs::file")::{open_read};
import("std::io::fd")::{io_read, io_write_all, io_close};
import("std::io::consts")::{IO_STDOUT_FD};
fun main() -> i32 {
var descriptor: i64 = open_read("input.txt");
if (descriptor < 0) {
return 1;
}
var buffer: array<u8, 4>;
var total: i64 = 0;
while (true) {
var count: i64 = io_read(descriptor, &buffer[0], 4);
if (count < 0) {
io_close(descriptor);
return 2;
}
if (count == 0) {
break;
}
if (io_write_all(IO_STDOUT_FD, &buffer[0], count) < 0) {
io_close(descriptor);
return 3;
}
total += count;
}
if (io_close(descriptor) < 0) {
return 4;
}
println("bytes={}", total);
return 0;
}
Результат выполнения:
Wave
bytes=5
Емкость буфера равна 4, но последнее чтение может составлять 1 байт. Мы всегда передаем на выход фактическое значение count. Если вы запишите весь массив, даже старые, непрочитанные байты могут быть выведены.
Программа открыла descriptor из input.txt, поэтому закройте ее. Стандартный вывод не является новым ресурсом в этой функции, поэтому он не закрывается произвольно в конце примера.
Полное чтение и недостаточная емкость
read_into получает фиксированное пространство для хранения всего файла. Если места недостаточно, он автоматически усекается и безуспешно возвращает NO_SPACE.
import("std::fs::file")::{read_into};
import("std::io::consts")::{IO_ERR_NO_SPACE};
fun main() {
var data: array<u8, 2>;
var status: i64 = read_into("input.txt", &data[0], 2);
if (status == IO_ERR_NO_SPACE) {
println("destination too small");
}
}
Результат выполнения:
destination too small
Это не предполагает, что неудачное чтение вообще не изменило байт назначения. Не используйте его в качестве готового содержимого файла, подготовьте репозиторий большего размера или выберите метод streaming. Даже если вы сначала запрашиваете размер, окончательным решением будет фактический результат чтения, поскольку файл может меняться между запросом и чтением.
Разница между записью и добавлением файлов
write заменяет существующий контент, а append добавляется в конец. Количество байтов для хранения можно получить непосредственно из длины строки и передать. NUL в конце строки обычно не включается в содержимое текстового файла.
import("std::fs::file")::{write, append, size, remove};
import("std::string::len")::{len};
fun main() -> i32 {
var first: str = "Wave";
var second: str = " study";
if (write("output.txt", first as ptr<u8>, len(first) as i64) < 0) {
return 1;
}
if (append("output.txt", second as ptr<u8>, len(second) as i64) < 0) {
return 2;
}
println("bytes={}", size("output.txt"));
if (remove("output.txt") < 0) {
return 3;
}
return 0;
}
Результат выполнения:
bytes=10
В этом примере создается, заменяется и, наконец, удаляется output.txt в рабочем каталоге. Запускайте из каталога практики без существующих файлов. Для фактического редактора или программы хранения могут потребоваться отдельные политики хранения, такие как временные файлы и замена.
API Таблица выбора
| ситуация | выбрать |
|---|---|
| Считать небольшой весь файл в фиксированный буфер | read_into |
| Храните все содержимое, не зная размера | read_to_end и Buffer |
| Обрабатывайте контент по порядку, а не сохраняйте его целиком. | open_read + io_read повторить |
| Чтение записей фиксированной длины | io_read_exact |
| Передать всю строку байтов | io_write_all |
| Обработка уже открытых файлов | fd функция вместо функции пути |
После выбора функции проверьте, как изменятся буфер, расположение файлов и внешние данные в случае сбоя.