Gambar, rekaman audio, log sensor, dan berkas format proprietary (.png, .wav, .dat) semuanya disimpan sebagai byte mentah, bukan teks yang bisa dibaca manusia. Membaca berkas biner berarti memberi tahu MATLAB dua hal: berapa byte per nilai dan bagaimana nilai itu disusun menjadi deretan byte. Chapter ini membahas perangkatnya:

  • Membuka berkas biner dengan fopen mode 'rb'/'wb'
  • Membaca dan menulis dengan fread/fwrite beserta presisi 'uint8', 'int32', 'single', 'double'
  • Mengatur endianness 'ieee-le'/'ieee-be'
  • Berpindah posisi di dalam berkas dengan fseek, ftell, dan frewind

Aturannya: operasi biner memakai file identifier yang sama dengan operasi teks, tetapi modenya diberi akhiran 'b' — 'rb' untuk baca biner, 'wb' untuk tulis biner. Mekanismenya: fwrite(fid, nilai, presisi) mengubah nilai menjadi deretan byte sesuai presisi lalu menuliskannya ke posisi berkas saat ini; fread(fid, jumlah, presisi) membaca byte dan menyusunnya kembali menjadi angka. Kita mulai dengan presisi paling mentah, uint8 — satu byte per nilai:

matlab
fid = fopen('sapa.bin', 'wb');
fwrite(fid, uint8([72 101 108 108 111]), 'uint8');   % kode ASCII "Hello"
fclose(fid);

fid = fopen('sapa.bin', 'rb');
A = fread(fid, inf, 'uint8');
fclose(fid);
fprintf('jumlah byte: %d, isi: %s\n', numel(A), char(A.'));

Output yang Dihasilkan:

text
jumlah byte: 5, isi: Hello

Mari kita bedah baris-baris kode di atas:

  1. Baris 2 (fwrite(..., 'uint8')): lima angka 0–255 ditulis apa adanya — total lima byte; uint8 adalah satuan tulis-baca paling primitif.
  2. Baris 6 (fread(fid, inf, 'uint8')): argumen inf berarti baca sampai akhir berkas; hasilnya vektor kolom 5×1, sehingga char(A.') perlu transpose untuk membentuk teks baris.
  3. Baris 7 (char(A.')): lima kode ASCII (72=H, 101=e, 108=l, 111=o) dikonversi kembali menjadi teks.

Presisi Data: dari uint8 sampai double #

Masalah nyatanya: berkas biner menyimpan campuran tipe — header berisi hitungan kecil, payload berisi pecahan presisi tinggi. Mekanismenya: argumen ketiga fread/fwrite menentukan berapa byte per nilai dan cara nilai itu dienkode:

PresisiUkuranJangkauan / ketelitianKhas dipakai untuk
uint81 byte0 sampai 255byte mentah, piksel, kode ASCII
int324 byte±2,1 miliarhitungan, indeks, ukuran data
single4 byte~7 digit desimaldata sensor, hemat memori
double8 byte~15–16 digit desimaldefault MATLAB

Argumen kedua fread membatasi jumlah elemen — fread(fid, 3, 'double') membaca tepat tiga nilai double lalu berhenti, sekalipun berkas masih panjang. Secara default fread mengonversi hasil ke double; notasi 'int32=>int32' mempertahankan tipe aslinya.

matlab
fid = fopen('ukur.bin', 'wb');
fwrite(fid, int32([100000 -200000 123456]), 'int32');
fclose(fid);

fid = fopen('ukur.bin', 'rb');
B = fread(fid, 3, 'int32=>int32');
fclose(fid);
fprintf('ukuran berkas: %d byte, tipe hasil: %s\n', dir('ukur.bin').bytes, class(B));
fprintf('nilai: %d %d %d\n', B);
delete('ukur.bin');

Output yang Dihasilkan:

text
ukuran berkas: 12 byte, tipe hasil: int32
nilai: 100000 -200000 123456

Mari kita bedah baris-baris kode di atas:

  1. Baris 2 (fwrite(..., 'int32')): tiga bilangan ditulis masing-masing 4 byte — total berkas 12 byte, terverifikasi lewat dir('ukur.bin').bytes.
  2. Baris 6 ('int32=>int32'): tanda => memisahkan tipe sumber dan tipe hasil; tanpa notasi itu, B dikonversi ke double.
  3. Baris 8 (delete): berkas uji dibersihkan segera — kebiasaan yang dipakai juga oleh contoh.m.

Endianness: urutan byte little atau big #

Komputer menyimpan angka multi-byte dalam dua konvensi: little-endian (byte rendah duluan) atau big-endian (byte tinggi duluan). Mekanismenya: fopen menerima argumen ketiga — 'ieee-le' atau 'ieee-be' — yang menentukan urutan penafsiran. Angka uint16 bernilai 258 (heksadesimal 0x0102) menghasilkan byte 02 01 di little-endian; dibaca ulang sebagai big-endian, byte yang sama ditafsirkan 0x0201:

matlab
fid = fopen('endi.bin', 'wb', 'ieee-le');
fwrite(fid, uint16(258), 'uint16');     % tersimpan: 02 01
fclose(fid);

fid = fopen('endi.bin', 'rb', 'ieee-le');
le = fread(fid, 1, 'uint16');
fclose(fid);
fid = fopen('endi.bin', 'rb', 'ieee-be');
be = fread(fid, 1, 'uint16');
fclose(fid);
fprintf('uint16 258: LE=%d, dibaca BE=%d\n', le, be);
delete('endi.bin');

Output yang Dihasilkan:

text
uint16 258: LE=258, dibaca BE=513

Mari kita bedah baris-baris kode di atas:

  1. Baris 2 (uint16(258)): nilai 16-bit ditulis dengan urutan little-endian karena berkas dibuka dengan 'ieee-le'.
  2. Baris 10 ('ieee-be'): pembacaan memakai urutan big-endian atas byte yang sama — hasil melonjak ke 513, bukan karena galat pembulatan, melainkan karena salah kamus.
  3. Implikasi praktis: instrumen industri kerap menyimpan big-endian sedangkan PC modern little-endian; nilai yang terbaca “aneh dan terlalu besar” adalah gejala klasik ketidakcocokan ini.

Berpindah Posisi dengan fseek, ftell, dan frewind #

Berkas biner sering besar, dan kita hanya butuh sebagian isinya. Mekanismenya: ftell(fid) melaporkan posisi baca saat ini (offset dari awal berkas, dalam byte); fseek(fid, offset, asal) melompat — dengan asal bernilai 'bof' (awal berkas), 'cof' (posisi sekarang, offset boleh negatif), atau 'eof' (akhir berkas); frewind(fid) mengembalikan posisi ke nol:

matlab
fid = fopen('sensor.bin', 'rb');
fprintf('posisi awal : %d\n', ftell(fid));
fseek(fid, 8, 'bof');                   % lompat ke offset 8 (awal payload)
x = fread(fid, 2, 'single');            % dua nilai pertama
fprintf('offset 8    : %.2f %.2f\n', double(x));
fprintf('posisi baru : %d\n', ftell(fid));
frewind(fid);
y = fread(fid, 1, 'uint32');
fprintf('setelah rewind, magic: %u\n', y);
fclose(fid);

Output yang Dihasilkan:

text
posisi awal : 0
offset 8    : 24.50 25.00
posisi baru : 16
setelah rewind, magic: 305419896

Mari kita bedah baris-baris kode di atas (berkas sensor.bin dibuat oleh contoh.m):

  1. Baris 3 (fseek(fid, 8, 'bof')): posisi pindah ke offset 8 — tepat setelah header 4+4 byte — sehingga fread langsung mendarat di data.
  2. Baris 6 (ftell): setelah membaca dua single (2×4 = 8 byte), posisi berada di 16; angka ini bisa dipakai untuk memverifikasi alur baca.
  3. Baris 8 (frewind): pembacaan header diulang tanpa membuka berkas lagi — frewind murah dibanding fclose + fopen.

Pola Header dan Payload #

Hampir semua format biner nyata mengikuti satu resep: header pendek berisi identitas dan ukuran, disusul payload data. Identitas itu disebut magic number — nilai tetap yang ditulis pembuat berkas sebagai tanda tangan. PNG membuka berkasnya dengan 89 50 4E 47; berkas buatan kita memakai 0x12345678 (= 305419896). Alur baca yang aman:

Diagram tersebut membaca header lebih dulu, memvalidasi magic number, lalu baru menyentuh data — berkas salah format ketahuan sebelum memori terbuang. Jumlah data dari header juga menentukan berapa elemen yang dibaca fread, sehingga pembaca tidak menebak panjang payload:

matlab
% Penulisan
magic = uint32(305419896);                % 0x12345678
data  = single([24.5 25.0 26.25 24.75]);  % 4 nilai sensor
fid = fopen('sensor.bin', 'wb');
fwrite(fid, magic, 'uint32');             % header: 4 byte
fwrite(fid, int32(numel(data)), 'int32'); % header: 4 byte
fwrite(fid, data, 'single');              % payload: 4 x 4 byte
fclose(fid);

% Pembacaan
fid = fopen('sensor.bin', 'rb');
m = fread(fid, 1, 'uint32');              % magic (jadi double)
n = fread(fid, 1, 'int32');               % jumlah data
d = fread(fid, n, 'single');              % payload n elemen
fclose(fid);
fprintf('sensor.bin tertulis: %d byte\n', dir('sensor.bin').bytes);
fprintf('magic cocok: %d, n=%d\n', m == magic, n);
fprintf('data: %.2f %.2f %.2f %.2f\n', double(d));

Output yang Dihasilkan:

text
sensor.bin tertulis: 24 byte
magic cocok: 1, n=4
data: 24.50 25.00 26.25 24.75

Mari kita bedah baris-baris kode di atas:

  1. Baris 7 (fwrite(fid, magic, 'uint32')): magic number menempati 4 byte pertama — penanda bahwa berkas ini “punya kita”.
  2. Baris 8 (int32(numel(data))): panjang payload disimpan di header, sehingga pembaca tahu harus membaca berapa elemen tanpa membaca sampai habis.
  3. Baris 17-19 (fread berturut-turut): karena posisi baca bergerak maju otomatis, tiga panggilan berurutan mengambil header lalu data — tanpa satu fseek pun.

Biner vs Teks: Perbandingan Ukuran #

Empat angka 12 34 56 78 memakan 12 byte sebagai teks (satu karakter per digit) tetapi hanya 4 byte sebagai uint8:

text
teks 4 angka: 12 byte, biner uint8: 4 byte

Makin besar angkanya makin lebar jurangnya: 123456789 memakan 9 byte sebagai teks tetapi tetap 4 byte sebagai int32. Biner juga bebas dari dua masalah teks — delimiter dan locale desimal (tidak ada koma-vs-titik-koma, tidak ada baris header). Harganya: tanpa dokumentasi presisi dan endianness, berkas biner tidak terbaca.

Berkas contoh.m pada bagian bawah halaman merangkai seluruh siklus — menulis header + payload, membaca ulang, navigasi fseek/frewind, uji endianness, perbandingan ukuran teks vs biner, lalu pembersihan berkas demo — dalam satu script.

Ringkasan #

fopen dengan mode 'rb'/'wb' membuka jalur biner; fread/fwrite bekerja dengan presisi uint8 hingga double yang menentukan byte per nilai; endianness 'ieee-le'/'ieee-be' menjaga urutan byte lintas mesin; fseek/ftell/frewind memindahkan posisi baca. Pola magic number + jumlah data di header menjadikan berkas biner validasi-diri dan ringkas. Sekarang kita balik arah — menulis berkas data terformat untuk laporan dan pertukaran — di chapter Menulis File Data.