2011-08-12 9 views
13

Tôi đã sử dụng phương pháp Inet6Address.getByName("2001:db8:0:0:0:0:2:1").toString() để nén địa chỉ IPv6 và đầu ra là 2001:db8:0:0:0:0:2:1, nhưng tôi cần 2001:db8::2:1. , Về cơ bản đầu ra nén nên dựa trên RFC 5952 standard, đó làĐịa chỉ IPV6 thành dạng nén trong Java

1) Shorten as Much as Possible: Ví dụ, năm 2001: db8: 0: 0: 0: 0: 2: 1 phải được rút ngắn xuống còn
2001: db8 :: 2 : 1. Tương tự như vậy, 2001: db8 :: 0: 1 không được chấp nhận, vì biểu tượng "::" có thể đã được sử dụng để tạo ra một biểu diễn ngắn hơn 2001: db8 :: 1.

2) Handling One 16-Bit 0 Field: Ký hiệu "::" KHÔNG được sử dụng để rút ngắn chỉ một trường 16 bit 0. Ví dụ: biểu diễn 2001: db8: 0: 1: 1: 1: 1: 1 là đúng, nhưng 2001: db8 :: 1: 1: 1: 1: 1 không chính xác.

3) Choice in Placement of "::" : = Khi có một sự lựa chọn thay thế trong vị trí của một "::", các chạy dài nhất của liên tiếp 16-bit 0 lĩnh vực PHẢI được rút ngắn (ví dụ, chuỗi với ba liên tiếp không ruộng là rút gọn vào năm 2001: 0: 0: 1: 0: 0: 0: 1). Khi độ dài của các trường 16 bit 0 liên tiếp bằng nhau (tức là, 2001: db8: 0: 0: 1: 0: 0: 1), chuỗi đầu tiên của số không bit PHẢI được rút ngắn. Ví dụ: 2001: db8 :: 1: 0: 0: 1 là chính xác đại diện.

Tôi cũng đã kiểm tra another post in Stack overflow, nhưng không có điều kiện nào được chỉ định (ví dụ lựa chọn vị trí: :).

Có thư viện java nào để xử lý việc này không? Có ai giúp tôi không?

Xin cảm ơn trước.

Trả lời

18

Làm thế nào về điều này?

String resultString = subjectString.replaceAll("((?::0\\b){2,}):?(?!\\S*\\b\\1:0\\b)(\\S*)", "::$2"); 

Giải thích mà không cần Java đúp xuyệc ngược địa ngục:

(  # Match and capture in backreference 1: 
(?: # Match this group: 
    :0 # :0 
    \b # word boundary 
){2,} # twice or more 
)  # End of capturing group 1 
:?  # Match a : if present (not at the end of the address) 
(?!  # Now assert that we can't match the following here: 
\S* # Any non-space character sequence 
\b  # word boundary 
\1  # the previous match 
:0  # followed by another :0 
\b  # word boundary 
)  # End of lookahead. This ensures that there is not a longer 
     # sequence of ":0"s in this address. 
(\S*) # Capture the rest of the address in backreference 2. 
     # This is necessary to jump over any sequences of ":0"s 
     # that are of the same length as the first one. 

Input:

2001:db8:0:0:0:0:2:1 
2001:db8:0:1:1:1:1:1 
2001:0:0:1:0:0:0:1 
2001:db8:0:0:1:0:0:1 
2001:db8:0:0:1:0:0:0 

Output:

2001:db8::2:1 
2001:db8:0:1:1:1:1:1 
2001:0:0:1::1 
2001:db8::1:0:0:1 
2001:db8:0:0:1:: 

(Tôi hy vọng ví dụ cuối cùng là chính xác - hoặc có một quy tắc khác nếu địa chỉ kết thúc bằng 0?)

+0

ước gì có thể nhiều hơn chỉ là 1 cho lời giải thích kỹ lưỡng –

+0

+1 khá ấn tượng –

+0

@Tim Awesome .... Cảm ơn bạn rất nhiều vì câu trả lời tuyệt vời của bạn. – Tony

9

Gần đây tôi đã gặp sự cố tương tự và muốn (rất nhẹ) cải thiện câu trả lời của Tim.

Các biểu thức chính quy sau đây đưa ra hai lợi thế:

((?:(?:^|:)0+\\b){2,}):?(?!\\S*\\b\\1:0+\\b)(\\S*)

Thứ nhất, nó kết hợp sự thay đổi để phù hợp với nhiều zero. Thứ hai, nó cũng khớp chính xác với các địa chỉ mà chuỗi dài nhất của số 0 ở đầu địa chỉ (chẳng hạn như 0:0:0:0:0:0:0:1).

+0

Mặc dù cụm từ thông dụng này đề cập đến các địa chỉ như "0: 0: 0: 0: 0: 0: 0: 0" và rút ngắn chính xác thành "::", nó không còn khớp với nhóm số 0 dài nhất (nghĩa là rút ngắn không chính xác "0: 0: 1: 0: 0: 0: 0: 0" đến ":: 1: 0: 0: 0: 0: 0" thay vì "0: 0: 1 ::". – chrixm

+0

Điều này nén '0000 : 0000: 0000: 0000: 0000: 0000: 0000: 0001' đến ':: 0001' thay vì' :: 1' –

1

java-ipv6 gần như là những gì bạn muốn. Kể từ phiên bản 0.10, nó không kiểm tra thời gian chạy dài nhất của số 0 để rút ngắn bằng :: - ví dụ 0: 0: 1 :: được rút ngắn thành :: 1: 0: 0: 0: 0: 0. Đó là một thư viện rất tốt để xử lý địa chỉ IPv6, và vấn đề này phải là fixed with version 0.11, sao cho thư viện là RFC 5952 compliant.

0

Sau khi thực hiện một số xét nghiệm, tôi nghĩ rằng chụp sau tất cả các kịch bản IPv6 khác nhau:

"((?:(?::0|0:0?)\\b){2,}):?(?!\\S*\\b\\1:0\\b)(\\S*)" -> "::$2" 
1

lớp InetAddresses ổi của có toAddrString() mà định dạng theo RFC 5952.