Programavimas

„Base64“ kodavimas ir dekodavimas „Java 8“

„Java 8“ atsimins daugiausia dėl to, kad į „Java“ įdiegė „lambdas“, srautus, naują datos / laiko modelį ir „Nashorn JavaScript“ variklį. Kai kurie taip pat prisimins „Java 8“, nes pristatė įvairias mažas, bet naudingas funkcijas, tokias kaip „Base64“ API. Kas yra „Base64“ ir kaip naudoti šią API? Šis įrašas atsako į šiuos klausimus.

Kas yra „Base64“?

Pagrindas64 yra dvejetainio teksto kodavimo schema, vaizduojanti dvejetainius duomenis spausdinamu ASCII eilutės formatu, išverčiant juos į radix-64 vaizdą. Kiekvienas „Base64“ skaitmuo reiškia tiksliai 6 dvejetainių duomenų bitus.

„Base64“ prašymas pateikti komentarų dokumentus

Pirmą kartą „Base64“ buvo aprašytas (bet nepavadintas) dokumente RFC 1421: „Internet Enail Enhancement for Internet Electronic Mail“: I dalis: Pranešimų šifravimo ir autentifikavimo procedūros. Vėliau jis buvo oficialiai pristatytas kaip „Base64“ RFC 2045: Daugiafunkciniai interneto pašto plėtiniai (MIME): Pirmoji dalis: interneto pranešimų elementų formatas ir vėliau peržiūrėtas RFC 4648: „Base16“, „Base32“ ir „Base64“ duomenų kodavimai.

„Base64“ naudojama siekiant išvengti duomenų modifikavimo, kai jie gabenami per informacines sistemas, pvz., El. Paštą, kurie gali būti ne 8 bitų švarūs (jie gali sugadinti 8 bitų reikšmes). Pvz., Prie el. Laiško pridedate atvaizdą ir norite, kad vaizdas atsidurtų kitame gale, nesukrapštytas. Jūsų el. Pašto programinė įranga „Base64“ koduoja vaizdą ir įterpia atitinkamą tekstą į pranešimą, kaip parodyta žemiau:

Turinio išdėstymas: įterptas; Failo pavadinimas = IMG_0006.JPG Turinio perkėlimas-Kodavimas: Base64 / 9j / 4R / + RXhpZgAATU0AKgAAAAgACgEPAAIAAAAGAAAAhgEQAAIAAAAKAAAAjAESAAMAAAABAAYA AAEaAAUAAAABAAAAlgEbAAUAAAABAAAAngEoAAMAAAABAAIAAAExAAIAAAAHAAAApgEyAAIAAAAU AAAArgITAAMAAAABAAEAAIdpAAQAAAABAAAAwgAABCRBcHBsZQBpUGhvbmUgNnMAAAAASAAAAAEA ... NOMbnDUk2bGh26x2yiJcsoBIrvtPe3muBbTRGMdeufmH + Nct4chUXpwSPk / qK9GtJRMWWVFbZ0JH I4rf2dkZSbOjt7hhEzwcujA4I7Gust75pYVwAPpXn + kzNLOVYD7xFegWEKPkHsM / pU1F0NKbNS32 o24sSCOlaaFYLUhjky4x9PSsKL5bJsdWkAz3xirH2dZLy1DM2C44zx1FZqL2PTXY / 9k =

Iliustracijoje parodyta, kad šis užkoduotas vaizdas prasideda / ir baigiasi =. ... nurodo tekstą, kurio nerodžiau trumpai. Atkreipkite dėmesį, kad visa šio ar bet kurio kito pavyzdžio koduotė yra maždaug 33 procentais didesnė už pradinius dvejetainius duomenis.

Gavėjo el. Pašto programinė įranga iššifruos užkoduotą tekstinį vaizdą, kad atkurtų pradinį dvejetainį vaizdą. Šiame pavyzdyje vaizdas bus rodomas kartu su likusia pranešimo dalimi.

„Base64“ kodavimas ir dekodavimas

„Base64“ remiasi paprastais kodavimo ir dekodavimo algoritmais. Jie dirba su 65 simbolių US-ASCII pogrupiu, kur kiekvienas iš pirmųjų 64 simbolių susiejamas su lygiaverte 6 bitų dvejetaine seka. Štai abėcėlė:

Reikšmės kodavimas Reikšmės kodavimas Vertės kodavimas Vertės kodavimas Vertės kodavimas 0 A 17 R 34 i 51 z 1 B 18 S 35 j 52 0 2 C 19 T 36 k 53 1 3 D 20 U 37 l 54 2 4 E 21 V 38 m 55 3 5 F 22 W 39 n 56 4 6 G 23 X 40 o 57 5 7 H 24 Y 41 p 58 6 8 I 25 Z 42 q 59 7 9 J 26 a 43 r 60 8 10 K 27 b 44 s 61 9 11 L 28 c 45 t 62 + 12 M 29 d 46 u 63/13 N 30 e 47 v 14 O 31 f 48 w (padas) = ​​15 P 32 g 49 x 16 Q 33 h 50 m

65-as simbolis (=) naudojamas užpildyti „Base64“ koduotą tekstą vientisu dydžiu, kaip paaiškinta netrukus.

Pogrupio ypatybė

Šis pogrupis turi svarbią savybę, kad jis identiškai pavaizduotas visose ISO 646 versijose, įskaitant „US-ASCII“, ir visi pogrupio simboliai taip pat yra identiški visose EBCDIC versijose.

Kodavimo algoritmas gauna 8 bitų baitų įvesties srautą. Manoma, kad šis srautas užsakomas pirmiausia su reikšmingiausiuoju bitu: pirmasis bitas yra aukšto lygio bitas pirmajame baite, aštuntasis bitas yra žemos eilės bitas šiame baite ir pan.

Iš kairės į dešinę šie baitai yra suskirstyti į 24 bitų grupes. Kiekviena grupė traktuojama kaip keturios sujungtos 6 bitų grupės. Kiekviena 6 bitų grupė indeksuojama į 64 spausdinamų simbolių masyvą; gautas simbolis yra išvestas.

Kai koduojamų duomenų pabaigoje yra mažiau nei 24 bitai, pridedama nulis bitų (dešinėje), kad būtų sudarytas vientisas 6 bitų grupių skaičius. Tada vienas ar du = trinkelių simboliai gali būti išvedami. Svarstytini du atvejai:

  • Vienas likęs baitas: prie šio baito pridedami keturi nuliniai bitai, kad būtų sudarytos dvi 6 bitų grupės. Kiekviena grupė indeksuoja masyvą ir išvestas gautas simbolis. Po šių dviejų simbolių, du = išvesties simbolių ženklai.
  • Du likę baitai: Du nuliniai bitai pridedami prie antrojo baito, kad būtų suformuotos trys 6 bitų grupės. Kiekviena grupė indeksuoja masyvą ir išvestas gautas simbolis. Po šių trijų simbolių, vienas = išvesties simbolio simbolis.

Apsvarstykime tris pavyzdžius, kad sužinotume, kaip veikia kodavimo algoritmas. Pirmiausia tarkime, kad norime užkoduoti @!*:

Šaltinis ASCII bitų sekos su paruoštais 0 bitų, kad susidarytų 8 bitų baitai: @! * 01000000 00100001 00101010 Padalinus šią 24 bitų grupę į keturias 6 bitų grupes gaunama: 010000 | 000010 | 000100 | 101010 Šie bitų modeliai prilygsta šiems rodikliams: 16 2 4 42 Indeksuojant į anksčiau parodytą „Base64“ abėcėlę gaunamas toks kodavimas: QCEq

Toliau sutrumpinsime įvesties seką iki @!:

Šaltinis ASCII bitų sekos su paruoštais 0 bitų, kad susidarytų 8 bitų baitai: @! 01000000 00100001 Pridedami du nulio bitai, kad būtų sudarytos trys 6 bitų grupės: 010000 | 000010 | 000100 Šie bitų modeliai prilygsta šiems indeksams: 16 2 4 Indeksuojant į anksčiau parodytą „Base64“ abėcėlę gaunamas toks kodavimas: QCE An = išvedamas simbolio ženklas, gaunamas toks galutinis kodavimas: QCE =

Paskutinis pavyzdys sutrumpina įvesties seką @:

Šaltinio ASCII bitų seka su iš anksto paruoštais 0 bitų, kad susidarytų 8 bitų baitas: @ 01000000 Pridedami keturi nuliniai bitai, kad būtų sudarytos dvi 6 bitų grupės: 010000 | 000000 Šie bitų modeliai prilygsta šiems indeksams: 16 0 Indeksavimas į anksčiau pateiktą „Base64“ abėcėlę suteikia tokį kodavimą: QA Du = išvedami simbolių ženklai, suteikiantys tokį galutinį kodavimą: QA ==

Dekodavimo algoritmas yra atvirkštinis kodavimo algoritmui. Tačiau galite imtis atitinkamų veiksmų aptikę simbolį, kuris nėra „Base64“ abėcėlėje, arba neteisingą skaičių simbolių.

„Base64“ variantai

Buvo sugalvoti keli „Base64“ variantai. Kai kurie variantai reikalauja, kad užkoduotas išvesties srautas būtų padalintas į kelias fiksuoto ilgio eilutes, kiekvienai eilutei neviršijant tam tikros ilgio ribos, ir (išskyrus paskutinę eilutę) atskirti nuo kitos eilutės per linijos separatorių (vežimo grąžinimas \ r po kurio eina eilutė \ n). Apibūdinu tris variantus, kuriuos palaiko „Java 8“ „Base64“ API. Peržiūrėkite Vikipedijos „Base64“ įrašą, kuriame rasite visą variantų sąrašą.

Pagrindinis

RFC 4648 apibūdina „Base64“ variantą, žinomą kaip Pagrindinis. Šiame variante kodavimui ir dekodavimui naudojamas „Base64“ abėcėlė, pateikta RFC 4648 ir RFC 2045 1 lentelėje (ir parodyta anksčiau šiame įraše). Koduotojas laiko koduotą išvesties srautą kaip vieną eilutę; išvesties nėra. Dekoderis atmeta koduotę, kurioje yra simbolių, esančių už „Base64“ abėcėlės ribų. Atkreipkite dėmesį, kad šias ir kitas sąlygas galima nepaisyti.

MIME

RFC 2045 aprašomas „Base64“ variantas, žinomas kaip MIME. Šiame variante kodavimui ir dekodavimui naudojamas „Base64“ abėcėlė, pateikta RFC 2045 1 lentelėje. Užkoduotas išvesties srautas yra suskirstytas į ne daugiau kaip 76 simbolių eilutes; kiekviena eilutė (išskyrus paskutinę eilutę) yra atskirta nuo kitos eilutės per linijų separatorių. Dekoduojant nepaisoma visų eilučių skyriklių ar kitų simbolių, kurių nėra „Base64“ abėcėlėje.

URL ir failo vardas saugus

RFC 4648 apibūdina „Base64“ variantą, žinomą kaip URL ir failo vardas saugus. Šiame variante kodavimui ir dekodavimui naudojamas „Base64“ abėcėlė, pateikta RFC 4648 2 lentelėje. Abėcėlė yra identiška abėcėlei, parodyta anksčiau, išskyrus tai - pakeičia + ir _ pakeičia /. Išvesties nėra. Dekoderis atmeta koduotę, kurioje yra simbolių, esančių už „Base64“ abėcėlės ribų.

„Base64“ kodavimas yra naudingas ilgų dvejetainių duomenų ir HTTP GET užklausų kontekste. Idėja yra užkoduoti šiuos duomenis ir pridėti juos prie HTTP GET URL. Jei buvo naudojamas „Basic“ arba „MIME“ variantas, bet kuris + arba / simboliai užkoduotuose duomenyse turėtų būti užkoduoti URL į šešioliktaines sekas (+ tampa % 2B ir / tampa % 2F). Gauta URL eilutė būtų šiek tiek ilgesnė. Pakeisdamas + su - ir / su _, URL ir „Filename Safe“ pašalina URL kodavimo ir (arba) iškodavimo programų poreikį (ir jų įtaką užkoduotų reikšmių ilgiui). Be to, šis variantas yra naudingas, kai koduojamus duomenis reikia naudoti failo vardui, nes „Unix“ ir „Windows“ failų pavadinimuose negali būti /.

Darbas su „Java“ „Base64“ API

„Java 8“ pristatė „Base64“ API, susidedančią iš java.util.Base64 klasė kartu su jos Koduotojas ir Dekoderis įdėta statinis klasės. Pagrindas64 pateikia keletą statinis kodavimo ir dekodavimo būdai:

  • 64. „Encoder getEncoder“ (): Grąžinkite pagrindinio varianto koduotoją.
  • 64. Dekoderis „getDecoder“ (): Grąžinkite pagrindinio varianto dekoderį.
  • 64. „Encoder“ getMimeEncoder (): Grąžinkite MIME varianto koduotoją.
  • 64. „Encoder“ getMimeEncoder (int lineLength, baitas [] lineSeparator): Grąžinkite modifikuoto MIME varianto koduotoją su duotu lineLength (suapvalinta žemyn iki artimiausio 4 daugiklio - išvestis neskirstoma į eilutes, kai lineLength<= 0) ir lineSeparator. Tai meta java.lang.IllegalArgumentException kada lineSeparator apima bet kokį „Base64“ abėcėlės simbolį, pateiktą RFC 2045 1 lentelėje.

    „RFC 2045“ enkoderis, kuris grąžinamas iš „noargument“ getMimeEncoder () metodas, yra gana griežtas. Pavyzdžiui, tas koduotojas sukuria užkoduotą tekstą, kurio fiksuotų linijų ilgis (išskyrus paskutinę eilutę) yra 76 simboliai. Jei norite, kad koduotojas palaikytų RFC 1421, nurodantį fiksuoto 64 simbolių ilgį, turite naudoti getMimeEncoder (int lineLength, baitas [] lineSeparator).

  • 64. Dekoderis „getMimeDecoder“ (): Grąžinkite MIME varianto dekoderį.
  • 64. „Encoder“ „getUrlEncoder“ (): Grąžinkite URL ir failo pavadinimo saugaus varianto koduotoją.
  • 64. Dekoderis „getUrlDecoder“ (): Grąžinkite URL ir failo pavadinimo saugaus varianto dekoderį.

64. Enkoderis pateikia kelis „threadsafe“ egzempliorių metodus, kaip užkoduoti baitų sekas. Perduodant nulinę nuorodą vienam iš šių metodų, gaunama java.lang.NullPointerException:

  • baitas [] koduoti (baitas [] src): Užkoduoti visus baitus src į naujai paskirstytą baitų masyvą, kurį šis metodas grąžina.
  • int koduoti (baitas [] src, baitas [] dst): Užkoduoti visus baitus src į dst (pradedant nuo 0 poslinkio). Jei dst nėra pakankamai didelis, kad būtų galima laikyti koduotę, Neteisėtas argumentas. Išimtis yra išmestas. Kitu atveju, parašytų baitų skaičius dst yra grąžinamas.
  • „ByteBuffer“ kodavimas („ByteBuffer“ buferis): Užkoduokite visus likusius baitus buferis į naujai paskirtą java.nio.ByteBuffer objektas. Grįžęs buferispozicija bus atnaujinta iki ribos; jo riba nebus pakeista. Grąžinto išvesties buferio padėtis bus lygi nuliui, o jos riba bus gautų užkoduotų baitų skaičius.
  • Eilutė encodeToString (baitas [] src): Užkoduoti visus baitus src prie eilutės, kuri grąžinama. Šio metodo iškvietimas yra tolygus vykdymui nauja eilutė (koduoti (src), StandardCharsets.ISO_8859_1).
  • 64. Enkoderis be pakavimo (): Grąžinkite koduotoją, kuris koduoja lygiaverčiai šiam koduotojui, bet nepridedant užpildymo simbolio užkoduotų baitų duomenų pabaigoje.
  • „OutputStream“ apvyniojimas („OutputStream OS“): Apvyniokite išvesties srautą, kad užkoduotumėte baitų duomenis. Po naudojimo rekomenduojama nedelsiant uždaryti grąžinamą išvesties srautą, kurio metu visi galimi likę baitai bus perkelti į pagrindinį išvesties srautą. Uždarius grąžintą išvesties srautą, bus uždarytas pagrindinis išvesties srautas.

64. Dekoderis pateikia keletą „threadsafe“ egzempliorių metodų, kaip iškoduoti baitų sekas. Perduodant nulinę nuorodą į vieną iš šių metodų gaunama „NullPointerException“: