¿Cómo se convierte una long
a una byte[]
y de vuelta en Java?
Estoy tratando de convertir a long
a byte[]
para poder enviarlo a byte[]
través de una conexión TCP. Por otro lado, quiero tomar eso byte[]
y convertirlo nuevamente en a double
.
¿Cómo se convierte una long
a una byte[]
y de vuelta en Java?
Estoy tratando de convertir a long
a byte[]
para poder enviarlo a byte[]
través de una conexión TCP. Por otro lado, quiero tomar eso byte[]
y convertirlo nuevamente en a double
.
Respuestas:
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 envuelto en una clase para evitar crear repetidamente ByteBuffers:
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();
}
}
Como esto se está volviendo tan popular, solo quiero mencionar que creo que es mejor usar una biblioteca como Guava en la gran mayoría de los casos. Y si tiene alguna oposición extraña a las bibliotecas, probablemente debería considerar esta respuesta primero para las soluciones nativas de Java. Creo que lo más importante que tiene mi respuesta es que no tiene que preocuparse por la endianidad del sistema usted mismo.
Puede utilizar los métodos de conversión de bytes de Google Guava .
Ejemplo:
byte[] bytes = Longs.toByteArray(12345L);
Probé el método ByteBuffer contra operaciones simples a nivel de bit pero este último es significativamente más rápido.
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]
el valor de byte se convertirá primero a largo, lo que sí firma la extensión. Un byte con valor -128 (hex 0x80
) se convertirá en un largo con valor -128 (hex 0xFFFF FFFF FFFF FF80
). Primero después de la conversión son los valores o: ed juntos. Uso de bit a bit-y protege contra esto convirtiendo primero el byte a un int y el corte de la extensión de signo: (byte)0x80 & 0xFF ==> (int)0xFFFF FF80 & 0xFF ==> (int) 0x80
. Por qué los bytes están firmados en Java es un poco misterioso para mí, pero supongo que encaja con otros tipos.
Si está buscando una versión rápida desenrollada, esto debería funcionar, suponiendo una matriz de bytes llamada "b" con una longitud de 8:
byte [] -> largo
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);
largo -> byte [] como contraparte exacta de lo anterior
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)};
¿Por qué necesitas el byte []? ¿Por qué no escribirlo en el zócalo?
Supongo que quiere decir largo en lugar de largo , este último debe permitir valores nulos.
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(socket.getOutputStream()));
dos.writeLong(longValue);
DataInputStream dis = new DataInputStream(
new BufferedInputStream(socket.getInputStream()));
long longValue = dis.readLong();
byte[]
es solo un medio para ese fin.
ByteBuffer
que, según los documentos "El orden inicial de un búfer de bytes es siempre BIG_ENDIAN.
Simplemente escriba el largo en un DataOutputStream con un ByteArrayOutputStream subyacente . Desde ByteArrayOutputStream puede obtener la matriz de bytes a través de 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));
}
}
Funciona para otras primitivas en consecuencia.
Sugerencia: para TCP no necesita el byte [] manualmente. Usarás un Socketsocket
y sus flujos
OutputStream os=socket.getOutputStream();
DataOutputStream dos=new DataOutputStream(os);
dos.writeLong(l);
//etc ..
en lugar.
Puede usar la implementación en org.apache.hadoop.hbase.util.Bytes http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/util/Bytes.html
El código fuente está aquí:
Busque los métodos toLong y toBytes.
Creo que la licencia de software le permite tomar partes del código y usarlo, pero verifíquelo.
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;
}
Agregaré otra respuesta que sea la más rápida posible ׂ (sí, incluso más que la respuesta aceptada), PERO no funcionará en todos los casos. SIN EMBARGO, funcionará para cada escenario concebible:
Simplemente puede usar String como intermedio. Tenga en cuenta que esto le dará el resultado correcto a pesar de que parece que el uso de String podría producir resultados incorrectos MIENTRAS SABE QUE ESTÁ TRABAJANDO CON STRINGS "NORMALES". Este es un método para aumentar la efectividad y simplificar el código, que a cambio debe usar algunas suposiciones en las cadenas de datos en las que opera.
Contras de usar este método: si está trabajando con algunos caracteres ASCII como estos símbolos al comienzo de la tabla ASCII, las siguientes líneas pueden fallar, pero seamos sinceros, probablemente nunca las usará de todos modos.
Pro de usar este método: recuerde que la mayoría de las personas generalmente trabajan con algunas cadenas normales sin caracteres inusuales y luego el método es la forma más simple y rápida de hacerlo.
de Long a byte []:
byte[] arr = String.valueOf(longVar).getBytes();
del byte [] a Long:
long longVar = Long.valueOf(new String(byteArr)).longValue();
Si ya está utilizando un OutputStream
para escribir en el socket, DataOutputStream podría ser una buena opción. Aquí hay un ejemplo:
// Assumes you are currently working with a SocketOutputStream.
SocketOutputStream outputStream = ...
long longValue = ...
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeLong(longValue);
dataOutputStream.flush();
Hay métodos similares para short
, int
, float
, etc. A continuación, puede utilizar DataInputStream en el lado receptor.
Con ByteBuffer.allocate (8) .putLong (obj) .array ():
public byte[] toBytes(Long obj) {
if (obj != null) {
return ByteBuffer.allocate(8).putLong(obj).array();
return null;
}
Fuente:
Para muchos otros ejemplos de uso de ByteBuffer:
Aquí hay otra forma de convertir byte[]
a long
Java 8 o más reciente:
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 conversión de a long
puede expresarse como los bits de orden alto y bajo de dos valores enteros sujetos a un OR por bits. Tenga en cuenta que el toUnsignedLong
es de la Integer
clase y la primera llamada a toUnsignedLong
puede ser superflua.
La conversión opuesta también se puede desenrollar, como han mencionado otros.
Extensiones Kotlin para tipos Long y 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()
}
Puede ver el código completo en mi biblioteca https://github.com/ArtemBotnev/low-level-extensions