Mã hóa thành Base64 trong Java


317

Tôi cần mã hóa một số dữ liệu trong mã hóa Base64 trong Java. Làm thế nào để làm điều đó? Tên của lớp cung cấp bộ mã hóa Base64 là gì?


Tôi đã cố gắng sử dụng sun.misc.BASE64Encoderlớp học, nhưng không thành công. Tôi có dòng mã Java 7 sau:

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

Tôi đang sử dụng Eclipse. Eclipse đánh dấu dòng này là một lỗi. Tôi đã nhập các thư viện cần thiết:

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

Nhưng một lần nữa, cả hai đều được hiển thị là lỗi. Tôi tìm thấy một bài tương tự ở đây .

Tôi đã sử dụng Apache Commons như một giải pháp được đề xuất bằng cách bao gồm:

import org.apache.commons.*;

và nhập các tệp JAR được tải xuống từ: http://commons.apache.org/codec/

Nhưng vấn đề vẫn tồn tại. Eclipse vẫn hiển thị các lỗi được đề cập trước đó. Tôi nên làm gì?


7
Lời khuyên của tôi: đọc thông báo lỗi và cố gắng hiểu những gì nó nói.
JB Nizet

27
Bạn không được phép sử dụng các lớp học dướisun.**
onon15

16
Chúng không phải là một phần của API công khai; chúng có thể được thay đổi, loại bỏ hoặc bất cứ điều gì mà không cần thông báo trước. Một số trong số chúng có thể là thử nghiệm hoặc chỉ không phải là cấp sản xuất. oracle.com/technetwork/java/faq-sun-packages-142232.html
onon15

5
Hoặc sử dụng JAXB DatatypeConverter được bao gồm làm tiêu chuẩn trong Java 6 trở lên.
Ian Roberts

9
java.util.Base64 có sẵn trong Java 8
Earcam

Câu trả lời:


621

Bạn cần thay đổi việc nhập lớp của bạn:

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

Và sau đó thay đổi lớp của bạn để sử dụng lớp Base64.

Dưới đây là một số mã ví dụ:

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));

Sau đó đọc lý do tại sao bạn không nên sử dụng gói mặt trời .


Cập nhật (2016-12-16)

Bây giờ bạn có thể sử dụng java.util.Base64với Java 8. Đầu tiên, nhập nó như bình thường:

import java.util.Base64;

Sau đó sử dụng các phương thức tĩnh Base64 như sau:

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));

Nếu bạn trực tiếp muốn mã hóa chuỗi và nhận kết quả dưới dạng chuỗi được mã hóa, bạn có thể sử dụng điều này:

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

Xem tài liệu Java cho Base64 để biết thêm.


Tôi có cần tải xuống bất kỳ gói bên ngoài để làm việc này không? Nếu có, cái nào?
hủy bỏ

2
Không, bạn không cần tải xuống bất cứ thứ gì afaik
pratnala

16
org.apache.commons.codec.binary.Base64 không giống như một thư viện mặc định. Tôi đoán bạn phải bao gồm apache commons cho điều đó. Đúng?
Robert Reiz

@Frank Giải mã các byte cùng một lúc gây ra lỗi OutOfMemory. Mọi ý tưởng đều xử lý nó trong bộ đệm
xyz

225

Sử dụng lớp không bao giờ quá muộn để tham gia vào cuộc vui của Java 8: java.util.Base64

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

11
Mặc dù một nhận xét tầm thường, lưu ý rằng nếu bạn sử dụng rằng bạn không tương thích với các phiên bản Java cũ hơn, thì (ít nhất là tại thời điểm này) có lẽ phổ biến hơn nhiều.
dcoder

Tôi cũng sẽ chọn lớp Java 8 là có thể. Tôi hiện đang làm việc trên một lớp để loại bỏ thư viện apache commons khỏi dự án mùa xuân của chúng tôi. Hầu hết các công cụ có thể được thay thế dễ dàng bằng phương thức từ thư viện Spring hoặc jdk.
Adrian Cosma

68

Trong Java 8, nó có thể được thực hiện dưới dạng: Base64.getEncoder (). EncodeToString (string.getBytes (StandardCharsets.UTF_8))

Dưới đây là một ví dụ đầy đủ, khép kín:

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);
    }
}

Đầu ra:

old crow medicine show => b2xkIGNyb3cgbWVkaWNpbmUgc2hvdw==

3
Tại sao không có hằng số ký tự trong thư viện chuẩn Java, oh tại sao?!
Lukasz Wiktor

4
Câu hỏi hay, Lukasz! Trên thực tế, có. Tôi quên mất! java.nio.charset.StandardCharsets. Tôi sẽ chỉnh sửa câu trả lời của tôi. Xem stackoverflow.com/questions/1684040/ Mạnh
Kirby

67

Bạn cũng có thể chuyển đổi bằng mã hóa Base64. Để làm điều này, bạn có thể sử dụng javax.xml.bind.DatatypeConverter#printBase64Binaryphương pháp.

Ví dụ:

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

4
Trong khi điều này hoạt động, tài liệu nêu cụ thể: DatatypeConverterInterface chỉ dành cho nhà cung cấp JAXB.
gebirgiebärbel

11
Tôi nghĩ rằng @rideirgiebaerbel là sai, phương thức printX () và parseX () có thể được sử dụng bởi bất kỳ, điều duy nhất chỉ dành cho JAXB là setDatatypeConverter()phương thức (sau đó phải được gọi cho các nhà cung cấp JAXB).
PhoneixS

9
Cuối cùng lớp Base64 từ Java 8 sẽ là những con đường để đi. Nhưng nếu bạn phải nhắm mục tiêu Java 7 trong khi đó, giải pháp này rất hay vì nó không phụ thuộc vào các thư viện bên ngoài.
dana

4
Điều này không hoạt động trong Java 9. Tệ hơn nữa, mã được biên dịch cho Java 7 bằng cách sử dụng javax.xml.bind. * Sẽ thất bại tại Runtime trong Java 9.
Stephen M -on strike- 25/8/17

21

Google Guava là một lựa chọn khác để mã hóa và giải mã dữ liệu Base64:

Cấu hình POM:

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

Mã mẫu:

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 cung cấp cho bạn một lỗi / cảnh báo vì bạn đang cố gắng sử dụng các lớp bên trong dành riêng cho nhà cung cấp JDK và không phải là một phần của API công khai. Jakarta Commons cung cấp việc triển khai riêng các codec cơ sở64, tất nhiên nằm trong một gói khác. Xóa các nhập đó và để Eclipse nhập các lớp Commons thích hợp cho bạn.


Các dự án Jakarta là không còn . Nó đã được trộn lẫn và khớp (và tên được sử dụng lại cho Java EE ). Bạn có thể cập nhật câu trả lời của bạn và cung cấp một số tài liệu tham khảo? Ví dụ, là nó bây giờ lớp Base64trongorg.apache.commons.codec.binary ? Có phải bây giờ Apache Commons cho bối cảnh này?
Peter Mortensen

9

Để chuyển đổi điều này, bạn cần một bộ mã hóa & giải mã mà bạn sẽ nhận được từ Base64Coder - một bộ mã hóa / giải mã Base64 mã nguồn mở trong Java . Đó là tệp Base64Coder.java bạn sẽ cần.

Bây giờ để truy cập lớp này theo yêu cầu của bạn, bạn sẽ cần lớp dưới đây:

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);
        }
    }
}

Trong Android, bạn có thể chuyển đổi bitmap của mình sang Base64 để tải lên máy chủ hoặc dịch vụ web.

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

Đây được mã hóa hình ảnh trực quan này là đại diện văn bản cho hình ảnh của bạn. Bạn có thể sử dụng mục đích này cho mục đích tải lên hoặc để cấp bằng trực tiếp vào trang HTML như bên dưới ( tham khảo ):

<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" />

Tài liệu: http://dwij.co.in/java-base64-image-encoder


Liên kết cuối cùng (dwij.co.in) bị hỏng (404).
Peter Mortensen


9

Đây là hai xu của tôi ... Java 8 có chứa triển khai Base64 của riêng nó . Tuy nhiên, tôi tìm thấy một sự khác biệt hơi đáng lo ngại. Để minh họa, tôi sẽ cung cấp một ví dụ mã:

Trình bao bọc codec của tôi:

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);
  }
}

Lớp kiểm tra:

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));
  }
}

ĐẦU RA:

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)

Lưu ý rằng văn bản được mã hóa Apache chứa các ngắt dòng bổ sung (khoảng trắng) ở cuối. Do đó, để codec của tôi mang lại kết quả tương tự bất kể việc triển khai Base64, tôi đã phải gọi trim()văn bản được mã hóa Apache. Trong trường hợp của tôi, tôi chỉ cần thêm lệnh gọi phương thức đã nói ở trên vào codec của mình apacheDecode()như sau:

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

Khi thay đổi này được thực hiện, kết quả là những gì tôi mong đợi bắt đầu bằng:

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!

KẾT LUẬN : Nếu bạn muốn chuyển từ Apache Base64 sang Java, bạn phải:

  1. Giải mã văn bản được mã hóa bằng bộ giải mã Apache của bạn.
  2. Mã hóa kết quả văn bản (thuần túy) với Java.

Nếu bạn chuyển đổi mà không làm theo các bước này, rất có thể bạn sẽ gặp vấn đề. Đó là cách tôi thực hiện khám phá này.


8

Trên Android, sử dụng các phương thức tĩnh của lớp tiện ích android.util.Base64 . Tài liệu tham khảo nói rằng lớp Base64 đã được thêm vào trong API cấp 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));

Đây là câu trả lời tốt nhất nếu bạn đang phát triển cho Android và bạn không thể sử dụng Java 8.
Craig Brown

6

Apache Commons có một triển khai tốt đẹp của Base64. Bạn có thể làm điều này đơn giản như:

// 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));

Bạn có thể tìm thêm chi tiết về mã hóa Base64mã hóa Base64 bằng Java và JavaScript .


Lưu ý rằng điều này giả sử chuỗi được mã hóa trong bộ ký tự mặc định
Kirby

6

Nếu bạn đang sử dụng Spring Framework ít nhất là phiên bản 4.1, bạn có thể sử dụng lớp org.springframework.util.Base64Utils :

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

Nó sẽ ủy quyền cho Base64, Apache Commons Codec hoặc JAXB DatatypeConverter, tùy thuộc vào những gì có sẵn.


4

Ví dụ đơn giản với Java 8:

import java.util.Base64;

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

3

Trong Java 7 tôi đã mã hóa phương thức này

import javax.xml.bind.DatatypeConverter;

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

Hoạt động theo Java 7 và 8, nhưng không phải Java 9. Tệ hơn nữa, nếu bạn xây dựng cái này theo Java 7 hoặc 8, nó sẽ xây dựng và sau đó bạn sẽ nhận được ClassDefNotFoundException tại Runtime trong Java 9.
Stephen M -on strike-


1

Tôi đã thử với đoạn mã sau. Nó hoạt động tốt. :-)

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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.