fs dan io: Transfer file dan byte

Menjelaskan masa pakai file, pembacaan penuh, transfer sebagian, dan status pasca-kegagalan.

Wave Foundation

Pilih file API

Fungsi kenyamanan std::fs::file menerima jalur dan melakukan pembukaan dan penutupan yang diperlukan. Fungsi yang mengembalikan deskriptor harus ditutup oleh pemanggil.

deklarasi Hasil sukses dan tindakan pencegahan
open_read(path: str) -> i64 Buka deskriptor. Angka negatif adalah kesalahan
create(path: str) -> i64 Membuat atau menghapus konten file yang ada. Mengembalikan deskriptor pemilik
open_append(path: str) -> i64 Buka atau buat untuk penambahan
size(path: str) -> i64 Jumlah byte. Angka negatif adalah kesalahan
read_into(path: str, dst: ptr<u8>, dst_cap: i64) -> i64 Jumlah byte di seluruh file. Kurangnya kapasitas adalah sebuah kesalahan
read_to_end(path: str, dst_buffer: ptr<Buffer>) -> i64 Tambahkan file setelah Buffer yang ada dan kembalikan jumlah tambahan
write(path: str, src: ptr<u8>, len: i64) -> i64 Jumlah byte yang ditulis menggantikan konten yang ada
append(path: str, src: ptr<u8>, len: i64) -> i64 Jumlah byte ditambahkan ke akhir
remove(path: str) -> i64 status penghapusan. kegagalan itu negatif

false dari exists(path) saja tidak dapat membedakan antara file yang hilang dan kesalahan izin. Pastikan untuk memeriksa hasil pembukaan sebenarnya, karena status dapat berubah antara pemeriksaan keberadaan dan pembukaan.

Tingkat rendah 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

Hasil positif dari io_read adalah jumlah byte yang dibaca, dan 0 dalam permintaan panjang positif adalah EOF. io_write boleh ditulis kurang dari yang diminta. Jika transfer penuh diperlukan, gunakan fungsi exact/all. Namun, kami tidak berasumsi bahwa kegagalan tersebut akan mengembalikan keadaan eksternal, karena beberapa transfer mungkin telah terjadi sebelum kesalahan tersebut.

io_read_exact adalah kesalahan jika EOF ditemukan sebelum panjang yang dibutuhkan. read_into mengembalikan IO_ERR_NO_SPACE jika buffer penuh, dan beberapa byte mungkin sudah ditulis. Fungsi baca tidak secara otomatis menambahkan NUL ke akhir string.

Buffer dan penanganan kesalahan

Jika gagal, read_to_end memulihkan lensa asli, namun kapasitas dan alamat datanya mungkin telah berubah. Penelepon harus membebaskan Buffer setelah berhasil atau gagal. API penulisan file tidak menjamin penggantian file atom.

Dari Latihan membaca file, Anda dapat menjalankan program dari import hingga rilis. Pertimbangkan perbedaan jalur/izin di Linux/macOS/Windows/FreeBSD dan batasan direktori yang dapat diakses di WASI. Itu tidak secara langsung menafsirkan nilai deskriptor sebagai pegangan mentah dari OS lainnya.

Membaca file besar ke dalam buffer kecil

Operasi yang tidak memerlukan seluruh file ditempatkan di memori dapat ditangani dengan buffer tetap dan iterasi baca. Program berikut mencetak konten input.txt dan menghitung jumlah total byte yang dibaca. Simpan satu Wave dan LF di file masukan.

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

Hasil eksekusi:

Wave
bytes=5

Kapasitas buffer adalah 4, namun pembacaan terakhir mungkin 1 byte. Kami selalu meneruskan count aktual ke output. Jika Anda menulis seluruh array, bahkan byte lama yang belum dibaca pun dapat dihasilkan.

Program membuka descriptor dari input.txt, jadi tutuplah. Output standar bukanlah sumber daya yang baru diperoleh dalam fungsi ini, sehingga tidak ditutup secara sembarangan di akhir contoh.

Bacaan penuh dan kapasitas tidak mencukupi

read_into menerima ruang penyimpanan tetap yang menampung seluruh file. Jika ruang tidak mencukupi, ia akan terpotong secara diam-diam dan mengembalikan NO_SPACE tanpa hasil.

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");
    }
}

Hasil eksekusi:

destination too small

Itu tidak berasumsi bahwa pembacaan yang gagal tidak mengubah byte tujuan sama sekali. Jangan menggunakannya sebagai konten file yang sudah jadi, siapkan repositori yang lebih besar atau pilih metode streaming. Meskipun Anda menanyakan ukurannya terlebih dahulu, hasil pembacaan sebenarnya adalah penilaian akhir, karena file dapat berubah antara kueri dan pembacaan.

Perbedaan antara menulis dan menambahkan file

write menggantikan konten yang ada dan append ditambahkan di akhir. Jumlah byte yang akan disimpan dapat diperoleh langsung dari panjang string dan diteruskan. Tanda NUL di akhir string biasanya tidak disertakan dalam konten file teks.

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

Hasil eksekusi:

bytes=10

Contoh ini membuat, mengganti, dan akhirnya menghapus output.txt di direktori kerja. Jalankan dari direktori latihan tanpa file yang ada. Editor atau program penyimpanan sebenarnya mungkin memerlukan kebijakan penyimpanan terpisah, seperti file sementara dan penggantian.

API Tabel pemilihan

situasi pilih
Baca seluruh file kecil ke dalam buffer tetap read_into
Simpan seluruh isinya tanpa mengetahui ukurannya read_to_end dan Buffer
Memproses konten secara berurutan daripada menyimpannya secara keseluruhan open_read + io_read ulangi
Baca catatan dengan panjang tetap io_read_exact
Mengirimkan seluruh string byte io_write_all
Menangani file yang sudah terbuka Fungsi fd alih-alih fungsi jalur

Setelah memilih fungsi, periksa bagaimana buffer, lokasi file, dan data eksternal berubah jika terjadi kegagalan.