Programmering

Base64-koding og dekoding i Java 8

Java 8 vil bli husket hovedsakelig for å introdusere lambdas, streams, en ny dato / klokkeslettmodell og Nashorn JavaScript-motoren til Java. Noen vil også huske Java 8 for å introdusere forskjellige små, men nyttige funksjoner som Base64 API. Hva er Base64, og hvordan bruker jeg dette API-et? Dette innlegget svarer på disse spørsmålene.

Hva er Base64?

Base64 er en binær-til-tekst-kodingsplan som representerer binære data i et utskrivbart ASCII-strengformat ved å oversette det til en radix-64-representasjon. Hvert Base64-siffer representerer nøyaktig 6 biter binær data.

Base64 forespørsel om kommentardokumenter

Base64 ble først beskrevet (men ikke navngitt) i RFC 1421: Privacy Enhancement for Internet Electronic Mail: Part I: Message Encryption and Authentication Procedures. Senere ble den offisielt presentert som Base64 i RFC 2045: Multipurpose Internet Mail Extensions (MIME) del 1: Format av Internett-meldingsinstanser, og deretter revidert i RFC 4648: Base16, Base32 og Base64 Data Encodings.

Base64 brukes til å forhindre at data endres under transport gjennom informasjonssystemer, for eksempel e-post, som kanskje ikke er 8-biters rene (de kan fordrive 8-biters verdier). For eksempel fester du et bilde til en e-postmelding og vil at bildet skal komme i den andre enden uten å bli forvirret. Din e-postprogramvare Base64-koder bildet og setter inn den tilsvarende teksten i meldingen, som illustrert nedenfor:

Innholdsdisposisjon: inline; filename = IMG_0006.JPG Content-Transfer-Encoding: base64 / 9j / 4R / + RXhpZgAATU0AKgAAAAgACgEPAAIAAAAGAAAAhgEQAAIAAAAKAAAAjAESAAMAAAABAAYA AAEaAAUAAAABAAAAlgEbAAUAAAABAAAAngEoAAMAAAABAAIAAAExAAIAAAAHAAAApgEyAAIAAAAU AAAArgITAAMAAAABAAEAAIdpAAQAAAABAAAAwgAABCRBcHBsZQBpUGhvbmUgNnMAAAAASAAAAAEA ... NOMbnDUk2bGh26x2yiJcsoBIrvtPe3muBbTRGMdeufmH + Nct4chUXpwSPk / qK9GtJRMWWVFbZ0JH I4rf2dkZSbOjt7hhEzwcujA4I7Gust75pYVwAPpXn + kzNLOVYD7xFegWEKPkHsM / pU1F0NKbNS32 o24sSCOlaaFYLUhjky4x9PSsKL5bJsdWkAz3xirH2dZLy1DM2C44zx1FZqL2PTXY / 9k =

Illustrasjonen viser at dette kodede bildet starter med / og ender med =. De ... indikerer tekst som jeg ikke har vist for kortfattethet. Merk at hele kodingen for dette eller andre eksempler er omtrent 33 prosent større enn de opprinnelige binære dataene.

Mottakerens e-postprogramvare vil Base64-dekode det kodede tekstbildet for å gjenopprette det opprinnelige binære bildet. For dette eksemplet vil bildet bli vist sammen med resten av meldingen.

Base64-koding og dekoding

Base64 er avhengig av enkle kodings- og dekodingsalgoritmer. De jobber med en 65-tegns delsett av US-ASCII der hver av de første 64 tegnene tilordnes til en ekvivalent 6-bits binær sekvens. Her er alfabetet:

Verdikoding Verdi Koding Verdi Koding Verdi Koding 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 (pute) = 15 P 32 g 49 x 16 Q 33 h 50 y

Den 65. karakteren (=) brukes til å putte Base64-kodet tekst til en integrert størrelse som forklart kort.

Delsett-eiendom

Dette delsettet har den viktige egenskapen at det er representert identisk i alle versjoner av ISO 646, inkludert US-ASCII, og alle tegn i delsettet er også representert identisk i alle versjoner av EBCDIC.

Kodingsalgoritmen mottar en inngangsstrøm på 8-bit byte. Denne strømmen antas å være bestilt med den mest betydningsfulle biten først: den første biten er høyordensbiten i den første byten, den åttende biten er den laveste ordenbiten i denne byten, og så videre.

Fra venstre til høyre er disse bytene organisert i 24-biters grupper. Hver gruppe behandles som fire sammenkoblede 6-biters grupper. Hver 6-biters gruppe indekseres i en matrise med 64 utskrivbare tegn; den resulterende karakteren sendes ut.

Når færre enn 24 biter er tilgjengelige på slutten av dataene som blir kodet, blir null biter lagt til (til høyre) for å danne et integrert antall 6-bits grupper. Så, en eller to = putetegn kan skrives ut. Det er to saker å vurdere:

  • En gjenværende byte: Fire nullbiter er lagt til denne byten for å danne to 6-biters grupper. Hver gruppe indekserer matrisen, og et resulterende tegn sendes ut. Etter disse to karakterene, to = pad-tegn sendes ut.
  • To gjenværende byte: To nullbiter er lagt til den andre byten for å danne tre 6-biters grupper. Hver gruppe indekserer matrisen, og et resulterende tegn sendes ut. Etter disse tre karakterene, en = padkarakter sendes ut.

La oss vurdere tre eksempler for å lære hvordan kodingsalgoritmen fungerer. Anta først at vi ønsker å kode @!*:

Kilde ASCII-bitsekvenser med forhåndsinnstilte 0 bits for å danne 8-bit byte: @! * 01000000 00100001 00101010 Å dele denne 24-bitersgruppen i fire 6-bitersgrupper gir følgende: 010000 | 000010 | 000100 | 101010 Disse bitmønstrene tilsvarer følgende indekser: 16 2 4 42 Indeksering i Base64-alfabetet vist tidligere gir følgende koding: QCEq

Vi fortsetter med å forkorte inngangssekvensen til @!:

Kilde ASCII-bitsekvenser med forhåndsinnstilte 0 bits for å danne 8-bit byte: @! 01000000 00100001 To nullbiter er lagt til for å lage tre 6-bits grupper: 010000 | 000010 | 000100 Disse bitmønstrene tilsvarer følgende indekser: 16 2 4 Indeksering i Base64-alfabetet vist tidligere gir følgende koding: QCE An = padtegn blir gitt, og gir følgende endelige koding: QCE =

Det siste eksemplet forkorter inngangssekvensen til @:

Kilde ASCII-bitsekvens med forhåndsforsatte 0 bits for å danne 8-biters byte: @ 01000000 Fire null-bits er lagt til for å lage to 6-biters grupper: 010000 | 000000 Disse bitmønstrene tilsvarer følgende indekser: 16 0 Indeksering i Base64-alfabetet som er vist tidligere gir følgende koding: QA To = padtegn blir gitt, og gir følgende endelige koding: QA ==

Dekodingsalgoritmen er den omvendte av kodingsalgoritmen. Imidlertid er det gratis å iverksette passende tiltak når det oppdages et tegn som ikke er i Base64-alfabetet eller et feil antall padtegn.

Base64-varianter

Flere Base64-varianter er utviklet. Noen varianter krever at den kodede utgangsstrømmen deles inn i flere linjer med fast lengde med hver linje som ikke overskrider en viss lengdegrense, og (bortsett fra den siste linjen) skilles fra neste linje via en linjeseparator (vognretur \ r etterfulgt av linefeed \ n). Jeg beskriver de tre variantene som støttes av Java 8s Base64 API. Sjekk Wikipedia's Base64-oppføring for en komplett liste over varianter.

Grunnleggende

RFC 4648 beskriver en Base64-variant kjent som Grunnleggende. Denne varianten bruker Base64-alfabetet presentert i tabell 1 i RFC 4648 og RFC 2045 (og vist tidligere i dette innlegget) for koding og dekoding. Koderen behandler den kodede utgangsstrømmen som en linje; ingen linjeseparatorer sendes ut. Dekoderen avviser en koding som inneholder tegn utenfor Base64-alfabetet. Merk at disse og andre bestemmelser kan overstyres.

MIME

RFC 2045 beskriver en Base64-variant kjent som MIME. Denne varianten bruker Base64-alfabetet presentert i tabell 1 i RFC 2045 for koding og dekoding. Den kodede utgangsstrømmen er organisert i linjer på ikke mer enn 76 tegn; hver linje (unntatt den siste linjen) er skilt fra neste linje via en linjeseparator. Alle linjeseparatorer eller andre tegn som ikke finnes i Base64-alfabetet, ignoreres under dekoding.

URL og filnavn trygt

RFC 4648 beskriver en Base64-variant kjent som URL og filnavn trygt. Denne varianten bruker Base64-alfabetet presentert i tabell 2 i RFC 4648 for koding og dekoding. Alfabetet er identisk med alfabetet vist tidligere bortsett fra det - erstatter + og _ erstatter /. Det skrives ikke ut linjeseparatorer. Dekoderen avviser en koding som inneholder tegn utenfor Base64-alfabetet.

Base64-koding er nyttig i sammenheng med lange binære data og HTTP GET-forespørsler. Ideen er å kode disse dataene og deretter legge dem til HTTP GET URL. Hvis Basic- eller MIME-varianten ble brukt, vil noen + eller / tegn i de kodede dataene må være URL-kodet i heksadesimale sekvenser (+ blir til % 2B og / blir til % 2F). Den resulterende URL-strengen vil være noe lengre. Ved å erstatte + med - og / med _, URL og filnavn Safe fjerner behovet for URL-kodere / dekodere (og deres innvirkning på lengden på kodede verdier). Denne varianten er også nyttig når de kodede dataene skal brukes til et filnavn fordi Unix- og Windows-filnavn ikke kan inneholde /.

Jobber med Java's Base64 API

Java 8 introduserte en Base64 API bestående av java.util.Base64 klasse sammen med sin Koder og Dekoder nestet statisk klasser. Base64 presenterer flere statisk metoder for å skaffe kodere og dekodere:

  • Base64.Encoder getEncoder (): Returner en koder for Basic-varianten.
  • Base64.Decoder getDecoder (): Returner en dekoder for Basic-varianten.
  • Base64.Encoder getMimeEncoder (): Returner en kode for MIME-varianten.
  • Base64.Encoder getMimeEncoder (int lineLength, byte [] lineSeparator): Returner en koder for en modifisert MIME-variant med det gitte lineLength (avrundet til nærmeste multiplum av 4 - utdata ikke skilt i linjer når lineLength<= 0) og lineSeparator. Det kaster java.lang.IllegalArgumentException når lineSeparator inkluderer ethvert Base64-alfabettegn presentert i tabell 1 i RFC 2045.

    RFC 2045-koderen, som returneres fra noargumentet getMimeEncoder () metoden, er ganske stiv. For eksempel lager koderen kodet tekst med faste linjelengder (unntatt den siste linjen) på 76 tegn. Hvis du vil at en koder skal støtte RFC 1421, som angir en fast linjelengde på 64 tegn, må du bruke getMimeEncoder (int lineLength, byte [] lineSeparator).

  • Base64.Decoder getMimeDecoder (): Returner en dekoder for MIME-varianten.
  • Base64.Encoder getUrlEncoder (): Returner en kode for URL- og filnavn Safe-varianten.
  • Base64.Decoder getUrlDecoder (): Returner en dekoder for URL- og Filename Safe-varianten.

Base64. koderen presenterer flere trådsikre forekomstmetoder for koding av bytesekvenser. Å overføre nullreferansen til en av følgende metoder resulterer i java.lang.NullPointerException:

  • byte [] koding (byte [] src): Kod alle byte i src til en nylig tildelt byte-matrise, som denne metoden returnerer.
  • int-kode (byte [] src, byte [] dst): Kod alle byte i src til dst (starter ved forskyvning 0). Hvis dst er ikke stor nok til å holde kodingen, IllegalArgumentException blir kastet. Ellers er antall byte skrevet til dst blir returnert.
  • ByteBuffer-kode (ByteBuffer-buffer): Kod alle gjenværende byte i buffer til en nylig tildelt java.nio.ByteBuffer gjenstand. Ved retur, bufferposisjon vil bli oppdatert til sin grense; grensen har ikke blitt endret. Den returnerte utgangsbufferens posisjon vil være null og grensen vil være antallet resulterende kodede byte.
  • StrengkodeToString (byte [] src): Kod alle byte i src til en streng som returneres. Å påkalle denne metoden tilsvarer å utføre ny streng (koding (src), StandardCharsets.ISO_8859_1).
  • Base64.Encoder withoutPadding (): Returner en kode som koder ekvivalent med denne koderen, men uten å legge til noe polstringstegn på slutten av de kodede bytdataene.
  • OutputStream wrap (OutputStream os): Pakk inn en utgangsstrøm for koding av byte-data. Det anbefales å umiddelbart lukke den returnerte utgangsstrømmen etter bruk, der den vil spyle alle mulige resterende byte til den underliggende utgangsstrømmen. Å lukke den returnerte utgangsstrømmen vil lukke den underliggende utgangsstrømmen.

Base64.Decoder presenterer flere trådsikre instansmetoder for dekoding av bytesekvenser. Å overføre nullreferansen til en av følgende metoder resulterer i NullPointerException:

$config[zx-auto] not found$config[zx-overlay] not found