2009-10-19 38 views
5

Tôi đang đọc 8 byte dữ liệu từ thiết bị phần cứng. Tôi cần phải chuyển đổi chúng thành một giá trị số. Tôi nghĩ rằng tôi muốn chuyển đổi chúng đến một thời gian dài như vậy nên phù hợp với 8 byte. Tôi không quen thuộc với Java và các hoạt động loại dữ liệu cấp thấp. Tôi dường như có hai vấn đề (ngoài thực tế là hầu như không có tài liệu cho phần cứng trong câu hỏi), Các byte được mong đợi để được unsigned, vì vậy tôi không thể làm một chuyển đổi số nguyên thẳng. Tôi không chắc họ là những gì.Làm thế nào để chuyển đổi một byte thành một đoạn dài trong Java?

Mọi lời khuyên sẽ được đánh giá cao.


Đã kết thúc với điều này (lấy từ một số mã nguồn tôi có lẽ đã đọc một tuần trước đây):

public static final long toLong (byte[] byteArray, int offset, int len) 
{ 
    long val = 0; 
    len = Math.min(len, 8); 
    for (int i = (len - 1); i >= 0; i--) 
    { 
     val <<= 8; 
     val |= (byteArray [offset + i] & 0x00FF); 
    } 
    return val; 
} 
+0

Tại sao bạn cần phải chuyển đổi 8 byte đó thành một giá trị số duy nhất? Nếu chúng thực sự là các byte thành phần có giá trị lớn hơn, thì chúng không phải là "đã ký" hoặc "chưa ký". Nếu bạn không biết tính cuối cùng của họ là gì, thì bạn chỉ đơn giản là không thể diễn giải chúng như một số giá trị lâu dài. –

+0

Tôi biết chúng là những giá trị liên tiếp (một bộ đếm từ) nên qua thử và sai tôi có thể tìm thấy khi nó báo cáo sự gia tăng chính xác. Tôi cần phải chuyển đổi chúng thành một giá trị số duy nhất để xác định tỷ lệ thay đổi của nó. – Jotham

+0

Bạn nên thay thế 0x00FF bằng 0xFFL vì điều đó sẽ thể hiện ý định chuyển đổi byte của bạn thành dài hơn. – starblue

Trả lời

1

Đối với tính cuối cùng, hãy thử nghiệm với một số số bạn biết, và sau đó bạn sẽ sử dụng chuyển dịch byte để di chuyển chúng vào lâu dài.

Bạn có thể thấy đây là điểm bắt đầu. Khó khăn là tùy thuộc vào endianess sẽ thay đổi cách bạn làm điều đó, nhưng bạn sẽ thay đổi bằng 24, 16, 8 rồi thêm phần cuối cùng, về cơ bản, nếu thực hiện 32 bit, nhưng bạn sẽ lâu hơn, do đó, chỉ cần làm thêm chuyển.

+0

Với sự dịch chuyển bổ sung, bạn phải chú ý rằng bạn đang dịch chuyển 'long', không phải là' int', bởi vì dịch chuyển hơn 24 bit trong 'int' sẽ loại bỏ các bit thứ tự cao nhất. – erickson

+0

Ông nói đó là một thời gian dài, vì vậy tôi nghĩ rằng ông có thể xác định có bao nhiêu bit nó nên được rằng ông thực sự cần. –

4

Byte#longValue() nên làm điều đó

Và nếu không (nhờ cho nguồn ví dụ) bạn có thể sử dụng java.nio.ByteBuffer chẳng hạn như trong

public static long toLong(byte[] b) { 
    ByteBuffer bb = ByteBuffer.allocate(b.length); 
    bb.put(b); 
    return bb.getLong(); 
} 

Ban đầu hoặc der là BIG_ENDIAN bạn có thể reed more here

+0

Tôi đã có một cái gì đó như thế nhưng nó vẫn không tốt. Có lẽ đó là vì tôi mới làm quen với Java. dài tĩnh công cộng bufferToLong (byte [] b) { \t giá trị dài = b [0]; \t cho (int i = 1; i Jotham

+0

Vì vậy, -1 là gì? Anyways - Tôi mở rộng câu trả lời để cung cấp cho bạn một ý tưởng khác. Từ những gì tôi biết - java.nio khá nhanh (nhanh hơn so với các luồng thông thường khác nhau của bạn) – Bostone

+1

Tôi nhận được 'BufferUnderflowException' trừ khi tôi gọi' bb.flip(); 'trước khi tôi gọi' getLong() ' –

1

Hãy xem BigInteger (byte []). Nó gần như là những gì bạn muốn, ngoại trừ nó là một ký tên. Vì vậy, bạn có thể thêm một byte nữa vào nó trước khi bạn chuyển nó cho BigInteger.

Một điều nữa là bạn nên biết những byte cuối cùng của bạn là gì.

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

12

Chuyển byte theo độ cuối của dữ liệu khá đơn giản. Tuy nhiên, có một mẹo nhỏ với kiểu dữ liệu long vì một phép toán nhị phân trên các loại tích phân là int hoặc nhỏ hơn kích hoạt các toán hạng thành int. Đối với các thay đổi trái lớn hơn 31 bit, điều này sẽ dẫn đến không, vì tất cả các bit đã được chuyển ra khỏi phạm vi int.

Vì vậy, hãy thăng hạng thành long bằng cách bao gồm toán hạng long trong phép tính. Dưới đây, tôi làm điều này bằng cách che dấu mỗi byte với giá trị 0xFF L, là long, buộc kết quả là long.

byte[] buf = new byte[8]; 
/* Fill buf somehow... */ 
long l = ((buf[0] & 0xFFL) << 56) | 
     ((buf[1] & 0xFFL) << 48) | 
     ((buf[2] & 0xFFL) << 40) | 
     ((buf[3] & 0xFFL) << 32) | 
     ((buf[4] & 0xFFL) << 24) | 
     ((buf[5] & 0xFFL) << 16) | 
     ((buf[6] & 0xFFL) << 8) | 
     ((buf[7] & 0xFFL) << 0) ; 
+0

Bạn có thể muốn đặt một vài phôi để dài trong đó ... –

+0

Và có lẽ sử dụng một chỉ số mảng khác hơn 0. –

+0

Vâng, tôi nhận thấy rằng khi bạn đang bình luận ... Tôi đã quan tâm đến nó bằng cách quảng bá dài mặt nạ. – erickson

5

Tôi tin rằng bạn có thể hưởng lợi từ việc sử dụng java.nio. Đây là cách bạn có thể lưu trữ 8 byte trong một thời gian dài:

// Byte Array TO Long 
public static long batol(byte[] buff) { 
    return batol(buff, false); 
} 

public static long batol(byte[] buff, boolean littleEndian) { 
    assert(buff.length == 8); 
    ByteBuffer bb = ByteBuffer.wrap(buff); 
    if (littleEndian) bb.order(ByteOrder.LITTLE_ENDIAN); 
    return bb.getLong(); 
}

Tất nhiên, kết quả sẽ có đại diện đã ký, nhưng chúng sẽ có giá trị nhị phân giống hệt với dữ liệu nguồn.Đối với một đại diện 64 bit + unsigned và arithmatic, bạn sẽ cần phải sử dụng BigInteger. Dưới đây là làm thế nào để chuyển đổi từ dữ liệu "unsigned" lưu trữ trong một thời gian để một BigInteger đúng:

// "Unsigned" Long TO Big Integer 
public static BigInteger ultobi(long ul) { 
    byte[] buff = new byte[8]; 
    ByteBuffer.wrap(buff).asLongBuffer().put(ul); 
    return new BigInteger(+1, buff); 
}
0

Nếu bạn đang đọc từ một InputStream, bạn cũng có thể muốn xem xét DataInputStream.readLong(). Java 1.5 đã giới thiệu Long.reverseBytes(long) có thể giúp bạn với tính xác thực.

+0

Nó có thể là một giải pháp tốt nhưng làm thế nào để bạn đối phó với "unsigned" dài? – Maxbester

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