Gần đây tôi đã nhận ra rằng tôi không hiểu rõ quá trình mã hóa chuỗi của Java.Từ khi biên dịch sang thời gian chạy, mã hóa chuỗi Java thực sự hoạt động như thế nào
Xét đoạn mã sau:
public class Main
{
public static void main(String[] args)
{
System.out.println(java.nio.charset.Charset.defaultCharset().name());
System.out.println("ack char: ^"); /* where^= 0x06, the ack char */
}
}
Kể từ khi ký tự điều khiển là interpreted differently between windows-1252 and ISO-8859-1, tôi đã chọn các ack
char để thử nghiệm.
Tôi hiện đang biên dịch mã hóa với các tệp mã hóa khác nhau, UTF-8, windows-1252 và ISO-8859-1. Cả hai biên dịch cho cùng một điều, byte-mỗi-byte như được xác minh bởi md5sum
.
sau đó tôi chạy chương trình:
$ java Main | hexdump -C
00000000 55 54 46 2d 38 0a 61 63 6b 20 63 68 61 72 3a 20 |UTF-8.ack char: |
00000010 06 0a |..|
00000012
$ java -Dfile.encoding=iso-8859-1 Main | hexdump -C
00000000 49 53 4f 2d 38 38 35 39 2d 31 0a 61 63 6b 20 63 |ISO-8859-1.ack c|
00000010 68 61 72 3a 20 06 0a |har: ..|
00000017
$ java -Dfile.encoding=windows-1252 Main | hexdump -C
00000000 77 69 6e 64 6f 77 73 2d 31 32 35 32 0a 61 63 6b |windows-1252.ack|
00000010 20 63 68 61 72 3a 20 06 0a | char: ..|
00000019
Nó một cách chính xác kết quả đầu ra 0x06
không có vấn đề mã hóa đang được sử dụng.
Ok, nó vẫn xuất kết quả giống nhau 0x06
, được hiểu là chữ [ACK] có thể in bằng mã windows-1252.
Điều đó dẫn tôi đến một vài câu hỏi:
- Sản bảng mã/charset của file Java được biên soạn dự kiến sẽ được trùng với charset mặc định của hệ thống, theo đó nó được biên soạn? Hai người luôn luôn đồng nghĩa?
- Biểu diễn được biên dịch dường như không phụ thuộc vào bộ ký tự biên dịch thời gian, đây có phải là trường hợp không?
- Điều này có nghĩa là các chuỗi trong các tệp Java có thể được diễn giải khác nhau trong thời gian chạy nếu chúng không sử dụng các ký tự chuẩn cho bộ ký tự/ngôn ngữ hiện tại?
- Tôi nên biết gì về chuỗi ký tự và chuỗi ký tự trong Java?
Nó không rõ ràng những gì bạn có nghĩa là "biên dịch nó với mã hóa tệp khác nhau". Bạn có nghĩa là bạn lưu tệp trong các mã hóa khác nhau, sau đó biên dịch từng tệp đó bằng cách sử dụng nút chuyển mã hóa sang javac không? Nếu vậy, làm thế nào để bạn biết những gì rác ngẫu nhiên là cuộn lên trong các tập tin nguồn sau khi lưu chúng trong những mã hóa? Bạn không thể đặt một ký tự điều khiển theo nghĩa đen vào nguồn của bạn và mong đợi nó tồn tại tuần tự hóa với các ký tự được mã hóa. –
Một tệp không có gì hơn một luồng byte. Vì vậy, tôi tham chiếu đến các chuỗi chứa 'char' có thể được diễn giải khác nhau, hoặc ở thời gian chạy hoặc tại thời gian biên dịch, bằng cách giả sử tập tin được mã hóa trong các bộ ký tự khác nhau. –
Để rõ ràng về bước biên dịch, tôi đã sử dụng thuộc tính mã hóa của mặt trời để đặt bộ ký tự tại thời gian biên dịch: 'javac -encoding windows-1252 Main.java', với bộ mã hóa phù hợp. –