2012-10-22 49 views
6

Tôi gặp sự cố khi chuyển đổi văn bản thành chuỗi Base64 trong Java (Android) và .NET (Visual Basic). Dạng đồng bằng (có thể đọc được) của các ký tự ASCII chuyển đổi tốt. Nhưng khi nói đến các ký tự đặc biệt (các ký tự có mã lớn hơn 128), chúng tạo ra rắc rối cho tôi.Java và .NET: Sự nhầm lẫn chuyển đổi Base64

Ví dụ: tôi thử chuyển đổi mã ký tự có giá trị ASCII là 65 (ký tự "A").

Mã của tôi Java là:

char a = 65; 
String c = String.valueOf(a); 
byte bt[] = c.getBytes();    
String result = Base64.encodeToString(bt, Base64.DEFAULT); 

Và mã NET của tôi là:

Dim c As String = Chr(65) 
Dim result as String = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(c)) 

Những cả trả lại kết quả tương tự: "QQ ==". Điều này là tốt. Nhưng khi tôi thử chuyển đổi một ký tự đặc biệt, ví dụ như một mã ký tự 153. Sau đó, nó trả về các kết quả khác nhau.

char a = 153; 
String c = String.valueOf(a);    
byte bt[] = c.getBytes();    
String result = Base64.encodeToString(bt, Base64.DEFAULT); 

này trả về "WPK ="

Và mã NET cùng của tôi:

Dim c As String = Chr(153) 
Dim result as String = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(c)) 

này trả về "4oSi"

này rất kỳ lạ. Có gì sai ở đây Tôi đang sử dụng các thư viện Base64 gốc trên cả hai nền tảng. Có gì sai với mã của tôi không?

+6

Bạn đang sử dụng UTF8 cho C# một và Java sử dụng unicode. Hãy thử sử dụng unicode trong cả hai. – Wug

+0

BTW - bạn nghĩ nhân vật 153 đại diện cho điều gì? Nó không thể in được bằng Unicode. Đó là nhãn hiệu (TM) trong ISO-8859-1. –

+0

Tôi đã thử sử dụng Unicode trên cả hai, vẫn có sự khác biệt. .NET hiện trả về "IiE =" trong khi Java vẫn trả về "wpk =". Có 153 có thể là dấu hiệu thương hiệu. Nhưng mã của tôi chỉ đơn giản là cố gắng để thực hiện một mã hóa bằng cách xáo trộn mã ký tự để chúng thay đổi bất cứ nơi nào giữa 0-255. Sau đó, để truyền tải an toàn qua internet, tôi cần phải chuyển nó sang Base64. –

Trả lời

9

Vì dữ liệu bạn đang mã hóa là dữ liệu được mã hóa - dữ liệu ngẫu nhiên trong đó bất kỳ byte nào có thể từ 0 đến 255 và, ở trạng thái được mã hóa, không có ký tự hoặc văn bản, bạn cần xử lý thông tin này nó - true binary dữ liệu. Cả Java và .NET đều hỗ trợ đầy đủ cho dữ liệu nhị phân thực thông qua các phần tử byte mảng tương ứng của chúng.

Như bạn đã biết, mã hóa base64 là quá trình chuyển đổi dữ liệu nhị phân thực (với dải từ 0 đến 255) thành mảng dữ liệu nhị phân lớn hơn một chút (trong đó mỗi byte được đảm bảo có cùng giá trị với ASCII có thể in được) nhân vật ở đâu đó giữa 32 và 126). Hãy gọi đây là encoded binary. Sau đó, encoded binary có thể được chuyển đổi thành văn bản một cách an toàn vì hầu như mọi bộ ký tự đã biết đều đồng ý với bộ ký tự ASCII có thể in (32 đến 126).

Vì vậy, vấn đề chính với cả đoạn mã Java và VB.NET là bạn đang cố gắng sử dụng văn bản nguyên thủy - char và String trong Java; Chuỗi trong VB.NET để lưu trữ true binary dữ liệu. Một khi bạn làm điều đó đã quá muộn. Không có cách nào để chuyển đổi nó trở lại mảng byte một cách đáng tin cậy vì các văn bản nguyên thủy không được thiết kế để lưu trữ và truy xuất dữ liệu nhị phân một cách an toàn. Để biết thêm về lý do tại sao điều này xảy ra, vui lòng đọc The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

May mắn là bản sửa lỗi rất đơn giản. Đối với Java, không sử dụng char và String để lưu trữ dữ liệu nhị phân. Đặt dữ liệu trực tiếp vào một mảng byte. Hãy thử như sau:

byte [] bt = new byte[1]; 
    bt[0] = (byte) 153; 
    String result = Base64.encodeToString(bt, Base64.DEFAULT); 

tôi nhận được mQ ==

Các khái niệm sửa chữa là như nhau trong VB.NET. Không sử dụng String. Sử dụng một mảng byte.

Dim bytes() As Byte = New Byte() {153} 
    Dim result As String = Convert.ToBase64String(bytes) 

Again - câu trả lời là mQ ==

Cuối cùng, sau khi mã hóa, nó hoàn toàn tốt đẹp để sử dụng Strings. Các ký tự của bạn nằm trong tập hợp con ASCII và bất kỳ chuyển đổi nào giữa chuỗi và mảng byte sẽ không làm hỏng dữ liệu vì tất cả các bộ ký tự đều đồng ý với tập con ASCII.

Hãy nhớ rằng bạn sẽ gặp phải vấn đề tương tự xảy ra theo thứ tự ngược - giải mã. Bạn sẽ giải mã thành mảng byte, tại thời điểm đó bạn sẽ quay lại true binary. Từ thời điểm này trên dữ liệu không bao giờ được lưu trữ như là một chuỗi - cho đến khi bạn kết thúc với nó - ví dụ. giải mã nó trở lại văn bản gốc rõ ràng.

Hy vọng điều này sẽ hữu ích.

+0

'System.Text.Encoding.UTF8.GetBytes (c)' trả về một mảng byte trong .NET. Những gì bạn viết về java âm thanh chính xác. – faester

+0

@Guido mã của bạn dường như hoạt động. Tôi không thực sự giỏi Java vì vậy tôi đoán tôi đã sai lầm khi chuyển đổi chuỗi thành byte thành base64. Những gì tôi đang cố gắng hoàn thành là tôi có một ứng dụng Android hoạt động trên dữ liệu XML. Vì vậy, tất cả dữ liệu văn bản thuần túy của nó. Sau đó, tôi đã thiết lập một máy chủ web với ASP.NET trên đó. Ứng dụng android của tôi là mã hóa dữ liệu tệp XML bằng mã mã hóa của riêng tôi, đó là lý do tại sao các nhân vật như 153 cũng tham gia chơi. Sau đó chuyển nó sang Base64 và truyền nó. Sau đó, trên máy chủ web dựa trên NET sẽ nhận được nó và giải mã từ Base64 và giải mã nó. –

+0

@FarazAzhar - cảm ơn vì đã làm rõ. Tôi đã cập nhật câu trả lời dựa trên sự hiểu biết tốt hơn về vấn đề bạn đang cố giải quyết. –