2011-11-04 49 views
5

tôi nhận được từ ổ cắm một chuỗi trong một mảng byte mà trông giống như:Làm thế nào để phát hiện kết thúc chuỗi trong mảng byte để chuyển đổi chuỗi?

[128,5,6,3,45,0,0,0,0,0] 

Kích thước được đưa ra bởi giao thức mạng là tổng chiều dài của chuỗi (bao gồm số không) như vậy, trong dụ tôi 10

Nếu tôi chỉ cần làm:

String myString = new String(myBuffer); 

tôi có vào cuối của chuỗi 5 không đúng caracter. Việc chuyển đổi dường như không phát hiện sự kết thúc của chuỗi caracter (0).

Để có được kích thước chính xác và chuỗi đúng tôi làm điều này:

int sizeLabelTmp = 0; 
//Iterate over the 10 bit to get the real size of the string 
for(int j = 0; j<(sizeLabel); j++) { 
    byte charac = datasRec[j]; 
    if(charac == 0) 
     break; 
    sizeLabelTmp ++; 
} 
// Create a temp byte array to make a correct conversion 
byte[] label = new byte[sizeLabelTmp]; 
for(int j = 0; j<(sizeLabelTmp); j++) { 
    label[j] = datasRec[j]; 
} 
String myString = new String(label); 

Có cách nào tốt hơn để xử lý các vấn đề?

Cảm ơn

Trả lời

7

0 không phải là "kết thúc chuỗi ký tự". Nó chỉ là một byte. Có hay không nó chỉ đến ở cuối chuỗi phụ thuộc vào mã hóa bạn đang sử dụng (và những gì văn bản có thể được). Ví dụ, nếu bạn sử dụng UTF-16, mỗi byte khác sẽ là 0 đối với các ký tự ASCII.

Nếu bạn chắc chắn rằng 0 đầu tiên cho biết kết thúc của chuỗi, bạn có thể sử dụng một cái gì đó như mã bạn đã đưa ra, nhưng tôi muốn viết lại nó như:

int size = 0; 
while (size < data.length) 
{ 
    if (data[size] == 0) 
    { 
     break; 
    } 
    size++; 
} 

// Specify the appropriate encoding as the last argument 
String myString = new String(data, 0, size, "UTF-8"); 

I mạnh mẽ khuyên bạn không chỉ sử dụng mã hóa mặc định nền tảng - nó không phải là di động và cũng có thể không cho phép tất cả các ký tự Unicode. Tuy nhiên, bạn không thể chỉ quyết định tùy ý - bạn cần đảm bảo rằng mọi thứ tạo và tiêu thụ dữ liệu này đều đồng ý trên bảng mã.

Nếu bạn kiểm soát giao thức, nó sẽ là nhiều hơn tốt hơn nếu bạn có thể giới thiệu tiền tố độ dài trước chuỗi, để cho biết có bao nhiêu byte ở dạng được mã hóa. Bằng cách đó, bạn có thể đọc chính xác lượng dữ liệu phù hợp (không cần "đọc quá") và bạn có thể biết dữ liệu đã bị cắt bớt vì một lý do nào đó hay không.

+0

+1 để tính mã hóa. Nếu các công cụ nhận được trên socket chỉ là một chuỗi Java được tuần tự hóa thì nó sẽ ổn. –

+0

@G_H: "Chỉ cần chuỗi Java được tuần tự hóa" không thực sự xác định định dạng tuần tự hóa là gì. Nếu OP sử dụng tuần tự nhị phân Java, anh ta sẽ không thực hiện thao tác này một cách rõ ràng ... và nếu đó là một số định dạng tuần tự hóa khác, chúng ta cần biết * cái nào *. –

+0

Tôi có lẽ nên ngừng nói chuyện ... Sự thật là tôi luôn tránh xa sự tuần tự hóa và không biết chi tiết về điều đó. JAXB hoặc JPA thường là điều duy nhất tôi thậm chí còn xem xét một tùy chọn. –

2

Các chuỗi trong Java không được kết thúc bằng 0, như trong một số ngôn ngữ khác. 0 sẽ được biến thành ký tự null, được cho phép xuất hiện trong một String. Tôi đề nghị bạn sử dụng lược đồ cắt tỉa hoặc phát hiện chỉ mục đầu tiên của mảng là 0 và sử dụng mảng phụ để tạo chuỗi (giả sử tất cả phần còn lại sẽ là 0 sau đó) hoặc chỉ cần tạo chuỗi và gọi trim(). Điều đó sẽ loại bỏ khoảng trắng đầu và cuối, là bất kỳ ký tự nào có mã ASCII 32 trở xuống.

Cách thứ hai sẽ không hoạt động nếu bạn có khoảng trống hàng đầu mà bạn phải giữ lại. Sử dụng StringBuilder và xóa các ký tự ở cuối miễn là chúng là ký tự null sẽ hoạt động tốt hơn trong trường hợp đó.

2

Bạn luôn có thể bắt đầu ở cuối mảng byte và quay lại cho đến khi bạn nhấn lần đầu tiên khác 0. Sau đó, chỉ cần sao chép vào một byte mới và sau đó String nó. Hy vọng điều này sẽ giúp:

byte[] foo = {28,6,3,45,0,0,0,0}; 
    int i = foo.length - 1; 

    while (foo[i] == 0) 
    { 
     i--; 
    } 

    byte[] bar = Arrays.copyOf(foo, i+1); 

    String myString = new String(bar, "UTF-8"); 
    System.out.println(myString.length()); 

Sẽ cho bạn kết quả là 4.

1

Dường như với tôi rằng bạn đang bỏ qua số lần đọc được trả về bởi phương thức read(). Các byte null sau có thể không được gửi đi, chúng có lẽ vẫn còn sót lại từ trạng thái ban đầu của bộ đệm.

int count = in.read(buffer); 
if (count < 0) 
    ; // EOS: close the socket etc 
else 
    String s = new String(buffer, 0, count); 
+0

Bộ đệm hiển thị trong OP của tôi chỉ là một trích xuất của toàn bộ gói. Chuỗi được gửi ở giữa nhiều dữ liệu khác. – grunk

+0

@grunk sau đó giao thức phải cho bạn biết số tiền đó là chuỗi, hoặc bằng cách vô hiệu hóa nó hoặc tiền tố chiều dài. – EJP

9

Có thể quá muộn, nhưng nó có thể giúp người khác. Điều đơn giản nhất bạn có thể làm là new String(myBuffer).trim() cung cấp cho bạn chính xác những gì bạn muốn.

1

Không đi sâu vào các cân nhắc giao thức mà OP ban đầu đã đề cập, làm thế nào về việc này để cắt tỉa các dấu 0?

public static String bytesToString(byte[] data) { 
    String dataOut = ""; 
    for (int i = 0; i < data.length; i++) { 
     if (data[i] != 0x00) 
      dataOut += (char)data[i]; 
    } 
    return dataOut; 
} 
Các vấn đề liên quan