Come faccio a convertire a long
in byte[]
e viceversa in Java?
Sto provando a convertire a in long
in byte[]
modo da poter inviare la byte[]
connessione via TCP. Dall'altro lato voglio prenderlo byte[]
e convertirlo nuovamente in a double
.
Come faccio a convertire a long
in byte[]
e viceversa in Java?
Sto provando a convertire a in long
in byte[]
modo da poter inviare la byte[]
connessione via TCP. Dall'altro lato voglio prenderlo byte[]
e convertirlo nuovamente in a double
.
Risposte:
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();
}
O racchiuso in una classe per evitare di creare ripetutamente ByteBuffer:
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();
}
}
Dato che questo sta diventando così popolare, voglio solo menzionare che penso che tu sia meglio usare una libreria come Guava nella stragrande maggioranza dei casi. E se hai una strana opposizione alle biblioteche, dovresti probabilmente considerare prima questa risposta per le soluzioni Java native. Penso che la cosa principale della mia risposta sia che non devi preoccuparti dell'endianità del sistema da solo.
È possibile utilizzare i metodi di conversione Byte di Google Guava .
Esempio:
byte[] bytes = Longs.toByteArray(12345L);
Ho testato il metodo ByteBuffer contro semplici operazioni bit a bit, ma quest'ultimo è significativamente più veloce.
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]
il valore del byte verrà prima convertito in long che significa estensione. Un byte con valore -128 (esadecimale 0x80
) si trasformerà in un lungo con valore -128 (esadecimale 0xFFFF FFFF FFFF FF80
). Primo dopo la conversione sono i valori o: ed insieme. Utilizzando bit a bit-e protegge contro questo convertendo prima il byte di un int e tagliare l'estensione del segno: (byte)0x80 & 0xFF ==> (int)0xFFFF FF80 & 0xFF ==> (int) 0x80
. Perché i byte sono firmati in Java è un po 'un mistero per me, ma credo che sia adatto ad altri tipi.
Se stai cercando una versione veloce srotolata, questo dovrebbe fare il trucco, supponendo un array di byte chiamato "b" con una lunghezza di 8:
byte [] -> long
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);
long -> byte [] come controparte esatta di quanto sopra
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)};
Perché hai bisogno del byte []? perché non scriverlo semplicemente sul socket?
Presumo che tu intenda long piuttosto che Long , quest'ultimo deve consentire valori 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[]
è solo un mezzo a tal fine.
ByteBuffer
che secondo i documenti "L'ordine iniziale di un buffer di byte è sempre BIG_ENDIAN.
Basta scrivere il long in un DataOutputStream con un ByteArrayOutputStream sottostante . Da ByteArrayOutputStream è possibile ottenere l'array di byte tramite 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));
}
}
Funziona di conseguenza per altri primitivi.
Suggerimento: per TCP non è necessario il byte [] manualmente. Utilizzerai un socket socket
e i suoi flussi
OutputStream os=socket.getOutputStream();
DataOutputStream dos=new DataOutputStream(os);
dos.writeLong(l);
//etc ..
anziché.
È possibile utilizzare l'implementazione in org.apache.hadoop.hbase.util.Bytes http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/util/Bytes.html
Il codice sorgente è qui:
Cerca i metodi toLong e toBytes.
Credo che la licenza del software ti consenta di prendere parti del codice e di usarlo, ma ti preghiamo di verificarlo.
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;
}
Aggiungerò un'altra risposta che è la più veloce possibile ׂ (sì, anche più della risposta accettata), MA non funzionerà per ogni singolo caso. TUTTAVIA, funzionerà per ogni scenario immaginabile:
Puoi semplicemente usare String come intermedio. Nota, questo ti darà il risultato corretto anche se sembra che l'utilizzo di String potrebbe produrre risultati errati FINO A QUANTO SAPI CHE STAI LAVORANDO CON STRINGHE "NORMALI". Questo è un metodo per aumentare l'efficacia e semplificare il codice che, in cambio, deve utilizzare alcune ipotesi sulle stringhe di dati su cui opera.
Contro dell'uso di questo metodo: se stai lavorando con alcuni caratteri ASCII come questi simboli all'inizio della tabella ASCII, le seguenti righe potrebbero non riuscire, ma ammettiamolo: probabilmente non li userai comunque.
Pro di utilizzare questo metodo: ricorda che la maggior parte delle persone di solito lavora con alcune stringhe normali senza caratteri insoliti e quindi il metodo è il modo più semplice e veloce per andare.
da Long a byte []:
byte[] arr = String.valueOf(longVar).getBytes();
da byte [] a Long:
long longVar = Long.valueOf(new String(byteArr)).longValue();
Se si sta già utilizzando un OutputStream
per scrivere nel socket, DataOutputStream potrebbe essere adatto. Ecco un esempio:
// Assumes you are currently working with a SocketOutputStream.
SocketOutputStream outputStream = ...
long longValue = ...
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeLong(longValue);
dataOutputStream.flush();
Ci sono metodi simili per short
, int
, float
, ecc Si può quindi utilizzare DataInputStream sul lato ricevente.
Con ByteBuffer.allocate (8) .putLong (obj) .array ():
public byte[] toBytes(Long obj) {
if (obj != null) {
return ByteBuffer.allocate(8).putLong(obj).array();
return null;
}
Fonte:
Per molti altri esempi di utilizzo di ByteBuffer:
Ecco un altro modo per convertire byte[]
in long
Java 8 o versioni successive:
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));
}
La conversione di a long
può essere espressa come i bit di ordine superiore e inferiore di due valori interi soggetti a OR bit a bit. Nota che toUnsignedLong
è della Integer
classe e la prima chiamata a toUnsignedLong
potrebbe essere superflua.
Anche la conversione opposta può essere srotolata, come altri hanno già detto.
Estensioni Kotlin per tipi Long e 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()
}
Puoi vedere il codice completo nella mia libreria https://github.com/ArtemBotnev/low-level-extensions