2013-01-23 39 views
10

Tôi đang tìm cách so sánh hai chuỗi Java tương đương về mặt từ điển nhưng không giống nhau ở mức byte.So sánh hai chuỗi có từ điển tương đương nhưng không giống nhau ở mức byte

Chính xác hơn lấy tên tập tin sau "baaaé.png", ở cấp độ byte nó có thể được biểu diễn theo hai cách khác nhau:

[98, 97, 97, 97, -61, -87 , 46, 112, 110, 103] -> "é" được mã hóa với 2 byte

[98, 97, 97, 97, 101, -52, -127, 46, 112, 110, 103] -> "é" được mã hóa với 3 byte

byte[] ch = {98, 97, 97, 97, -61, -87, 46, 112, 110, 103}; 
    byte[] ff = {98, 97, 97, 97, 101, -52, -127, 46, 112, 110, 103}; 

    String st = new String(ch,"UTF-8"); 
    String st2 = new String(ff,"UTF-8"); 
    System.out.println(st); 
    System.out.println(st2); 
    System.out.println(st.equals(st2)); 

Sẽ tạo ra kết quả sau:

baaaé.png 
baaaé.png 
false 

Có cách nào để so sánh sao cho phương thức bằng trả về đúng không?

+5

Chúng không hiển thị giống nhau ở đây. –

+3

@dystroy dẫn chúng tôi xem xét lại câu lệnh "_lexicographically equivalent_" :) – Fallup

+3

@dystroy Biểu mẫu chuẩn hóa ưu tiên (mạnh) cho web là NFC. Rõ ràng trình duyệt web của bạn có các phím tắt dễ dàng và chỉ hỗ trợ NFC, không phải NFD. Đối với những gì nó có giá trị, tôi làm như vậy. Rõ ràng các trình duyệt web không bận tâm thực hiện NFD. Tuy nhiên, tôi có thể sao chép và dán cả hai ví dụ vào một ứng dụng khác hỗ trợ cả NFC và NFD và chúng hiển thị giống hệt nhau. – Celada

Trả lời

8

Bạn có thể sử dụng lớp Collator với cường độ có thể áp dụng để bình thường hóa những thứ như các dấu trọng âm khác nhau. điều này sẽ cho phép bạn so sánh chuỗi thành công.

Trong trường hợp này, một miền địa phương của Mỹ và một sức mạnh Tertiary là đủ để có được những chuỗi được bình đẳng

Collator usCollator = Collator.getInstance(); 
usCollator.setStrength(Collator.TERTIARY); 
System.out.println(usCollator.equals(st, st2)); 

đầu ra

true 

Bạn cũng có thể sử dụng lớp Normalizer Java để chuyển đổi giữa khác nhau các dạng Unicode. Điều này sẽ biến đổi các chuỗi của bạn, nhưng chúng sẽ kết thúc giống nhau, cho phép bạn sử dụng các công cụ chuỗi chuẩn để thực hiện việc so sánh

Cuối cùng, có thể muốn xem dự án ICU (Cấu phần quốc tế cho Unicode), cung cấp nhiều công cụ để làm việc với các chuỗi Unicode theo nhiều cách khác nhau.

+0

Tôi đã kiểm tra lớp Normalizer và nó hoạt động hoàn hảo. Cảm ơn. – Davz

7

Có hai loại Unicode normalization forms mà bạn cần xem xét:

Đầu tiên là NFC so với NFD. Ví dụ bạn đưa ra trong câu hỏi là một ví dụ tuyệt vời về sự khác biệt giữa NFC và NFD. Chuỗi đầu tiên của bạn là trong NFC trong khi chuỗi thứ hai của bạn là trong NFD.

Trong Unicode, nhiều ký tự có dấu có thể được biểu diễn theo hai cách khác nhau: làm ký tự cơ bản theo sau là dấu kết hợp hoặc ký tự có dấu trọng âm. NFC sử dụng các ký tự được phân bổ trước khi chúng có sẵn. NFD luôn sử dụng các dạng bị phân hủy.

Thông thường, chúng tôi không sử dụng kết hợp NFC và NFD. Hầu hết các môi trường xác định đó là hình thức ưa thích. Rất ngắn gọn: tên tập tin MacOS X sử dụng NFD, và khá nhiều thứ khác sử dụng NFC. Nhưng nếu bạn được cung cấp đầu vào có thể ở dạng chuẩn hóa khác, bạn có thể dễ dàng chuyển đổi nó: quá trình đơn giản (sử dụng thông tin do cơ sở dữ liệu ký tự Unicode cung cấp) và không mất dữ liệu (tức là bạn có thể chuyển qua lại giữa NFC và NFD nếu bạn muốn mà không làm mất thông tin).

java cung cấp lớp được xây dựng có tên là Normalizer có thể chuyển đổi chuỗi thành dạng Unicode nhất định.

Có hai dạng chuẩn hóa khác: NFKC và NFKD. Các hình thức này không nhằm mục đích sử dụng chung, nhưng chỉ dành cho các so sánh từ vựng. Họ giải thích thực tế rằng, ví dụ, ¼ nên được xem xét giống như 1/4 trong một tìm kiếm hoặc so sánh. Nhưng họ không ngụ ý rằng ¼ và 1/4 giống nhau hoặc người ta thường được chuyển đổi thành người khác.

Việc chuyển đổi từ NFC sang NFKC và từ NFD sang NFKD trở nên đơn giản (bạn cần có cơ sở dữ liệu ký tự) nhưng lần này mất dữ liệu. Bạn cần giữ lại văn bản NFC/NFD gốc và chỉ sử dụng NFKC/NFKD làm khóa tìm kiếm/sắp xếp.

+0

java cung cấp lớp dựng sẵn có tên [Normalizer] (http://docs.oracle.com/javase/6/docs/api/java/text/Normalizer.html) có thể chuyển đổi chuỗi thành dạng Unicode nhất định –

+0

+ 1 cho câu trả lời chi tiết của bạn mà giải thích rõ ràng nguyên nhân gốc rễ của vấn đề. – Davz

Các vấn đề liên quan