web-dev-qa-db-fra.com

Comment convertir une longueur en octet [] et une valeur de retour dans java

Comment convertir un long en octet [] et revenir en Java? J'essaye de convertir un long en octet [] afin de pouvoir envoyer l'octet [] via une connexion TCP. De l'autre côté, je veux prendre cet octet [] et le reconvertir en double. Des conseils seraient appréciés.

128
Emre801
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();
}

Ou enveloppé dans une classe pour éviter de créer à plusieurs reprises 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();
    }
}

Étant donné que cela devient si populaire, je tiens à mentionner que je pense que vous feriez mieux d'utiliser une bibliothèque comme Guava dans la grande majorité des cas. Et si vous avez une étrange opposition aux bibliothèques, vous devriez probablement envisager cette réponse d’abord pour les solutions natives Java. Je pense que le principal objectif de ma réponse est que vous n'avez pas à vous soucier de l'endurance du système vous-même.

195
Brad Mace

Vous pouvez utiliser les méthodes de conversion en octets de Google Guava .

Exemple:

byte[] bytes = Longs.toByteArray(12345L);
74
Sonson123

J'ai testé la méthode ByteBuffer contre des opérations simples au niveau des bits, mais celle-ci est nettement plus rapide.

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(byte[] b) {
    long result = 0;
    for (int i = 0; i < 8; i++) {
        result <<= 8;
        result |= (b[i] & 0xFF);
    }
    return result;
}
70
Wytze

Pourquoi avez-vous besoin de l'octet []? pourquoi ne pas simplement l'écrire dans la prise?

Je suppose que vous voulez dire long plutôt que long, ce dernier doit autoriser les valeurs nulles.

DataOutputStream dos = new DataOutputStream(
     new BufferedOutputStream(socket.getOutputStream()));
dos.writeLong(longValue);

DataInputStream dis = new DataInputStream(
     new BufferedInputStream(socket.getInputStream()));
long longValue = dis.readLong();
15
Peter Lawrey

Si vous recherchez une version rapide déroulée, faites-le, en supposant un tableau d'octets appelé "b" d'une longueur de 8:

octet [] -> 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 -> octet [] comme contrepartie exacte de ce qui précède

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)};
13
Michael Böckling

Il suffit d'écrire le long d'un DataOutputStream avec un sous-jacent ByteArrayOutputStream . À partir de ByteArrayOutputStream, vous pouvez obtenir le tableau d'octets via 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));       
        }
}

Fonctionne pour les autres primitives en conséquence.

Astuce: Pour TCP, vous n'avez pas besoin de l'octet [] manuellement. Vous utiliserez un socket socket et ses flux

OutputStream os=socket.getOutputStream(); 
DataOutputStream dos=new DataOutputStream(os);
dos.writeLong(l);
//etc ..

au lieu.

4
Michael Konietzka

Vous pouvez utiliser l'implémentation de org.Apache.hadoop.hbase.util.Bytes http://hbase.Apache.org/apidocs/org/Apache/hadoop/hbase/util/Bytes.html

Le code source est ici:

http://grepcode.com/file/repository.cloudera.com/content/repositories/releases/com.cloudera.hbase/hbase/0.89.20100924-28/org/Apache/hadoop/hbase/util/ Bytes.Java # Bytes.toBytes% 28long% 29

Recherchez les méthodes toLong et toBytes.

Je crois que la licence du logiciel vous permet de prendre des parties du code et de les utiliser, mais veuillez vérifier cela.

4
Marquez
 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;
    }
3
maziar

Je vais ajouter une autre réponse qui est la plus rapide possible (oui, même plus que la réponse acceptée), MAIS cela ne fonctionnera pas pour chaque cas. TOUTEFOIS, cela fonctionnera pour tous les scénarios imaginables:

Vous pouvez simplement utiliser String comme intermédiaire. Notez que ceci vous donnera le résultat correct même s'il semble que l'utilisation de String puisse donner des résultats incorrects aussi longtemps que vous savez que vous travaillez avec des chaînes "normales". Ceci est une méthode pour augmenter l'efficacité et simplifier le code qui doit en retour utiliser certaines hypothèses sur les chaînes de données sur lesquelles il opère.

Con de l'utilisation de cette méthode: Si vous travaillez avec des caractères ASCII comme ces symboles au début de la table ASCII, les lignes suivantes risquent d'échouer , mais avouons-le - vous ne les utiliserez probablement jamais de toute façon.

Pro utilisant cette méthode: Rappelez-vous que la plupart des gens travaillent habituellement avec des chaînes normales sans caractères inhabituels et que la méthode est le moyen le plus simple et le plus rapide à suivre.

de long en octet []:

byte[] arr = String.valueOf(longVar).getBytes();

de byte [] à Long:

long longVar = Long.valueOf(new String(byteArr)).longValue();
2
Yonatan Nir

Si vous utilisez déjà un OutputStream pour écrire dans le socket, alors DataOutputStream peut convenir. Voici un exemple:

// Assumes you are currently working with a SocketOutputStream.

SocketOutputStream outputStream = ...
long longValue = ...

DataOutputStream dataOutputStream = new DataOutputStream(outputStream);

dataOutputStream.writeLong(longValue);
dataOutputStream.flush();

Il existe des méthodes similaires pour short, int, float, etc. Vous pouvez ensuite utiliser DataInputStream du côté de la réception.

1
Matt Solnit