Apakah ada bahaya dalam menulis byte mentah ke file? [Tutup]

12

Saya sedang mengerjakan masalah dalam Pemrograman Mutiara - khususnya, implementasi program yang mengurutkan file yang berisi paling banyak 10.000.000 bilangan bulat (Kolom 1, Masalah 3). Karena buku itu tidak menentukan bagaimana data harus disimpan dalam file, saya mempertimbangkan menyimpan integer sebagai byte mentah (ada beberapa kendala lain yang membuat byte mentah menjadi pilihan yang baik). Saya belum pernah bekerja di level rendah ini sebelumnya, jadi saya ingin tahu apakah ada sesuatu yang berbahaya yang harus saya perhatikan. Apakah saya perlu khawatir tentang tidak sengaja menggunakan semacam urutan end-of-file ketika saya sedang menulis byte mentah ke file, misalnya?

Edit:

Saya menyadari sekarang seberapa luas pertanyaan saya. Saya benar-benar memaksudkan masalah yang lebih berbahaya, seperti menimpa file-file lain di disk secara tidak sengaja. Maaf saya awalnya tidak jelas.

Drake Sobania
sumber
6
Perhatikan bahwa Memprogram Mutiara adalah buku yang sangat tua; Anda dapat dengan mudah membaca seluruh 10 ^ 7 bilangan bulat ke dalam memori pada mesin desktop modern, lakukan pengurutan, dan tulis kembali. Untuk mendapatkan poin asli dari bab itu, batasi jumlah yang Anda baca setiap saat hingga sepersekian dari jumlah total. Atau, tambah ukuran file menjadi sekitar 10 ^ 10 bilangan bulat.
Caleb
3
Sebenarnya, ketika saya mendengar kata "berbahaya", saya memikirkan hal-hal yang membuat PC saya meledak, menghapus rekening bank saya atau sesuatu seperti itu. Dan saya kira kemungkinan besar aman untuk mengasumsikan bahwa - selama program Anda tidak digunakan untuk mengendalikan Airbus atau pembangkit listrik - tidak ada yang benar-benar "berbahaya" akan terjadi ketika Anda mencoba apa yang ada dalam pikiran Anda.
Doc Brown
2
@delnan Bertahun-tahun yang lalu, ketika mitos karakter EOF sedang populer, saya ingat sistem perlindungan salinan yang didasarkan pada 'menyalin hingga karakter EOF' yang dilakukan oleh banyak program salinan waktu itu. Beberapa program akan memasukkan data tambahan yang akan mereka periksa setelah penanda EOF dari file teks terkait, tetapi sebelum akhir file dialokasikan. Program penyalinan tidak akan menyalin data tambahan yang memvalidasi instalasi yang bersih ... ahh ... nostalgia.
bahaya? Seperti pada "apakah komputer saya akan meledak jika saya melakukan ini"? Nggak.
jwenting

Jawaban:

11

Satu-satunya bahaya yang akan Anda hadapi adalah sedikit vs endianess besar (apakah byte paling signifikan atau paling tidak ditulis pertama). Namun jika Anda tetap berada di lingkungan yang sama tidak akan ada masalah. selain memastikan umum menulis / parsing pulang pergi.

Sistem file dirancang untuk menangani urutan byte apa pun.

aneh ratchet
sumber
2
+1 untuk baris terakhir. Saya tidak yakin masalah besar / kecil adalah satu - satunya masalah - OP misalnya bisa bingung tentang di mana batas-batas antara bilangan bulat. Tapi tetap saja jawabannya bagus.
Caleb
27

Tidak, sebenarnya ini adalah berapa banyak format file berfungsi. Contoh umum file biner seperti ini termasuk file gambar dan musik / audio.

Untuk menjaga integritas file dan data yang membacanya, pastikan untuk mengikuti panduan ini:

  • Selalu buka file (membaca atau menulis) menggunakan mode yang sama: teks atau biner. Perbedaan utama adalah mode teks peduli tentang baris baru, dan dapat "mematikan" karakter baris baru saat membaca file (tergantung pada perpustakaan tertentu yang digunakan). Mode teks juga dapat melakukan terjemahan Unicode yang kemungkinan akan tersedak pada data non-Unicode.
  • Saat membaca data non-string, pastikan untuk membaca menggunakan tipe data yang sama saat Anda menulis. Misalnya, jika empat byte pertama file adalah bilangan bulat deskriptif, pastikan untuk membaca dan menulis menggunakan metode yang mengambil / menyediakan bilangan bulat untuk memastikan itu diperlakukan secara konsisten. Tipe data yang sama mungkin memiliki ukuran yang berbeda pada mesin yang berbeda, dan pencampuran tipe data pada mesin yang sama juga dapat mengubah makna data (misalnya menafsirkan sedikit di tengah bilangan bulat yang lebih panjang sebagai bit tanda).
  • Endianness: jika perpustakaan yang Anda gunakan tidak menangani ini secara konsisten, Anda mungkin perlu menanganinya sendiri. Misalnya, Java selalu menggunakan urutan byte jaringan (big endian) untuk tipe multi-byte. C dan C ++ menggunakan apa pun yang diputuskan pelaksana perpustakaan, biasanya sama dengan prosesor (little endian pada Intel, big endian pada sebagian besar lainnya). Jika ini adalah latihan cepat pada satu sistem itu tidak penting, tetapi masih merupakan kebiasaan yang baik untuk memperhatikan ini dan kode di sekitarnya jika perlu.

Rincian spesifik akan bervariasi berdasarkan kerangka kerja, platform, dan bahasa, tetapi ini harus mencakup "gotchas" dasar dengan file I / O.


sumber
3
Poin tambahan untuk data non-string: pastikan Anda menggunakan jumlah byte yang konsisten untuk setiap jenis. Dalam C dan C ++ suatu intdapat antara 2 dan 8 atau lebih byte (benar-benar oktet).
Bart van Ingen Schenau
Itu secara implisit disertakan dengan poin kedua saya, misalnya 32 v. 64 bit integer. Mereka akan menjadi tipe data yang berbeda.
Anda mungkin ingin membuatnya eksplisit. Tidak jelas bahwa intpada dua mesin yang berbeda dapat dianggap tipe data yang berbeda.
Bart van Ingen Schenau
9

Selain semua gotchas yang telah disebutkan, jika Anda membuat format file biner baru daripada membaca dan menulis data dalam format yang sudah ada, sangat penting bahwa Anda menyertakan header file : blok data di awal file yang jelas mengidentifikasi format file dan mencatat setiap metadata yang mungkin diperlukan.

Header file yang baik mencakup setidaknya tiga hal:

  • " Angka ajaib ", paling tidak empat byte. Angka ajaib HARUS rfc2119 menjadi N byte pertama dalam file, HARUS tidak pernah digunakan untuk format file lain yang dapat Anda gali, dan HARUS berisi setidaknya satu byte yang bukan karakter ASCII yang dapat dicetak. Lihat spesifikasi PNG untuk cara mendesain angka ajaib yang sangat menyeluruh . Lihat kode sumber file(1)perintah untuk basis data angka ajaib yang ada yang komprehensif seperti yang mungkin Anda temukan.

    Maksud dari angka ajaib adalah memberi label yang jelas pada file, in-band, dengan formatnya. Jika Anda tidak menyertakan nomor ajaib, atau itu tidak hal pertama dalam file, Anda menjalankan resiko program misidentifying file Anda sebagai beberapa lainnya jenis file, yang mengarah ke hilangnya data, virus melarikan diri deteksi , dan seperti lainnya malapetaka.

  • Indikasi versi format file. Bahkan jika Anda berpikir Anda tidak akan pernah harus merevisi format file Anda secara drastis, buat dua byte berikutnya setelah angka ajaib menjadi 00 00dan mendokumentasikan bahwa ini adalah nomor versi 16-bit dalam beberapa endianness yang pasti (mana pun yang Anda suka, tetapi pilih satu dan menempel di seluruh file ) dan akan bertambah jika arti dari data selanjutnya berubah secara radikal. Masa depan Anda akan berterima kasih.

    (Spesifikasi PNG mengambil rute yang berbeda di sini, menetapkan bahwa format chunk dibekukan, dan bahwa semua perubahan di masa depan pada format tersebut akan mengambil bentuk tipe chunk baru. Itu juga valid, tetapi saya merekomendasikan pendekatan angka sulap sederhana + nomor versi untuk pemula hingga pemrosesan data biner. Orang-orang yang mendesain PNG menggunakan pengalaman puluhan tahun bersama dengan format gambar.)

  • Beberapa jenis mekanisme untuk menanamkan metadata sewenang-wenang dalam file. Ini bisa sesederhana memiliki dua byte berikutnya menjadi offset 16-bit dari ujung header ke awal data aktual, dengan segala sesuatu di antaranya ditafsirkan sebagai pasangan nilai kunci UTF-8 a la RFC 822 (yaitu, " Tag: value\n" - jika Anda memilih rute ini, saya sarankan untuk tidak melipat garis panjang). Sekali lagi, PNG jauh lebih pintar.

zwol
sumber
Tidak perlu membuat format file Anda sendiri ... hanya menyimpan data sebagai gambar. Anda mungkin perlu mengubah dimensionalitas (mis. 10k x 1k) sehingga akan didukung. Atau Anda bisa menggunakan FITS . Jika data Anda lebih kompleks daripada hanya satu array, Anda bisa menggunakan HDF , CDF atau NetCDF .
Joe
Saya sarankan agar tetap sederhana. 256 versi yang berbeda sudah cukup dan jika tidak, versi tambahan dapat dirancang sebagai subversi dari versi 255. Demikian pula untuk metadata, cukup menambahkannya ke dalam versi ketika mereka benar-benar diperlukan. @Joe Gambar ??? Anda menghindari kebingungan format potensial dengan membingungkan semua orang sebelumnya!
maaartinus
@maaartinus Membuat bidang versi dua byte memaksa perancang format untuk melakukan endianness di depan. Ruang untuk metadata harus selalu dalam versi 0 dari format biner, jika tidak, Anda berakhir dengan kludges mengerikan seperti ID3. Saya memang memiliki banyak simpati untuk logika spesifikasi PNG mengenai ekstensibilitas melalui tipe chunk baru alih-alih format versi gundukan. Namun, file terstruktur chunk membawa banyak kerumitan sendiri sehingga saya ragu untuk merekomendasikan mereka untuk kasus sederhana. Saya telah tergoda untuk merekomendasikan HDF sebagai format generik yang ini ditangani dengan banyak isu-isu ini sudah.
zwol
2

Arsitektur yang berbeda memiliki representasi yang berbeda untuk bilangan bulat. Risiko utama di sini adalah menyimpan representasi byte dari integer di mesin A dan kemudian mencoba membaca kembali dan menafsirkan konten sebagai integer di mesin B. Jika mesin A dan B memiliki ukuran yang berbeda untuk integer dan / atau endianness yang berbeda , Anda harus ll kemungkinan besar akan menyebabkan perilaku yang tidak terdefinisi (misalnya dalam C) atau pengecualian.

Karena ini hanyalah contoh pemrograman dan bukan program "nyata", ini bukan masalah. Jika ini adalah program nyata, menggulung format biner khusus aplikasi Anda sendiri biasanya bukan ide yang baik; ada solusi yang lebih baik, seperti SQLite atau format serialisasi berbasis string seperti JSON, YAML, XML, dll. Untuk nilai tunggal mengubahnya menjadi string sudah cukup; untuk daftar sederhana Anda dapat menyimpan satu string per baris dan cukup membagi input pada baris baru ketika Anda membacanya kembali.

Doval
sumber
Setuju secara umum, tetapi JSON atau XML akan secara signifikan meningkatkan ukuran file yang berisi 10 ^ 7 angka. Juga, mereka umumnya dibaca dan diurai sekaligus, tetapi bab yang bersangkutan membahas tentang pengurutan file yang berisi lebih banyak data daripada yang dapat Anda muat di memori yang tersedia.
Caleb
Itu tergantung pada apa yang Anda lakukan. Kadang-kadang hit kinerja SQL vs roll-Anda-sendiri adalah besar. Terakhir kali saya melakukannya saya memiliki catatan kecil dan ada kemungkinan besar saya ingin tetangga. Membaca blok yang lebih besar dari disk umumnya hampir tidak ada biaya jadi jika saya ingin satu catatan saya membaca 1000 ke dalam cache. Catatan saya hampir pasti bersebelahan, dengan SQL kepala disk akan memantul di semua tempat.
Loren Pechtel