1. Tep tren dia la byte
Hom nay ta se thuc hien mot “chuyen doi tu duy” quan trong: dung xem tep nhu “mot chuoi nam tren dia” va bat dau xem no dung nhu ban chat cua no — mot chuoi cac byte. Nghe co ve kho khan, nhung trong thuc te no giup ban tiet kiem hang gio “dau kho” khi lan dau thu “doc anh nhu van ban” va nhan duoc… noi cach khac, tho ca co nguon goc may moc.
Khi ban quen voi readText(), rat de tin rang tep “duoc tao tu cac chu cai”. Thuc ra, tep tren dia duoc tao tu byte — nhung con so nho duoc luu lien tiep. “Van ban” chi xuat hien khi ta thong nhat cach dien giai cac byte do thanh ky tu. Va chinh su thong nhat nay la ly do chu yeu khien cung mot tap byte doi khi tro thanh van ban binh thuong, doi khi lai thanh “mojibake/ky tu rac”.
Hay tuong tuong mot so do don gian:
flowchart LR
A[Tep tren dia] --> B[Byte: 0..255]
B --> C{Dien giai thanh van ban?}
C -- co --> D[Giai ma theo quy tac bang ma (encoding)]
D --> E[String: ky tu]
C -- khong --> F[Du lieu nhi phan: anh/nen/am thanh...]
Y chinh: chuoi la dien giai, con byte la thuc te.
2. Van ban va byte: khi nao readText() khong phu hop
Trong cac bai giang truoc, ta doc tep nhu van ban va moi thu deu on: ban doc tung dong, cat khoang trang, parse so — rat “dep”. Nhung ngay khi ban lay mot tep ma ve mat y nghia khong phai van ban (vi du PNG hoac ZIP), viec “doc thanh chuoi” se bien thanh mot dong hon don vo nghia. Day khong phai “loi cua Kotlin”. Day la loi trong y tuong cua chung ta: ta ap dung “ong kinh van ban” cho du lieu khong co van ban.
Tien loi khi ghi nho so sanh don gian sau:
| Thu ta dang cam tren tay | Thu nam trong tep tren dia | Doc bang gi | Vi sao |
|---|---|---|---|
| .txt, .csv, .json (thuong) | byte, nhung byte nay chinh la ky tu da duoc ma hoa | readText(), readLines() | ta muon nhan duoc ky tu |
| .png, .zip, .pdf, .mp3 | byte, nhung byte nay la cau truc cua dinh dang | readBytes(), stream | ta muon nhan du lieu nguyen ban |
Trong Kotlin/JVM co mot nhom mang rieng cho kieu nguyen thuy (nhu IntArray, DoubleArray va nhan vat chinh cua ta ByteArray). Day khong phai “Array<Byte> thong thuong”, ma la mot kieu dac biet hieu qua hon.
3. ByteArray — hop chua cho du lieu “tho”
Neu den gio ban song trong the gioi String, thi ByteArray la cua ngo vao the gioi “du lieu khong can dien giai”. Tin vui: hanh vi cua no rat giong cac mang ban da hoc. No co size, truy cap theo chi so qua [], va hoat dong rat tot trong vong lap. Tin khong vui: no khong co gang tien loi nhu “van ban”, nen ban can can than hon mot chut khi lam viec (nhung ta se lam duoc; ta da tung vuot qua null va try/catch roi — khong de bi doa dau).
Bat dau tu dieu don gian nhat: tao mot mang byte va xem ben trong co gi.
fun main() {
val bytes = byteArrayOf(1, 2, 3, 4)
println("size=${bytes.size}") // size=4
println("first=${bytes[0]}") // first=1
}
ByteArray ho tro danh chi so thong thuong (chi so bat dau tu 0) — day la quy tac chung cho mang trong Kotlin.
Bay gio la vi du voi mot mang “rong” co kich thuoc can thiet — day da giong voi bo dem (buffer) ma ta se som dung khi lam viec voi tep:
fun main() {
val buffer = ByteArray(8 * 1024) // 8 KB
buffer[0] = 10
buffer[1] = 20
println("bufferSize=${buffer.size}") // bufferSize=8192
println("first=${buffer[0]}") // first=10
}
Hay chu y phong cach: ta tao mang mot lan, sau do thay doi noi dung ben trong. Day la thoi quen quan trong cho I/O: tai su dung buffer thuong tot hon viec tao mang moi cho tung viec nho.
4. Mot vai diem tinh te: Byte, buffer va so sanh mang
Kieu Byte trong Kotlin: “nho va hoi kho tinh”
Truoc do ta co Int va Long, cu xu “dung nhu mong doi”: so lon, moi thu on. Byte la so nguyen nho co kich thuoc 1 byte, va trong Kotlin no la co dau: pham vi -128..127. Dieu nay doi khi lam nguoi moi bat ngo, boi vi “byte trong tep” thuong duoc hinh dung la 0..255. Nhung trong Kotlin, kieu Byte chinh la nhu vay.
Hay xem vi du:
fun main() {
val a: Byte = 120
val b: Byte = 127
println("a=$a") // a=120
println("b=$b") // b=127
}
Va bay gio — can than, minh hoa “vi sao khong the cu the nhat 200 vao Byte”:
fun main() {
val x = 200
val asByte: Byte = x.toByte()
println("x=$x") // x=200
println("asByte=$asByte") // asByte=-56
}
Day khong phai bug: do la cach ep kieu hoat dong, boi vi Byte ve mat vat ly khong the chua 200 trong pham vi cua no, va gia tri bi “cat bot” de vua 8 bit. Hien tai ban chua can di sau vao so hoc nhi phan — quan trong la nho quy tac thuc dung: byte rat nho, va khi chuyen doi, du lieu co the bi “mat”.
Buffer: ByteArray hoat dong nhu mot “cai xau”
Tu “buffer” nghe co ve nhu thu gi do thuoc lap trinh he thong, chi danh cho nguoi uong ca phe khong duong va viet driver. Thuc ra, buffer chi la mot mang kich thuoc co dinh ma ta dung nhu “cai xau”: muc mot muoi du lieu, xu ly, roi muc tiep.
Luc nay ta chua dong den file stream, nhung ta co the luyen y tuong “theo tung phan” tren mang thong thuong: gia lap viec sao chep du lieu theo tung khoi.
fun main() {
val source = byteArrayOf(10, 20, 30, 40, 50, 60, 70)
val chunkSize = 3
var i = 0
while (i < source.size) {
val end = minOf(i + chunkSize, source.size)
println("chunk: ${source.copyOfRange(i, end).contentToString()}")
i += chunkSize
}
// chunk: [10, 20, 30]
// chunk: [40, 50, 60]
// chunk: [70]
}
Diem quan trong o day khong nam o chinh ham copyOfRange, ma la y tuong: phan cuoi gan nhu luon nho hon kich thuoc thong thuong cua moi “muoi”. Dieu nay sau do se rat then chot khi doc tep: lan doc cuoi hiem khi vua tron 8 KB hay 16 KB — no bi “cat” boi diem ket thuc cua tep.
So sanh ByteArray: vi sao == so sanh sai thu ban muon
Co mot tinh huong kinh dien khien nguoi moi (va doi khi ca nguoi co kinh nghiem vao sang thu Hai) mac bay: so sanh mang. Truc giac khien ta muon lam the nay: “neu hai mang byte giong nhau, thi a == b phai la true”. Nhung mang co mot dac diem: toan tu == doi voi chung thuong mang nghia so sanh tham chieu, khong phai noi dung. Tức la “co phai cung mot doi tuong khong?” thay vi “du lieu co giong nhau khong?”.
Voi mang du lieu, gan nhu luc nao ta cung can so sanh theo noi dung — va de lam dieu do co contentEquals(...).
fun main() {
val a = byteArrayOf(1, 2, 3)
val b = byteArrayOf(1, 2, 3)
println(a == b) // false (usually)
println(a.contentEquals(b)) // true
}
Dieu nay cuc ky quan trong trong chu de tep: neu ban “copy tep”, kiem tra “ban copy co bang ban goc khong” chinh la kiem tra tung byte mot, khong phai “co tro den cung mot doi tuong khong”.
5. Nang cap nho cho ung dung thuc hanh: van ban → byte
Ta co gang phat trien mot ung dung theo tung buoc. Cho den luc nay, ta tu tin luu du lieu duoi dang van ban: tao chuoi bao cao va ghi ra tep. Hom nay ta them mot buoc nho nhung quan trong ve mat khai niem: hoc cach lay bieu dien dang byte cua du lieu. Day la su chuan bi cho lam viec nhi phan (copy, nen, v.v.), nhung chua can di sau vao cac chu de tiep theo.
Gia su ta co ham tao van ban bao cao (nhung ngay truoc ban co the viet bang StringBuilder hoac noi chuoi don gian). Bay gio ta se lam mot ham tra ve ByteArray.
fun reportText(total: Int): String {
return "Total expenses: $total"
}
fun reportBytes(total: Int): ByteArray {
val text = reportText(total)
return text.encodeToByteArray()
}
fun main() {
val bytes = reportBytes(total = 1200)
println("bytes=${bytes.size}") // bytes=20 (co the khac)
}
Dieu quan trong can hieu o muc do bai hoc hom nay:
String va ByteArray la hai “dang” du lieu khac nhau. Chuoi la ky tu (trong bo nho cua ngon ngu), con ByteArray la nhung byte cu the co the ghi “nguyen trang” hoac truyen vao cac API cap thap. Ham encodeToByteArray() va ham nguoc lai decodeToString() tao ra cay cau giua hai the gioi nay.
Va hay cho thay chuyen doi nguoc — chi de minh hoa rang byte co the la van ban neu ban chac chan do la byte cua van ban:
fun main() {
val original = "Hello, bytes!"
val bytes = original.encodeToByteArray()
val restored = bytes.decodeToString()
println(original) // Hello, bytes!
println(restored) // Hello, bytes!
}
Mot y can cuc ky can than: khong phai moi tap byte deu la van ban. Nhung byte nay la van ban vi chinh ta tao ra no nhu vay. Neu do la byte cua anh PNG, decodeToString() se giong nhu co gang doc ma vach bang mat thuong ma khong co may quet: ve mat hinh thuc thi co the, nhung y nghia thi “troi mat”.
6. Pipeline cho tuong lai: “du lieu → byte → luu tru”
De tranh nham lan ve sau (khi xuat hien tep that, stream va bufferization), nen co dinh truoc pipeline tu duy:
flowchart TD
A[Du lieu ung dung: so, chuoi, cau truc] --> B[Bao cao dang String / dinh dang]
B --> C[ByteArray: byte]
C --> D["Tep/nen/ban sao (sau)"]
Hom nay ta dung vung o buoc ByteArray. Cac bai tiep theo trong ngay se day cach doc/ghi nhung byte nay vao tep va di chuyen theo tung khoi — con muc tieu hien tai: dung nham van ban voi nhi phan va song binh tinh voi y tuong “byte la binh thuong”.
7. Loi thuong gap: nhan ra qua trieu chung
Loi 1: doc tep nhi phan bang readText() “chi de xem thu”.
Gan nhu luc nao cung ket thuc bang “rac” tren console va cam giac sai lam rang tep bi hong. Thuc ra chi co cach dien giai cua ta bi hong. Neu tep ve mat y nghia khong phai van ban, mo hinh nen la “byte”, tuc ByteArray, khong phai String.
Loi 2: nghi rang Byte chua duoc pham vi 0..255.
Trong Kotlin, Byte co dau, nen khi chuyen doi kieu nhu 200.toByte() ban se nhan so am. Day khong phai “hong”, ma la “khong vua”. Cach xu ly khong phai hoang so, ma la hieu dung kieu du lieu: Byte nho, va du lieu co the bi mat.
Loi 3: so sanh mang byte bang == roi ngac nhien.
Khi ban so sanh hai tap du lieu (dac biet neu sau nay ban kiem tra “ban copy tep co trung voi ban goc khong”), ban can so sanh theo noi dung: contentEquals. Neu khong, ban dang so sanh khong phai du lieu ma la “co phai cung mot doi tuong khong”, thu gan nhu khong bao gio la dieu ban muon.
Loi 4: tao mang moi o moi buoc, thay vi tai su dung buffer.
Ngay ca khi chua lam viec voi tep, cung thay ro rang xu ly “theo tung phan” gan nhu luon ham y tai su dung cung mot container (buffer). Neu sau nay ban doc du lieu lon ma lien tuc tao ByteArray moi, ban se cho chuong trinh tap the duc voi GC, va cho chinh minh mot cuoc phieu luu voi profiling.
Loi 5: co gang bien bat ky byte nao ve lai chuoi bang decodeToString().
Chuyen doi “byte ↔ chuoi” chi co y nghia khi byte thuc su la van ban da duoc ma hoa. Voi anh, tep nen va cac dinh dang nhi phan khac, hanh dong nay khong them y nghia — chi them nhieu.
GO TO FULL VERSION