Làm cách nào để chuyển đổi a long
thành a byte[]
và trở lại trong Java?
Tôi đang thử chuyển đổi long
thành một byte[]
để tôi có thể gửi byte[]
qua kết nối TCP. Mặt khác tôi muốn lấy nó byte[]
và chuyển đổi lại thành a double
.
Làm cách nào để chuyển đổi a long
thành a byte[]
và trở lại trong Java?
Tôi đang thử chuyển đổi long
thành một byte[]
để tôi có thể gửi byte[]
qua kết nối TCP. Mặt khác tôi muốn lấy nó byte[]
và chuyển đổi lại thành a double
.
Câu trả lời:
public byte[] longToBytes(long x) {
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
buffer.putLong(x);
return buffer.array();
}
public long bytesToLong(byte[] bytes) {
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
buffer.put(bytes);
buffer.flip();//need flip
return buffer.getLong();
}
Hoặc được bao bọc trong một lớp để tránh tạo ByteBuffers nhiều lần:
public class ByteUtils {
private static ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
public static byte[] longToBytes(long x) {
buffer.putLong(0, x);
return buffer.array();
}
public static long bytesToLong(byte[] bytes) {
buffer.put(bytes, 0, bytes.length);
buffer.flip();//need flip
return buffer.getLong();
}
}
Vì điều này đang trở nên rất phổ biến, tôi chỉ muốn đề cập rằng tôi nghĩ rằng bạn nên sử dụng một thư viện như Guava trong phần lớn các trường hợp. Và nếu bạn có một số sự phản đối kỳ lạ đối với các thư viện, có lẽ bạn nên xem xét câu trả lời này trước tiên cho các giải pháp java gốc. Tôi nghĩ rằng điều chính mà câu trả lời của tôi thực sự có được là bạn không phải lo lắng về tính chính xác của hệ thống.
Bạn có thể sử dụng các phương thức chuyển đổi Byte từ Google Guava .
Thí dụ:
byte[] bytes = Longs.toByteArray(12345L);
Tôi đã thử nghiệm phương pháp ByteBuffer chống lại các hoạt động bitwise đơn giản nhưng sau này nhanh hơn đáng kể.
public static byte[] longToBytes(long l) {
byte[] result = new byte[8];
for (int i = 7; i >= 0; i--) {
result[i] = (byte)(l & 0xFF);
l >>= 8;
}
return result;
}
public static long bytesToLong(final byte[] bytes, final int offset) {
long result = 0;
for (int i = offset; i < Long.BYTES + offset; i++) {
result <<= Long.BYTES;
result |= (bytes[i] & 0xFF);
}
return result;
}
result |= b[i]
giá trị byte trước tiên sẽ được chuyển đổi thành dài mà ký hiệu mở rộng. Một byte có giá trị -128 (hex 0x80
) sẽ biến thành dài với giá trị -128 (hex 0xFFFF FFFF FFFF FF80
). Đầu tiên sau khi chuyển đổi là các giá trị hoặc: ed với nhau. Sử dụng bitwise - và bảo vệ chống lại điều này bằng cách trước tiên chuyển đổi byte thành int và cắt phần mở rộng dấu : (byte)0x80 & 0xFF ==> (int)0xFFFF FF80 & 0xFF ==> (int) 0x80
. Tại sao byte được đăng nhập trong java là một bí ẩn đối với tôi, nhưng tôi đoán rằng nó phù hợp với các loại khác.
Nếu bạn đang tìm kiếm một phiên bản không được kiểm soát nhanh, điều này sẽ thực hiện thủ thuật, giả sử một mảng byte có tên là "b" với độ dài 8:
byte [] -> dài
long l = ((long) b[7] << 56)
| ((long) b[6] & 0xff) << 48
| ((long) b[5] & 0xff) << 40
| ((long) b[4] & 0xff) << 32
| ((long) b[3] & 0xff) << 24
| ((long) b[2] & 0xff) << 16
| ((long) b[1] & 0xff) << 8
| ((long) b[0] & 0xff);
dài -> byte [] làm đối tác chính xác ở trên
byte[] b = new byte[] {
(byte) lng,
(byte) (lng >> 8),
(byte) (lng >> 16),
(byte) (lng >> 24),
(byte) (lng >> 32),
(byte) (lng >> 40),
(byte) (lng >> 48),
(byte) (lng >> 56)};
Tại sao bạn cần byte []? Tại sao không chỉ viết nó vào ổ cắm?
Tôi giả sử bạn có nghĩa là dài hơn là dài , cái sau cần cho phép giá trị null.
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(socket.getOutputStream()));
dos.writeLong(longValue);
DataInputStream dis = new DataInputStream(
new BufferedInputStream(socket.getInputStream()));
long longValue = dis.readLong();
byte[]
chỉ là một phương tiện để kết thúc đó.
ByteBuffer
mà theo các tài liệu "Thứ tự ban đầu của bộ đệm byte luôn là BIG_ENDIAN.
Chỉ cần viết dài vào DataOutputStream với ByteArrayOutputStream nằm bên dưới . Từ ByteArrayOutputStream, bạn có thể lấy mảng byte thông qua toByteArray () :
class Main
{
public static byte[] long2byte(long l) throws IOException
{
ByteArrayOutputStream baos=new ByteArrayOutputStream(Long.SIZE/8);
DataOutputStream dos=new DataOutputStream(baos);
dos.writeLong(l);
byte[] result=baos.toByteArray();
dos.close();
return result;
}
public static long byte2long(byte[] b) throws IOException
{
ByteArrayInputStream baos=new ByteArrayInputStream(b);
DataInputStream dos=new DataInputStream(baos);
long result=dos.readLong();
dos.close();
return result;
}
public static void main (String[] args) throws java.lang.Exception
{
long l=123456L;
byte[] b=long2byte(l);
System.out.println(l+": "+byte2long(b));
}
}
Hoạt động cho các nguyên thủy khác cho phù hợp.
Gợi ý: Đối với TCP, bạn không cần byte [] theo cách thủ công. Bạn sẽ sử dụng một socket socket
và các luồng của nó
OutputStream os=socket.getOutputStream();
DataOutputStream dos=new DataOutputStream(os);
dos.writeLong(l);
//etc ..
thay thế.
Bạn có thể sử dụng triển khai trong org.apache.hadoop.hbase.util.Bytes http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/util/Bytes.html
Mã nguồn ở đây:
Tìm kiếm các phương thức toLong và toBytes.
Tôi tin rằng giấy phép phần mềm cho phép bạn lấy các phần của mã và sử dụng nó nhưng vui lòng xác minh điều đó.
public static long bytesToLong(byte[] bytes) {
if (bytes.length > 8) {
throw new IllegalMethodParameterException("byte should not be more than 8 bytes");
}
long r = 0;
for (int i = 0; i < bytes.length; i++) {
r = r << 8;
r += bytes[i];
}
return r;
}
public static byte[] longToBytes(long l) {
ArrayList<Byte> bytes = new ArrayList<Byte>();
while (l != 0) {
bytes.add((byte) (l % (0xff + 1)));
l = l >> 8;
}
byte[] bytesp = new byte[bytes.size()];
for (int i = bytes.size() - 1, j = 0; i >= 0; i--, j++) {
bytesp[j] = bytes.get(i);
}
return bytesp;
}
Tôi sẽ thêm một câu trả lời khác nhanh nhất có thể (vâng, thậm chí nhiều hơn câu trả lời được chấp nhận), NHƯNG nó sẽ không hoạt động cho mọi trường hợp. TUY NHIÊN, nó S work hoạt động cho mọi kịch bản có thể tưởng tượng được:
Bạn chỉ có thể sử dụng String làm trung gian. Lưu ý, điều này S give cung cấp cho bạn kết quả chính xác mặc dù có vẻ như việc sử dụng Chuỗi có thể mang lại kết quả sai NHƯ VẬY NHƯ BẠN BIẾT BẠN ĐANG LÀM VIỆC VỚI CÁC CHIẾN LƯỢC "BÌNH THƯỜNG". Đây là một phương pháp để tăng hiệu quả và làm cho mã đơn giản hơn, đổi lại phải sử dụng một số giả định trên chuỗi dữ liệu mà nó hoạt động.
Sử dụng phương pháp này: Nếu bạn đang làm việc với một số ký tự ASCII như các ký hiệu này ở đầu bảng ASCII, các dòng sau có thể thất bại, nhưng hãy đối mặt với nó - có thể bạn sẽ không bao giờ sử dụng chúng.
Pro sử dụng phương pháp này: Hãy nhớ rằng hầu hết mọi người thường làm việc với một số chuỗi bình thường mà không có bất kỳ ký tự bất thường nào và sau đó phương pháp là cách đơn giản nhất và nhanh nhất để đi.
từ Dài đến byte []:
byte[] arr = String.valueOf(longVar).getBytes();
từ byte [] đến Long:
long longVar = Long.valueOf(new String(byteArr)).longValue();
Nếu bạn đã sử dụng một OutputStream
để ghi vào ổ cắm, thì DataOutputStream có thể phù hợp. Đây là một ví dụ:
// Assumes you are currently working with a SocketOutputStream.
SocketOutputStream outputStream = ...
long longValue = ...
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeLong(longValue);
dataOutputStream.flush();
Có nhiều phương pháp tương tự cho short
, int
, float
vv Sau đó, bạn có thể sử dụng DataInputStream ở phía bên nhận.
Với ByteBuffer.allocate (8) .putLong (obj) .array ():
public byte[] toBytes(Long obj) {
if (obj != null) {
return ByteBuffer.allocate(8).putLong(obj).array();
return null;
}
Nguồn:
Đối với nhiều ví dụ sử dụng khác của ByteBuffer:
Đây là một cách khác để chuyển đổi byte[]
sang long
sử dụng Java 8 hoặc mới hơn:
private static int bytesToInt(final byte[] bytes, final int offset) {
assert offset + Integer.BYTES <= bytes.length;
return (bytes[offset + Integer.BYTES - 1] & 0xFF) |
(bytes[offset + Integer.BYTES - 2] & 0xFF) << Byte.SIZE |
(bytes[offset + Integer.BYTES - 3] & 0xFF) << Byte.SIZE * 2 |
(bytes[offset + Integer.BYTES - 4] & 0xFF) << Byte.SIZE * 3;
}
private static long bytesToLong(final byte[] bytes, final int offset) {
return toUnsignedLong(bytesToInt(bytes, offset)) << Integer.SIZE |
toUnsignedLong(bytesToInt(bytes, offset + Integer.BYTES));
}
Chuyển đổi a long
có thể được biểu thị dưới dạng các bit bậc cao và bậc thấp của hai giá trị nguyên theo bit-OR. Lưu ý rằng đó toUnsignedLong
là từ Integer
lớp và cuộc gọi đầu tiên toUnsignedLong
có thể là thừa.
Việc chuyển đổi ngược lại cũng có thể được kiểm soát, như những người khác đã đề cập.
Tiện ích mở rộng Kotlin cho các loại Long và ByteArray:
fun Long.toByteArray() = numberToByteArray(Long.SIZE_BYTES) { putLong(this@toByteArray) }
private inline fun numberToByteArray(size: Int, bufferFun: ByteBuffer.() -> ByteBuffer): ByteArray =
ByteBuffer.allocate(size).bufferFun().array()
@Throws(NumberFormatException::class)
fun ByteArray.toLong(): Long = toNumeric(Long.SIZE_BYTES) { long }
@Throws(NumberFormatException::class)
private inline fun <reified T: Number> ByteArray.toNumeric(size: Int, bufferFun: ByteBuffer.() -> T): T {
if (this.size != size) throw NumberFormatException("${T::class.java.simpleName} value must contains $size bytes")
return ByteBuffer.wrap(this).bufferFun()
}
Bạn có thể xem mã đầy đủ trong thư viện của tôi https://github.com/ArtemBotnev/low-level-extensions