Setelah membaca wiki base64 ...
Saya mencoba mencari tahu bagaimana rumusnya bekerja:
Diberikan string dengan panjang n
, panjang base64 akan menjadi
Yang mana : 4*Math.Ceiling(((double)s.Length/3)))
Saya sudah tahu bahwa panjang base64 harus %4==0
memungkinkan decoder mengetahui berapa panjang teks aslinya.
Jumlah maksimal padding untuk urutan dapat =
atau ==
.
wiki: Jumlah byte keluaran per byte input sekitar 4/3 (33% overhead)
Pertanyaan:
Bagaimana informasi di atas sesuai dengan panjang output ?
4 * n / 3
memberikan panjang yang tidak ditambahkan.Dan dibulatkan ke kelipatan 4 terdekat untuk padding, dan karena 4 adalah kekuatan 2 dapat menggunakan operasi logis bitwise.
sumber
$(( ((4 * n / 3) + 3) & ~3 ))
4 * n / 3
sudah gagal padan = 1
, satu byte dikodekan menggunakan dua karakter, dan hasilnya jelas satu karakter.Untuk referensi, rumus panjang encoder Base64 adalah sebagai berikut:
Seperti yang Anda katakan, encoder Base64 yang diberikan
n
byte data akan menghasilkan serangkaian4n/3
karakter Base64. Dengan kata lain, setiap 3 byte data akan menghasilkan 4 karakter Base64. EDIT : Sebuah komentar dengan benar menunjukkan bahwa gambar saya sebelumnya tidak menjelaskan padding; rumus yang benar adalahCeiling(4n/3)
.Artikel Wikipedia menunjukkan dengan tepat bagaimana string ASCII
Man
dikodekan ke dalam string Base64TWFu
dalam contohnya. Input string adalah 3 byte, atau 24 bit, ukuran, sehingga rumus dengan benar memprediksi output akan 4 bytes (atau 32 bit) panjang:TWFu
. Proses mengkodekan setiap 6 bit data menjadi salah satu dari 64 karakter Base64, sehingga input 24 bit dibagi dengan 6 hasil dalam 4 karakter Base64.Anda bertanya dalam komentar berapa ukuran pengkodean
123456
. Ingatlah bahwa setiap karakter dari string tersebut berukuran 1 byte, atau 8 bit (dengan asumsi pengkodean ASCII / UTF8), kami menyandikan 6 byte, atau 48 bit, data. Menurut persamaan, kami berharap panjang output menjadi(6 bytes / 3 bytes) * 4 characters = 8 characters
.Menempatkan
123456
ke dalam encoder Base64 menciptakanMTIzNDU2
, yang panjangnya 8 karakter, seperti yang kita harapkan.sumber
floor((3 * (length - padding)) / 4)
. Lihat intinya berikut ini .Integer
Umumnya kami tidak ingin menggunakan ganda karena kami tidak ingin menggunakan operasi floating point, pembulatan kesalahan, dll. Mereka tidak perlu.
Untuk ini adalah ide yang baik untuk mengingat bagaimana melakukan pembagian plafon:
ceil(x / y)
dalam ganda dapat ditulis sebagai(x + y - 1) / y
(sambil menghindari angka negatif, tetapi waspadalah terhadap melimpah).Dapat dibaca
Jika Anda menggunakan keterbacaan, tentu saja Anda juga dapat memprogramnya seperti ini (misalnya dalam Java, untuk C Anda dapat menggunakan makro, tentu saja):
Sebaris
Empuk
Kita tahu bahwa kita membutuhkan 4 blok karakter pada saat itu untuk masing-masing 3 byte (atau kurang). Jadi rumusnya menjadi (untuk x = n dan y = 3):
atau digabungkan:
kompiler Anda akan mengoptimalkan
3 - 1
, jadi biarkan saja seperti ini untuk menjaga keterbacaan.Belum dicetak
Yang kurang umum adalah varian tidak murni, untuk ini kita ingat bahwa setiap kita memerlukan karakter untuk setiap 6 bit, dibulatkan ke atas:
atau digabungkan:
namun kita masih dapat membaginya menjadi dua (jika kita mau):
Tidak dapat dibaca
Jika Anda tidak percaya kompiler Anda untuk melakukan optimasi akhir untuk Anda (atau jika Anda ingin membingungkan kolega Anda):
Empuk
Belum dicetak
Jadi di sinilah kita, dua cara perhitungan logis, dan kita tidak memerlukan cabang, bit-ops atau modulo ops - kecuali kita benar-benar menginginkannya.
Catatan:
sumber
Saya pikir jawaban yang diberikan melewatkan titik pertanyaan awal, yaitu berapa banyak ruang yang perlu dialokasikan agar sesuai dengan pengkodean base64 untuk string biner panjang n byte yang diberikan.
Jawabannya adalah
(floor(n / 3) + 1) * 4 + 1
Ini termasuk padding dan penghentian karakter nol. Anda mungkin tidak memerlukan panggilan lantai jika Anda melakukan aritmatika integer.
Termasuk padding, string base64 membutuhkan empat byte untuk setiap potongan tiga byte dari string asli, termasuk potongan parsial. Satu atau dua byte tambahan pada akhir string masih akan dikonversi menjadi empat byte dalam string base64 ketika padding ditambahkan. Kecuali jika Anda memiliki penggunaan yang sangat spesifik, yang terbaik adalah menambahkan padding, biasanya karakter sama dengan. Saya menambahkan byte ekstra untuk karakter nol di C, karena string ASCII tanpa ini sedikit berbahaya dan Anda harus membawa panjang string secara terpisah.
sumber
Berikut adalah fungsi untuk menghitung ukuran asli file Base 64 yang dikodekan sebagai String dalam KB:
sumber
Sementara semua orang berdebat rumus aljabar, saya lebih suka menggunakan BASE64 sendiri untuk memberi tahu saya:
525
710
Jadi sepertinya rumus 3 byte yang diwakili oleh 4 karakter base64 tampaknya benar.
sumber
(Dalam upaya untuk memberikan derivasi yang ringkas namun lengkap.)
Setiap byte input memiliki 8 bit, jadi untuk n byte input kita dapatkan:
Setiap 6 bit adalah byte keluaran, jadi:
Ini tanpa bantalan.
Dengan bantalan, kami membulatkannya hingga beberapa dari empat byte keluaran:
Lihat Divisi Bertingkat (Wikipedia) untuk kesetaraan pertama.
Menggunakan integer arithmetics, ceil ( n / m ) dapat dihitung sebagai ( n + m - 1) div m , maka kita mendapatkan:
Untuk ilustrasi:
Akhirnya, dalam kasus pengkodean MIME Base64, dua byte tambahan (CR LF) diperlukan per setiap 76 byte output, dibulatkan ke atas atau ke bawah tergantung pada apakah diperlukan baris baru yang mengakhiri.
sumber
Menurut saya formula yang tepat adalah:
sumber
Saya percaya bahwa ini adalah jawaban yang tepat jika n% 3 bukan nol, bukan?
Versi Mathematica:
Selamat bersenang-senang
GI
sumber
Implementasi sederhana dalam javascript
sumber
Untuk semua orang yang berbicara C, lihat dua makro ini:
Diambil dari sini .
sumber
Saya tidak melihat rumus yang disederhanakan dalam tanggapan lain. Logikanya tercakup tetapi saya menginginkan bentuk paling dasar untuk penggunaan yang disematkan:
CATATAN: Saat menghitung jumlah yang tidak ditambahkan, kami mengumpulkan divisi bilangan bulat yaitu menambahkan Divisor-1 yang merupakan +2 dalam kasus ini
sumber
Di windows - Saya ingin memperkirakan ukuran buffer berukuran mime64, tetapi semua rumus perhitungan yang tepat tidak bekerja untuk saya - akhirnya saya berakhir dengan rumus perkiraan seperti ini:
Ukuran alokasi string Mine64 (perkiraan) = (((4 * ((ukuran buffer biner) + 1)) / 3) + 1)
Jadi +1 terakhir - digunakan untuk ascii-nol - karakter terakhir perlu dialokasikan untuk menyimpan akhiran nol - tetapi mengapa "ukuran buffer biner" adalah +1 - Saya menduga ada beberapa karakter terminasi mime64? Atau mungkin ini masalah pelurusan.
sumber
Jika ada seseorang yang tertarik untuk mencapai solusi @Pedro Silva di JS, saya baru saja mem-porting solusi yang sama untuk ini:
sumber