Selain format .npy yang membawa metadata, NumPy memungkinkan kita menulis isi array sebagai byte mentah lewat ndarray.tofile() dan membacanya kembali dengan np.fromfile(). Format semacam ini berguna ketika lawan bicara adalah sistem lain yang sudah sepakat memakai tata letak byte tertentu — misalnya data hasil instrumen, berkas dari perangkat lunak C atau Fortran, atau protokol tertulis.
Harga yang harus dibayar: tanpa metadata, tidak ada yang mengingatkan dtype, bentuk, maupun urutan byte-nya. Bab ini mendemonstrasikan ketiga jebakan itu, lalu menutup dengan perbandingan ukuran biner versus teks sebagai bahan keputusan format.
tofile dan fromfile: Byte Mentah Tanpa Metadata #
tofile() menulis byte array apa adanya; fromfile() membaca byte tersebut menurut dtype yang kita sebutkan. Bentuk array tidak ikut tersimpan — hasil pembacaan selalu 1-D:
import numpy as np
m = np.arange(6, dtype=np.int32).reshape(2, 3)
m.tofile("matriks.bin")
c = np.fromfile("matriks.bin", dtype=np.int32)
print(c, c.shape)
print(c.reshape(2, 3))Output yang Dihasilkan:
[0 1 2 3 4 5] (6,)
[[0 1 2]
[3 4 5]]Mari kita bedah:
- Baris 3-4 (
tofile("matriks.bin")): dua belas byte ditulis — persis 6 elemen × 4 byte perint32— tanpa header apa pun. - Baris 5 (
np.fromfile(..., dtype=np.int32)): pembacaan mengembalikan array 1-D berbentuk(6,); informasireshape(2, 3)milik array asal tidak tercatat di berkas. - Baris 6-7: bentuk asli dapat dipulihkan hanya karena kita, pembacanya, masih ingat bentuknya — di sinilah letak tanggung jawab yang berpindah ke kita.
Dtype yang Salah, Isi yang Melenceng #
Karena tidak ada metadata, fromfile menataskan byte sesuai dtype yang diberikan, tanpa bisa memeriksa kebenarannya. Berkas int32 yang dibaca sebagai int64 akan dipasangkan dua elemen lama menjadi satu elemen baru:
import numpy as np
b = np.array([1, 2, 3], dtype=np.int32)
b.tofile("angka.bin")
print(np.fromfile("angka.bin", dtype=np.int64))Output yang Dihasilkan:
[8589934593]Penjelasan tiap bagian:
- Baris 3-4: tiga elemen
int32(12 byte) disimpan. - Baris 5 (
fromfile(..., dtype=np.int64)): pembaca menuntut 8 byte per elemen; dari 12 byte yang tersedia hanya satu elemen penuh yang terbentuk. - Baris keluaran: nilai
8589934593adalah gabungan byte1dan2dalam satu bilangan 64-bit — data terlihat sah, padahal isinya sudah lenceng. Kesalahan semacam ini tidak memunculkan error apa pun, sehingga paling berbahaya dikenali.
Endian: Urutan Byte Antar Platform #
Urutan byte (endianness) juga tidak dijaga oleh tofile. Array dengan dtype big-endian >i4 yang dibaca seolah little-endian <i4 menghasilkan nilai yang dirotasi byte-nya:
import numpy as np
a = np.arange(3, dtype=">i4")
a.tofile("besar.bin")
print(np.fromfile("besar.bin", dtype=">i4"))
print(np.fromfile("besar.bin", dtype="<i4"))Output yang Dihasilkan:
[0 1 2]
[ 0 16777216 33554432]Mari kita telaah:
- Baris 3 (
dtype=">i4"): tanda>berarti big-endian — byte terpenting disimpan lebih dulu, kebiasaan umum pada arsitektur dan berkas instrumen lama. - Baris 5: pembacaan dengan dtype yang cocok mengembalikan data persis aslinya.
- Baris 6: pembacaan dengan
<i4menghasilkan16777216untuk angka1— nilainya256 × 256 × 256, efek pemutaran urutan byte. Dtypes yang mencantumkan endian eksplisit adalah cara komunikasi yang benar dengan data lintas platform.
| Sumber data | Yang hilang tanpa metadata | Akibat bila diabaikan |
|---|---|---|
| bentuk array | tidak tersimpan | hasil selalu 1-D, perlu reshape manual |
| dtype | tidak tersimpan | data terbaca melenceng tanpa error |
| endianness | tidak tersimpan | nilai tertukar byte antar platform |
Perbandingan Ukuran Biner versus Teks #
Kapan memilih byte mentah atau .npy, dan kapan memilih teks? Ukuran berkas adalah salah satu faktornya. Untuk seribu nilai float64, kita bandingkan tiga format sekaligus:
import numpy as np
import os
data = np.arange(1000, dtype=np.float64)
data.tofile("data.bin")
np.savetxt("data.csv", data, fmt="%.2f", delimiter=",")
np.save("data.npy", data)
print("bin :", os.path.getsize("data.bin"), "byte")
print("csv :", os.path.getsize("data.csv"), "byte")
print("npy :", os.path.getsize("data.npy"), "byte")Output yang Dihasilkan:
bin : 8000 byte
csv : 6890 byte
npy : 8128 bytePenjelasan tiap bagian:
- Baris 4-6: array seribu
float64disimpan dalam tiga format — byte mentah, teks dua desimal, dan.npy. - Baris 7-9: byte mentah tepat
8000byte (1000 × 8); teksnya 6.890 byte karena angka kecil lebih pendek dari representasi binernya;.npyhanya menambah 128 byte header di atas data biner. - Kesimpulan ukuran: untuk data float, teks dan biner tidak selisih jauh pada angka ramping; teks membengkak justru pada angka dengan banyak desimal, sedangkan biner berukuran tetap terlepas dari nilainya.