เข้ารหัสเป็น Base64 ใน Java


317

ฉันต้องการเข้ารหัสข้อมูลบางส่วนในการเข้ารหัส Base64 ใน Java ฉันจะทำอย่างไร ชื่อของคลาสที่ให้การเข้ารหัส Base64 คืออะไร?


ฉันพยายามใช้sun.misc.BASE64Encoderชั้นเรียนโดยไม่ประสบความสำเร็จ ฉันมีบรรทัดโค้ด Java 7 ต่อไปนี้:

wr.write(new sun.misc.BASE64Encoder().encode(buf));

ฉันกำลังใช้ Eclipse Eclipse ทำเครื่องหมายบรรทัดนี้ว่าเป็นข้อผิดพลาด ฉันนำเข้าห้องสมุดที่ต้องการ:

import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder;

แต่อีกครั้งทั้งคู่จะแสดงเป็นข้อผิดพลาด ผมพบว่าการโพสต์ที่คล้ายกันที่นี่

ฉันใช้ Apache Commons เป็นวิธีแก้ปัญหาที่แนะนำโดยรวมถึง:

import org.apache.commons.*;

และอิมพอร์ตไฟล์ JAR ที่ดาวน์โหลดจาก: http://commons.apache.org/codec/

แต่ปัญหายังคงมีอยู่ Eclipse ยังคงแสดงข้อผิดพลาดที่กล่าวถึงก่อนหน้านี้ ฉันควรทำอย่างไรดี?


7
คำแนะนำของฉัน: อ่านข้อความแสดงข้อผิดพลาดและพยายามเข้าใจสิ่งที่พูด
JB Nizet

27
คุณไม่ควรที่จะใช้งานภายใต้การเรียนsun.**
onon15

16
พวกเขาไม่ได้เป็นส่วนหนึ่งของ API สาธารณะ อาจมีการเปลี่ยนแปลงเอาออกหรืออะไรก็ได้โดยไม่ต้องแจ้งให้ทราบล่วงหน้า บางคนอาจจะทดลองหรือไม่ได้เกรดการผลิต oracle.com/technetwork/java/faq-sun-packages-142232.html
onon15

5
หรือใช้ JAXB DatatypeConverterซึ่งรวมเป็นมาตรฐานใน Java 6 และใหม่กว่า
Ian Roberts

9
java.util.Base64มีอยู่ใน Java 8
earcam

คำตอบ:


621

คุณต้องเปลี่ยนการนำเข้าของคลาสของคุณ:

import org.apache.commons.codec.binary.Base64;

จากนั้นเปลี่ยนคลาสของคุณเพื่อใช้คลาส Base64

นี่คือตัวอย่างรหัส:

byte[] encodedBytes = Base64.encodeBase64("Test".getBytes());
System.out.println("encodedBytes " + new String(encodedBytes));
byte[] decodedBytes = Base64.decodeBase64(encodedBytes);
System.out.println("decodedBytes " + new String(decodedBytes));

อ่านแล้วทำไมคุณไม่ควรใช้อาทิตย์ * แพคเกจ


อัปเดต (2016-12-16)

ตอนนี้คุณสามารถใช้java.util.Base64กับ Java 8 ก่อนอื่นให้นำเข้ามันตามปกติ:

import java.util.Base64;

จากนั้นใช้วิธีการคงที่ Base64 ดังต่อไปนี้:

byte[] encodedBytes = Base64.getEncoder().encode("Test".getBytes());
System.out.println("encodedBytes " + new String(encodedBytes));
byte[] decodedBytes = Base64.getDecoder().decode(encodedBytes);
System.out.println("decodedBytes " + new String(decodedBytes));

หากคุณต้องการเข้ารหัสสตริงโดยตรงและรับผลลัพธ์เป็นสตริงที่เข้ารหัสคุณสามารถใช้สิ่งนี้:

String encodeBytes = Base64.getEncoder().encodeToString((userName + ":" + password).getBytes());

ดูเอกสาร Java สำหรับ Base64เพิ่มเติม


ฉันจำเป็นต้องดาวน์โหลดแพ็คเกจภายนอกเพื่อให้ใช้งานได้หรือไม่ ถ้าใช่อันไหน
ยกเลิก

2
ไม่คุณไม่จำเป็นต้องดาวน์โหลดอะไรเลย afaik
pratnala

16
org.apache.commons.codec.binary.Base64 ดูไม่เหมือนไลบรารีเริ่มต้น ฉันคิดว่าคุณต้องรวม apache ทั่วไปสำหรับการที่ ขวา?
Robert Reiz

@ Frank ถอดรหัสไบต์ทันทียกข้อผิดพลาด OutOfMemory ความคิดใด ๆ ในการประมวลผลบัฟเฟอร์
xyz

225

ใช้คลาสที่ไม่เคยสายเกินไปที่จะเข้าร่วมในชั้นเรียนของ Java 8: java.util.Base64

new String(Base64.getEncoder().encode(bytes));

11
แม้ว่าความคิดเห็นเล็กน้อยโปรดสังเกตว่าถ้าคุณใช้ที่คุณไม่เข้ากันได้กับ Java รุ่นเก่าซึ่งเป็น (อย่างน้อยในเวลานี้) อาจจะแพร่หลายมากขึ้น
dcoder

ฉันจะเลือกคลาส Java 8 เป็นไปได้เช่นกัน ฉันกำลังทำงานในชั้นเรียนเพื่อลบ apache คอมมอนส์ห้องสมุดออกจากโครงการฤดูใบไม้ผลิของเรา ส่วนใหญ่ของสิ่งที่สามารถเปลี่ยนได้อย่างง่ายดายด้วยวิธีการจากห้องสมุดฤดูใบไม้ผลิหรือ jdk
Adrian Cosma

68

ใน Java 8 สามารถทำได้ดังนี้: Base64.getEncoder (). encodeToString (string.getBytes (StandardCharsets.UTF_8)

นี่เป็นตัวอย่างสั้น ๆ ที่สมบูรณ์ในตัวเอง:

import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class Temp {
    public static void main(String... args) throws Exception {
        final String s = "old crow medicine show";
        final byte[] authBytes = s.getBytes(StandardCharsets.UTF_8);
        final String encoded = Base64.getEncoder().encodeToString(authBytes);
        System.out.println(s + " => " + encoded);
    }
}

เอาท์พุท:

old crow medicine show => b2xkIGNyb3cgbWVkaWNpbmUgc2hvdw==

3
เหตุใดจึงไม่มีค่าคงที่ Charset ในไลบรารีมาตรฐาน Java ทำไม?!
Lukasz Wiktor

4
เป็นคำถามที่ดี Lukasz! จริงๆแล้วมี ฉันลืม! java.nio.charset.StandardCharsets. ฉันจะแก้ไขคำตอบของฉัน ดูstackoverflow.com/questions/1684040/…
Kirby

67

คุณสามารถแปลงโดยใช้การเข้ารหัส Base64 ในการทำเช่นนี้คุณสามารถใช้javax.xml.bind.DatatypeConverter#printBase64Binaryวิธีการ

ตัวอย่างเช่น:

byte[] salt = new byte[] { 50, 111, 8, 53, 86, 35, -19, -47 };
System.out.println(DatatypeConverter.printBase64Binary(salt));

4
ในขณะที่ใช้งานได้เอกสารระบุว่า: DatatypeConverterInterface สำหรับผู้ให้บริการ JAXB ใช้เท่านั้น
gebirgsbärbel

11
ฉันคิดว่า @gebirgsbaerbel ผิดวิธี printX () และ parseX () สามารถใช้ได้โดยสิ่งใดสิ่งเดียวที่สำหรับ JAXB เท่านั้นคือsetDatatypeConverter()วิธีการ (ซึ่งจะต้องเรียกผู้ให้บริการ JAXB)
PhoneixS

9
ในที่สุดชั้น Base64 จาก Java 8 จะวิธีที่จะไป แต่ถ้าคุณต้องตั้งเป้าหมาย Java 7 ในขณะเดียวกันทางออกนี้ดีเพราะไม่ต้องพึ่งพาไลบรารีภายนอก
dana

4
สิ่งนี้ไม่ทำงานภายใต้ Java 9 ที่เลวร้ายยิ่งรหัสที่รวบรวมสำหรับ Java 7 โดยใช้ javax.xml.bind. * จะล้มเหลวที่ Runtime ภายใต้ Java 9
Stephen M -on strike-

21

Google Guavaเป็นอีกทางเลือกในการเข้ารหัสและถอดรหัสข้อมูล Base64:

การกำหนดค่า POM:

<dependency>
   <artifactId>guava</artifactId>
   <groupId>com.google.guava</groupId>
   <type>jar</type>
   <version>14.0.1</version>
</dependency>

รหัสตัวอย่าง:

String inputContent = "Hello Việt Nam";
String base64String = BaseEncoding.base64().encode(inputContent.getBytes("UTF-8"));

// Decode
System.out.println("Base64:" + base64String); // SGVsbG8gVmnhu4d0IE5hbQ==
byte[] contentInBytes = BaseEncoding.base64().decode(base64String);
System.out.println("Source content: " + new String(contentInBytes, "UTF-8")); // Hello Việt Nam

10

Eclipse ให้ข้อผิดพลาด / คำเตือนเนื่องจากคุณพยายามใช้คลาสภายในที่เฉพาะเจาะจงกับผู้จำหน่าย JDK และไม่ได้เป็นส่วนหนึ่งของ API สาธารณะ จาการ์ตาคอมมอนส์มีการใช้งานตัวแปลงสัญญาณเบส 64 ของตัวเองซึ่งแน่นอนอยู่ในแพ็คเกจอื่น ลบการนำเข้าเหล่านั้นและให้ Eclipse นำเข้าคลาสคอมมอนส์ที่เหมาะสมสำหรับคุณ


โครงการจาการ์ตาไม่มีอีกต่อไป มันได้รับการผสมและจับคู่ (และชื่อที่นำมาใช้ใหม่สำหรับ Java EE ) คุณสามารถปรับปรุงคำตอบของคุณและให้การอ้างอิงบางอย่าง? ตัวอย่างเช่นตอนนี้เป็นคลาสBase64ในorg.apache.commons.codec.binary ? ตอนนี้เป็นApache Commonsสำหรับบริบทนี้หรือไม่
Peter Mortensen

9

การแปลงนี้คุณจะต้องเข้ารหัสและถอดรหัสที่คุณจะได้รับจากBase64Coder - โอเพนซอร์ส Base64 เข้ารหัส / ถอดรหัสในชวา มันเป็นไฟล์Base64Coder.javaคุณจะต้อง

ตอนนี้เพื่อเข้าถึงชั้นนี้ตามความต้องการของคุณคุณจะต้องเรียนด้านล่าง:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Base64 {

    public static void main(String args[]) throws IOException {
        /*
         * if (args.length != 2) {
         *     System.out.println(
         *         "Command line parameters: inputFileName outputFileName");
         *     System.exit(9);
         * } encodeFile(args[0], args[1]);
         */
        File sourceImage = new File("back3.png");
        File sourceImage64 = new File("back3.txt");
        File destImage = new File("back4.png");
        encodeFile(sourceImage, sourceImage64);
        decodeFile(sourceImage64, destImage);
    }

    private static void encodeFile(File inputFile, File outputFile) throws IOException {
        BufferedInputStream in = null;
        BufferedWriter out = null;
        try {
            in = new BufferedInputStream(new FileInputStream(inputFile));
            out = new BufferedWriter(new FileWriter(outputFile));
            encodeStream(in, out);
            out.flush();
        }
        finally {
            if (in != null)
                in.close();
            if (out != null)
                out.close();
        }
    }

    private static void encodeStream(InputStream in, BufferedWriter out) throws IOException {
        int lineLength = 72;
        byte[] buf = new byte[lineLength / 4 * 3];
        while (true) {
            int len = in.read(buf);
            if (len <= 0)
                break;
            out.write(Base64Coder.encode(buf, 0, len));
            out.newLine();
        }
    }

    static String encodeArray(byte[] in) throws IOException {
        StringBuffer out = new StringBuffer();
        out.append(Base64Coder.encode(in, 0, in.length));
        return out.toString();
    }

    static byte[] decodeArray(String in) throws IOException {
        byte[] buf = Base64Coder.decodeLines(in);
        return buf;
    }

    private static void decodeFile(File inputFile, File outputFile) throws IOException {
        BufferedReader in = null;
        BufferedOutputStream out = null;
        try {
            in = new BufferedReader(new FileReader(inputFile));
            out = new BufferedOutputStream(new FileOutputStream(outputFile));
            decodeStream(in, out);
            out.flush();
        }
        finally {
            if (in != null)
                in.close();
            if (out != null)
                out.close();
        }
    }

    private static void decodeStream(BufferedReader in, OutputStream out) throws IOException {
        while (true) {
            String s = in.readLine();
            if (s == null)
                break;
            byte[] buf = Base64Coder.decodeLines(s);
            out.write(buf);
        }
    }
}

ใน Android คุณสามารถแปลงบิตแมปเป็น Base64 เพื่ออัปโหลดไปยังเซิร์ฟเวอร์หรือบริการบนเว็บ

Bitmap bmImage = //Data
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmImage.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] imageData = baos.toByteArray();
String encodedImage = Base64.encodeArray(imageData);

“ encodedImage” นี้เป็นการแสดงข้อความของภาพของคุณ คุณสามารถใช้สิ่งนี้เพื่อวัตถุประสงค์ในการอัปโหลดหรือการเจรจาต่อรองโดยตรงในหน้า HTML ดังต่อไปนี้ ( อ้างอิง ):

<img alt="" src="data:image/png;base64,<?php echo $encodedImage; ?>" width="100px" />
<img alt="" src="data:image/png;base64,/9j/4AAQ...........1f/9k=" width="100px" />

เอกสารประกอบ: http://dwij.co.in/java-base64-image-encoder


ลิงค์สุดท้าย (dwij.co.in) เสีย (404)
Peter Mortensen


9

นี่คือสองเซ็นต์ของฉัน ... Java 8 จะมีการดำเนินการของตัวเองของBase64 อย่างไรก็ตามฉันพบความแตกต่างที่รบกวนเล็กน้อย เพื่ออธิบายฉันจะให้ตัวอย่างรหัส:

เสื้อคลุมตัวแปลงสัญญาณของฉัน:

public interface MyCodec
{
  static String apacheDecode(String encodedStr)
  {
    return new String(Base64.decodeBase64(encodedStr), Charset.forName("UTF-8"));
  }

  static String apacheEncode(String decodedStr)
  {
    byte[] decodedByteArr = decodedStr.getBytes(Charset.forName("UTF-8"));
    return Base64.encodeBase64String(decodedByteArr);
  }

  static String javaDecode(String encodedStr)
  {
    return new String(java.util.Base64.getDecoder().decode(encodedStr), Charset.forName("UTF-8"));
  }

  static String javaEncode(String decodedStr)
  {
    byte[] decodedByteArr = decodedStr.getBytes(Charset.forName("UTF-8"));
    return java.util.Base64.getEncoder().encodeToString(decodedByteArr);
  }
}

ชั้นทดสอบ:

public class CodecDemo
{
  public static void main(String[] args)
  {
    String decodedText = "Hello World!";

    String encodedApacheText = MyCodec.apacheEncode(decodedText);
    String encodedJavaText = MyCodec.javaEncode(decodedText);

    System.out.println("Apache encoded text: " + MyCodec.apacheEncode(encodedApacheText));
    System.out.println("Java encoded text: " + MyCodec.javaEncode(encodedJavaText));

    System.out.println("Encoded results equal: " + encodedApacheText.equals(encodedJavaText));

    System.out.println("Apache decode Java: " + MyCodec.apacheDecode(encodedJavaText));
    System.out.println("Java decode Java: " + MyCodec.javaDecode(encodedJavaText));

    System.out.println("Apache decode Apache: " + MyCodec.apacheDecode(encodedApacheText));
    System.out.println("Java decode Apache: " + MyCodec.javaDecode(encodedApacheText));
  }
}

เอาท์พุท:

Apache encoded text: U0dWc2JHOGdWMjl5YkdRaA0K

Java encoded text: U0dWc2JHOGdWMjl5YkdRaA==
Encoded results equal: false
Apache decode Java: Hello World!
Java decode Java: Hello World!
Apache decode Apache: Hello World!
Exception in thread "main" java.lang.IllegalArgumentException: Illegal base64 character d
    at java.util.Base64$Decoder.decode0(Base64.java:714)
    at java.util.Base64$Decoder.decode(Base64.java:526)
    at java.util.Base64$Decoder.decode(Base64.java:549)

โปรดสังเกตว่าข้อความที่เข้ารหัสของ Apache มีตัวแบ่งบรรทัดเพิ่มเติม (ช่องว่างสีขาว) ในตอนท้าย ดังนั้นเพื่อให้ตัวแปลงสัญญาณของฉันให้ผลลัพธ์เดียวกันโดยไม่คำนึงถึงการใช้งาน Base64 ฉันต้องโทรหาtrim()ข้อความที่เข้ารหัส Apache ในกรณีของฉันฉันเพิ่งเพิ่มการเรียกวิธีดังกล่าวไปยังตัวแปลงสัญญาณของฉันapacheDecode()ดังนี้

return Base64.encodeBase64String(decodedByteArr).trim();

เมื่อทำการเปลี่ยนแปลงแล้วผลลัพธ์คือสิ่งที่ฉันคาดว่าจะเริ่มต้นด้วย:

Apache encoded text: U0dWc2JHOGdWMjl5YkdRaA==
Java encoded text: U0dWc2JHOGdWMjl5YkdRaA==
Encoded results equal: true
Apache decode Java: Hello World!
Java decode Java: Hello World!
Apache decode Apache: Hello World!
Java decode Apache: Hello World!

สรุป : หากคุณต้องการเปลี่ยนจาก Apache Base64 เป็น Java คุณต้อง:

  1. ถอดรหัสข้อความที่เข้ารหัสด้วยตัวถอดรหัส Apache ของคุณ
  2. เข้ารหัสข้อความ (ธรรมดา) ที่มี Java

หากคุณสลับโดยไม่ทำตามขั้นตอนเหล่านี้มีโอกาสมากที่คุณจะพบปัญหา นั่นคือวิธีที่ฉันค้นพบนี้


8

บน Android ให้ใช้วิธีการคงที่ของคลาสยูทิลิตี้android.util.Base64 เอกสารอ้างอิงที่อ้างว่ามีการเพิ่มคลาส Base64 ใน API ระดับ 8 ( Android 2.2 (Froyo))

import android.util.Base64;

byte[] encodedBytes = Base64.encode("Test".getBytes());
Log.d("tag", "encodedBytes " + new String(encodedBytes));

byte[] decodedBytes = Base64.decode(encodedBytes);
Log.d("tag", "decodedBytes " + new String(decodedBytes));

นี่เป็นคำตอบที่ดีที่สุดหากคุณพัฒนาสำหรับ Android และคุณไม่สามารถใช้ Java 8 ได้
Craig Brown

6

Apache Commonsใช้งาน Base64 ได้ดี คุณสามารถทำได้ง่ายๆเพียงแค่:

// Encrypt data on your side using BASE64
byte[] bytesEncoded = Base64.encodeBase64(str .getBytes());
System.out.println("ecncoded value is " + new String(bytesEncoded));

// Decrypt data on other side, by processing encoded data
byte[] valueDecoded= Base64.decodeBase64(bytesEncoded );
System.out.println("Decoded value is " + new String(valueDecoded));

คุณสามารถค้นหารายละเอียดเพิ่มเติมเกี่ยวกับการเข้ารหัส base64 ที่Base64 เข้ารหัสโดยใช้ Java และ JavaScript


โปรดทราบว่านี่ถือว่าสตริงถูกเข้ารหัสในชุดอักขระเริ่มต้น
Kirby

6

หากคุณกำลังใช้ฤดูใบไม้ผลิกรอบอย่างน้อยรุ่น 4.1 คุณสามารถใช้org.springframework.util.Base64Utilsระดับ:

byte[] raw = { 1, 2, 3 };
String encoded = Base64Utils.encodeToString(raw);
byte[] decoded = Base64Utils.decodeFromString(encoded);

มันจะมอบให้กับ Base64, Apache Commons Codec หรือ JAXB DatatypeConverter ของ Java 8 ขึ้นอยู่กับว่ามีอะไรบ้าง


4

ตัวอย่างง่ายๆกับ Java 8:

import java.util.Base64;

String str = "your string";
String encodedStr = Base64.getEncoder().encodeToString(str.getBytes("utf-8"));

3

ใน Java 7 ฉันเขียนโค้ดวิธีนี้

import javax.xml.bind.DatatypeConverter;

public static String toBase64(String data) {
    return DatatypeConverter.printBase64Binary(data.getBytes());
}

ทำงานภายใต้ Java 7 และ 8 แต่ไม่ใช่ Java 9 แย่ลงถ้าคุณสร้างมันภายใต้ Java 7 หรือ 8 มันจะสร้างและจากนั้นคุณจะได้รับ ClassDefNotFoundException ที่รันไทม์ภายใต้ Java 9
Stephen M -on strike-


1

ฉันลองใช้ข้อมูลโค้ดต่อไปนี้ มันทำงานได้ดี :-)

com.sun.org.apache.xml.internal.security.utils.Base64.encode("The string to encode goes here");

0
public String convertImageToBase64(String filePath) {
    byte[] fileContent = new byte[0];
    String base64encoded = null;
    try {
        fileContent = FileUtils.readFileToByteArray(new File(filePath));
    } catch (IOException e) {
        log.error("Error reading file: {}", filePath);
    }
    try {
        base64encoded = Base64.getEncoder().encodeToString(fileContent);
    } catch (Exception e) {
        log.error("Error encoding the image to base64", e);
    }
    return base64encoded;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.