Fungsi bytearray() Pada Python

Dalam bahasa pemrograman Python, kita sering berurusan dengan string ketika memproses teks. Namun, ketika kita mulai bekerja dengan data biner (seperti gambar, file PDF, atau informasi yang tidak selalu berbentuk teks), kita butuh suatu tipe data yang mampu menangani bytes secara lebih fleksibel. Pada Python, tersedia dua struktur data utama untuk tujuan ini, yaitu bytes dan bytearray.

Meskipun keduanya sama-sama digunakan untuk merepresentasikan kumpulan data biner, bytearray() memiliki kelebihan khusus karena ia bersifat mutable. Artinya, kita dapat mengubah nilai-nilai byte di dalamnya tanpa harus membuat objek baru. Sedangkan, bytes bersifat immutable. Artikel ini akan mengupas tuntas mengenai bytearray(), kegunaannya, serta contoh implementasinya pada berbagai kasus.

Apa Itu bytearray()?

Secara sederhana, bytearray() adalah tipe data yang merepresentasikan deretan byte seperti bytes, namun dapat diubah isinya (mutable). Python menyediakan fungsi bytearray() untuk membuat objek ini.

Perhatikan bahwa pada Python, byte string (objek bertipe bytes) menyimpan data yang hanya bisa dibaca atau diakses (read-only). Jika kita ingin memodifikasi data tersebut—misalnya mengubah byte pada indeks tertentu—maka kita tidak bisa melakukannya pada bytes secara langsung. Kita perlu menyalin data ke struktur lain atau melakukan konversi ke bytearray() agar bisa memodifikasinya.

Mengapa bytearray() Penting?

Cara Membuat bytearray

Python menyediakan beberapa cara untuk membuat bytearray:

  1. Mengonversi Tipe Lain ke bytearray:
    Kita bisa mengonversi string (dengan encoding tertentu) atau pun list/tuple yang berisi bilangan bulat 0-255 ke bytearray. Contoh:
    data_string = "Halo!"
    data_bytes = bytearray(data_string, 'utf-8')
    print(data_bytes)  # Output: bytearray(b'Halo!')
    
    data_list = [72, 97, 108, 111, 33]  # ASCII: H a l o !
    data_bytes2 = bytearray(data_list)
    print(data_bytes2)  # Output: bytearray(b'Halo!')
  2. Inisialisasi dengan Panjang Tertentu:
    Kita juga bisa membuat bytearray baru dengan ukuran tertentu. Ini bermanfaat jika kita ingin mencadangkan buffer kosong untuk suatu keperluan:
    buffer_kosong = bytearray(10) 
    # Membuat bytearray berukuran 10 byte, diinisialisasi dengan nilai b'\x00' (null byte)
    print(buffer_kosong)  # Output: bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
  3. Langsung dari Objek bytes:
    Jika kita sudah punya objek bytes dan ingin membuat versi yang bisa dimodifikasi, kita cukup melakukan konversi:
    data_bytes = b"Python Bytes"
    data_bytearray = bytearray(data_bytes)
    print(data_bytearray)  # Output: bytearray(b'Python Bytes')

Perbedaan Utama Antara bytes dan bytearray

Meski bytes dan bytearray sama-sama merepresentasikan data biner, perbedaan mendasar terletak pada sifat mutable dan immutable. Pada bytes, kita tidak dapat mengubah isi data secara langsung. Misalnya:

Contoh dengan bytes (Immutable)

immutable_bytes = b"Hello"
# immutable_bytes[0] = 72  # Akan error karena bersifat immutable

Contoh dengan bytearray (Mutable)

mutable_bytearray = bytearray(b"Hello")
mutable_bytearray[0] = 72  # Mengubah byte pertama ke ASCII 72 (yaitu 'H')
print(mutable_bytearray)   # bytearray(b'Hello')

Ketika kita memodifikasi mutable_bytearray[0] menjadi 72, sebetulnya nilainya sudah sama dengan 'H' sehingga mungkin tidak terlihat perubahan signifikan. Namun, jika kita mengubah nilainya menjadi 74, hasilnya akan berbeda:

mutable_bytearray[0] = 74  # ASCII untuk 'J'
print(mutable_bytearray)    # Output: bytearray(b'Jello')

Inilah mengapa bytearray sangat berguna: kita dapat memodifikasi data biner secara langsung, misalnya jika kita ingin memperbaiki satu byte yang rusak pada file biner, atau menimpa sebagian buffer dengan data baru tanpa membuat objek yang sama sekali baru.

Operasi Dasar pada bytearray

1. Mengakses dan Mengubah Elemen

Sama halnya dengan list, kita dapat mengakses byte pada bytearray menggunakan indeks. Contoh:

data = bytearray(b"ABC")
print(data[0])  # 65 (ASCII 'A')
data[1] = 90     # Mengubah 'B' (66) menjadi 'Z' (90)
print(data)      # bytearray(b"AZC")

2. Slicing

bytearray mendukung slicing seperti list atau string pada Python. Kita bisa mengambil sub-bagian dari bytearray:

data = bytearray(b"ABCDEFG")
slice_data = data[2:5]  
print(slice_data)  # bytearray(b"CDE")

# Kita juga bisa menimpa bagian tertentu melalui slicing
data[2:5] = b"XYZ"
print(data)        # bytearray(b"ABXYZFG")

3. Menambahkan dan Menggabungkan bytearray

Karena sifatnya yang mutable, ada beberapa cara untuk menambahkan data ke bytearray. Kita bisa menggunakan metode extend() atau operator +=:

data = bytearray(b"Hello")
data.extend(b" World")
print(data)  # bytearray(b'Hello World')

data += b"!"
print(data)  # bytearray(b'Hello World!')

4. Menghapus Elemen (Del)

Kita juga dapat menghapus beberapa byte sekaligus menggunakan del:

data = bytearray(b"Hello World!")
del data[5:]  
print(data)  # bytearray(b'Hello')

Contoh Penggunaan bytearray pada Berbagai Kasus

Berikut beberapa skenario yang sering melibatkan bytearray:

1. Membaca dan Memodifikasi File Biner

Salah satu penggunaan paling umum bytearray adalah ketika kita ingin melakukan operasi pada file biner. Misalnya, kita mungkin memiliki file gambar dan ingin mengganti byte tertentu untuk suatu keperluan khusus. Berikut contoh sederhana:

def ubah_file_biner(nama_file):
    # Membuka file dalam mode read-binary
    with open(nama_file, 'rb') as file:
        data_biner = file.read()

    # Konversi bytes ke bytearray agar bisa dimodifikasi
    data_bytearray = bytearray(data_biner)

    # Contoh: mengganti 10 byte pertama menjadi 0x00
    for i in range(10):
        data_bytearray[i] = 0

    # Menyimpan kembali perubahan ke file baru
    with open('file_biner_baru.bin', 'wb') as file_baru:
        file_baru.write(data_bytearray)

    print("Berhasil mengubah file biner dan menyimpannya sebagai file_biner_baru.bin")

Pada contoh di atas, kita membuka file biner dan membacanya sebagai bytes. Lalu mengubahnya menjadi bytearray dan memodifikasi sepuluh byte pertamanya menjadi 0x00. Terakhir, kita menuliskannya kembali ke file baru. Konsep ini sama bisa diterapkan untuk memodifikasi gambar, audio, atau dokumen PDF. Namun, tentunya kita harus berhati-hati agar tidak merusak struktur file sehingga tidak bisa dibaca lagi oleh aplikasi lain.

2. Membaca dan Mengirim Data Melalui Socket

Saat kita membuat aplikasi jaringan (misalnya server dan client) di Python, kita mungkin harus berurusan dengan data biner secara langsung melalui socket. Kita bisa membaca data dalam bentuk bytes, lalu memasukkannya ke bytearray untuk memudahkan perubahan. Contoh sangat sederhana:

import socket

def server_sederhana(host='localhost', port=12345):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((host, port))
        s.listen()
        print("Server listening on", (host, port))
        
        conn, addr = s.accept()
        with conn:
            print('Terhubung dengan', addr)
            while True:
                data = conn.recv(1024)  # Menerima data dalam bentuk bytes
                if not data:
                    break
                
                # Convert ke bytearray untuk memodifikasi
                data_mod = bytearray(data)
                # Contoh sederhana: Balik urutan byte
                data_mod.reverse()
                
                # Kirim kembali ke klien
                conn.sendall(data_mod)

def client_sederhana(host='localhost', port=12345):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((host, port))
        s.sendall(b"Hello World")
        
        data = s.recv(1024)
        print("Data diterima dari server:", data)

Pada contoh di atas, server menerima data dalam bentuk bytes dari klien, lalu mengonversinya menjadi bytearray untuk membalik urutannya sebelum dikirim balik. Dengan bytearray, kita bisa mengubah setiap byte sesuai kebutuhan, misalnya mengenkripsi, menambahkan header, atau melakukan operasi lainnya.

3. Memanipulasi Buffer untuk Streaming atau Frame Video

Dalam kasus pengolahan video atau media lainnya, biasanya ada konsep buffer yang memuat sekumpulan byte. Dengan bytearray, kita bisa memotong, mengganti, atau menimpa bagian-bagian tertentu dengan cepat. Misalnya, jika kita mendapatkan frame video sebagai kumpulan bytes, kita bisa langsung mengubah beberapa pixel atau menimpa segmen tertentu (walaupun untuk aplikasi nyata, kita mungkin lebih sering menggunakan perpustakaan seperti OpenCV).

4. Menciptakan String Terenkripsi atau Terkode

Kadang kita butuh mengolah string yang di-encode ke bentuk bytes. Misalnya kita memiliki string "Rahasia" yang dienkripsi sederhana, lalu kita simpan atau kirim. Dengan bytearray, kita bisa lebih mudah mengganti byte tertentu untuk dekripsi atau enkripsi manual. Contoh:

def enkripsi_sederhana(teks, kunci):
    """
    Menggabungkan tiap byte teks dengan kunci sederhana
    untuk menciptakan efek 'enkripsi' (XOR).
    """
    data = bytearray(teks.encode('utf-8'))
    for i in range(len(data)):
        data[i] ^= kunci
    return data

def dekripsi_sederhana(data, kunci):
    """
    Proses dekripsi sama dengan enkripsi karena XOR.
    """
    for i in range(len(data)):
        data[i] ^= kunci
    return data.decode('utf-8')

# Contoh penggunaan
plaintext = "Halo, ini rahasia!"
kunci = 25  # kunci XOR
enkripsi_data = enkripsi_sederhana(plaintext, kunci)
print("Data terenkripsi:", enkripsi_data)

dekripsi_teks = dekripsi_sederhana(enkripsi_data, kunci)
print("Teks setelah dekripsi:", dekripsi_teks)

Konsep di atas hanya ilustrasi sederhana untuk memamerkan bagaimana kita dapat memanipulasi byte dengan mudah. Teknik XOR ini jauh dari kata aman jika bicara enkripsi sesungguhnya, tetapi menunjukkan bahwa bytearray() memudahkan kita untuk melakukan operasi bitwise.

Konversi bytearray Menjadi Tipe Lain

Tentu kita bisa mengonversi kembali bytearray menjadi bytes kapan pun diperlukan. Misalnya, kita sudah selesai memodifikasi data, dan sekarang ingin mengirimnya ke fungsi tertentu yang hanya menerima bytes:

data_bytearray = bytearray(b"Hello")
data_bytes = bytes(data_bytearray)
print(type(data_bytes))  # 

Selain itu, jika kita yakin bahwa data biner yang kita punya sebenarnya adalah string yang di-encode (misalnya UTF-8), kita dapat mendekodekannya menjadi string Python biasa:

decoded_string = data_bytearray.decode('utf-8')
print(decoded_string)  # Menampilkan "Hello" jika isinya benar-benar data UTF-8

Penggunaan Lanjutan: memoryview dan bytearray

Python juga menyediakan memoryview untuk memanipulasi data biner tanpa menyalin buffer. Hal ini bisa berguna agar kita tidak boros memori jika kita hanya ingin melihat atau mengubah sebagian data. memoryview dapat diterapkan ke bytearray, bytes, maupun array.array.

Sebagai contoh, jika kita memiliki bytearray besar dan hanya ingin mengakses atau mengubah beberapa byte di tengah, memoryview memungkinkan kita bekerja dengan "jendela" ke bagian tertentu. Contoh:

data = bytearray(b"ABCDEFGH")
mv = memoryview(data)
# Akses byte kelima sampai ketujuh lewat memoryview
sub_mv = mv[4:7]  
# sub_mv sekarang mereferensikan data[4], data[5], data[6] 
# yg setara dengan b'EFG' pada awalnya
sub_mv[0] = 88  # ASCII 88 = 'X'
sub_mv[1] = 89  # ASCII 89 = 'Y'
print(data)     # bytearray(b"ABCDXYGH")

Terlihat bahwa ketika kita mengubah sub_mv, data asli juga ikut berubah, karena memoryview tidak membuat salinan.

Performa dan Pertimbangan Penggunaan

Kenapa kita tidak selalu menggunakan bytearray saja ketimbang bytes? Ada beberapa pertimbangan:

Namun, begitu kita berhadapan dengan kebutuhan untuk memodifikasi data biner, bytearray adalah pilihan yang tepat untuk efisiensi dan kemudahan.

Kesimpulan

Fungsi bytearray() di Python adalah alat yang sangat berguna ketika kita berhadapan dengan data biner yang perlu diubah-ubah. Berbeda dengan bytes yang tidak bisa dimodifikasi, bytearray memungkinkan kita mengakses tiap byte, menggantinya, menghapusnya, menambahnya, dan melakukan beragam manipulasi lain dengan mudah.

Dalam praktiknya, bytearray seringkali digunakan pada:

Memahami cara kerja bytearray juga membuka pintu untuk memahami tipe data Python lainnya yang bekerja di level rendah, seperti memoryview dan array.array. Di sisi lain, jika kita tidak perlu memodifikasi data, penggunaan bytes bisa jadi lebih disarankan karena sifatnya yang immutable—memberikan rasa aman tambahan dan potensi optimasi performa.

Dengan memanfaatkan bytearray secara bijak, kita dapat menangani berbagai skenario pengolahan data biner di Python dengan lebih efisien. Semoga artikel ini memberi gambaran yang jelas dan bermanfaat mengenai fungsi bytearray() serta penerapannya dalam situasi nyata. Selamat bereksperimen dengan data biner!


Baca Juga :