Java Serializable Object to Byte Array

292

Angenommen, ich habe eine serialisierbare Klasse AppMessage.

Ich möchte es als byte[]Over-Socket an eine andere Maschine senden, wo es aus den empfangenen Bytes neu aufgebaut wird.

Wie könnte ich das erreichen?

iTEgg
quelle
5
Warum als byte[]? Warum nicht einfach mit direkt in die Steckdose schreiben ObjectOutputStreamund mit lesen ObjectInputStream?
Marquis von Lorne
benutze Apache Kamel
die Hand von NOD
1
new ObjectMapper().writeValueAsBytes(JAVA_OBJECT_HERE)
Asad Shakeel

Antworten:

411

Bereiten Sie das zu sendende Byte-Array vor:

ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = null;
try {
  out = new ObjectOutputStream(bos);   
  out.writeObject(yourObject);
  out.flush();
  byte[] yourBytes = bos.toByteArray();
  ...
} finally {
  try {
    bos.close();
  } catch (IOException ex) {
    // ignore close exception
  }
}

Erstellen Sie ein Objekt aus einem Byte-Array:

ByteArrayInputStream bis = new ByteArrayInputStream(yourBytes);
ObjectInput in = null;
try {
  in = new ObjectInputStream(bis);
  Object o = in.readObject(); 
  ...
} finally {
  try {
    if (in != null) {
      in.close();
    }
  } catch (IOException ex) {
    // ignore close exception
  }
}
Taylor Leese
quelle
48
So habe ich die Frage nicht gelesen. Für mich klingt es so, als ob sein Problem darin besteht, das Objekt in ein Byte [] zu konvertieren - nicht wie es gesendet wird.
Taylor Leese
1
Taylor: Ja, du hast es richtig gemacht. Ich möchte das Objekt in ein Byte [] verwandeln und es übertragen. Können Sie bitte auch den Code angeben, wie dieses Byte [] in ein Objekt umgewandelt werden kann?
iTEgg
Bitte schließen Sie immer jeden Stream, um die Systemressourcen freizugeben. (Im Code bearbeitet)
LuckyMalaka
Kann dies mit Objekten funktionieren, die ich nicht serialisierbar implementieren kann?
KJW
2
ObjectInput, ObjectOuput, ByteArrayOutputStreamUnd ByteArrayInputStreamalle implementieren AutoCloseableSchnittstelle, wäre es nicht gut , die Praxis umgesetzt werden , es zu benutzen, damit sie nicht versehentlich fehlt schließen? (Ich bin mir nicht ganz sicher, ob dies die beste Vorgehensweise ist. Deshalb frage ich mich.) Beispiel : try(ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutput out = new ObjectOutputStream(bos)){ /*Do stuff*/ }catch(IOException e){/*suppress exception*/}. Es beseitigt auch die Notwendigkeit der finalKlausel und ihrer zusätzlichen try-catch.
Ludvig Rydahl
307

Der beste Weg, dies zu tun, ist die Verwendung SerializationUtilsvon Apache Commons Lang .

So serialisieren Sie:

byte[] data = SerializationUtils.serialize(yourObject);

Deserialisieren:

YourObject yourObject = SerializationUtils.deserialize(data)

Wie bereits erwähnt, ist hierfür die Commons Lang-Bibliothek erforderlich. Es kann mit Gradle importiert werden:

compile 'org.apache.commons:commons-lang3:3.5'

Maven:

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.5</version>
</dependency>

Glasdatei

Und weitere hier erwähnte Möglichkeiten

Alternativ kann die gesamte Sammlung importiert werden. Verweisen Sie auf diesen Link

Uris
quelle
56
Overhead hinzugefügt? Könnte auch das Rad an dieser Stelle wieder aufbauen. Im Ernst, es ist viel einfacher, diesen Einzeiler zu verstehen und mögliche Fehler zu reduzieren (z. B. den Stream nicht zum richtigen Zeitpunkt zu schließen und so weiter).
ALOToverflow
2
Der beste Weg, weil Sie eine gemeinsame Bibliothek verwenden, die Ihnen Folgendes bietet: 1) Robustheit: Die Benutzer verwenden diese und daher ist sie für die Arbeit validiert. 2) Die oben genannte (beliebteste Antwort) wird mit nur 1 Zeile ausgeführt, damit Ihr Code sauber bleibt. 3) Weil Dan es gesagt hat. 4) Ich mache nur Spaß in Bezug auf 3 :-)
Lawrence
2
Leider beschränkt die Methode die Ausgabegröße auf 1024. Wenn eine Datei in einen Bytestream konvertiert werden muss, verwenden Sie diese besser nicht.
Abilash
Ich würde diesen nicht für Microservices bevorzugen. Die Bibliothek könnte sie schwerer machen als direkte Methoden.
Zon
89

Wenn Sie Java> = 7 verwenden, können Sie die akzeptierte Lösung mithilfe von try with resources verbessern :

private byte[] convertToBytes(Object object) throws IOException {
    try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
         ObjectOutput out = new ObjectOutputStream(bos)) {
        out.writeObject(object);
        return bos.toByteArray();
    } 
}

Und umgekehrt:

private Object convertFromBytes(byte[] bytes) throws IOException, ClassNotFoundException {
    try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
         ObjectInput in = new ObjectInputStream(bis)) {
        return in.readObject();
    } 
}
Víctor Romero
quelle
7

Kann von SerializationUtils , von der Serialize & Deserialize-Methode von ApacheUtils durchgeführt werden, um ein Objekt in Byte [] zu konvertieren und umgekehrt, wie in der Antwort von @uris angegeben.

So konvertieren Sie ein Objekt durch Serialisierung in Byte []:

byte[] data = SerializationUtils.serialize(object);

Um Byte [] durch Deserialisieren in ein Objekt umzuwandeln ::

Object object = (Object) SerializationUtils.deserialize(byte[] data)

Klicken Sie auf den Link, um org-apache-commons-lang.jar herunterzuladen

Integrieren Sie die JAR-Datei, indem Sie auf Folgendes klicken:

Dateiname -> Medule-Einstellungen öffnen -> Modul auswählen -> Abhängigkeiten -> Jar-Datei hinzufügen und fertig.

Hoffe das hilft .

Pankaj Lilan
quelle
3
Fügen Sie niemals eine solche Abhängigkeit hinzu, verwenden Sie maven / gradle, um die Abhängigkeit herunterzuladen und sie dem Erstellungspfad hinzuzufügen
Daniel Bo
4

Ich empfehle auch, das SerializationUtils-Tool zu verwenden. Ich möchte einen falschen Kommentar von @Abilash korrigieren. Die SerializationUtils.serialize()Methode ist entgegen einer anderen Antwort hier nicht auf 1024 Bytes beschränkt.

public static byte[] serialize(Object object) {
    if (object == null) {
        return null;
    }
    ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
    try {
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(object);
        oos.flush();
    }
    catch (IOException ex) {
        throw new IllegalArgumentException("Failed to serialize object of type: " + object.getClass(), ex);
    }
    return baos.toByteArray();
}

Auf den ersten Blick , denken Sie vielleicht, dass dies new ByteArrayOutputStream(1024)nur eine feste Größe zulässt. Wenn Sie sich das genauer ansehen ByteArrayOutputStream, werden Sie feststellen, dass der Stream bei Bedarf wächst:

Diese Klasse implementiert einen Ausgabestream, in den die Daten in ein Byte-Array geschrieben werden. Der Puffer wächst automatisch, wenn Daten darauf geschrieben werden. Die Daten können mit toByteArray()und abgerufen werden toString().

gzg_55
quelle
Können Sie hinzufügen, wie man das Gegenteil macht? also Byte [] zum Objekt? Ich weiß, dass andere dies haben, aber ich mag Ihre Antwort viel mehr und ich kann die Deserialisierung nicht zum Laufen bringen. Ich möchte auf jeden Fall vermeiden, null zurückzugeben.
Tobias Kolb
1

Ich möchte es als Byte [] über Sockets an eine andere Maschine übertragen

// When you connect
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
// When you want to send it
oos.writeObject(appMessage);

wo es aus den empfangenen Bytes neu aufgebaut wird.

// When you connect
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
// When you want to receive it
AppMessage appMessage = (AppMessage)ois.readObject();
Marquis von Lorne
quelle
1

Eine andere interessante Methode ist von com.fasterxml.jackson.databind.ObjectMapper

byte[] data = new ObjectMapper().writeValueAsBytes(JAVA_OBJECT_HERE)

Maven-Abhängigkeit

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>
Asad Shakeel
quelle
1

Frühlingsrahmen org.springframework.util.SerializationUtils

byte[] data = SerializationUtils.serialize(obj);
xxg
quelle
1

Wenn Sie Feder verwenden, gibt es eine Util-Klasse in Spring-Core. Sie können einfach tun

import org.springframework.util.SerializationUtils;

byte[] bytes = SerializationUtils.serialize(anyObject);
Object object = SerializationUtils.deserialize(bytes);
Supun Wijerathne
quelle
0

Codebeispiel mit Java 8+:

public class Person implements Serializable {

private String lastName;
private String firstName;

public Person() {
}

public Person(String firstName, String lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

public void setFirstName(String firstName) {
    this.firstName = firstName;
}

public String getFirstName() {
    return firstName;
}

public String getLastName() {
    return lastName;
}

public void setLastName(String lastName) {
    this.lastName = lastName;
}

@Override
public String toString() {
    return "firstName: " + firstName + ", lastName: " + lastName;
}
}


public interface PersonMarshaller {
default Person fromStream(InputStream inputStream) {
    try (ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)) {
        Person person= (Person) objectInputStream.readObject();
        return person;
    } catch (IOException | ClassNotFoundException e) {
        System.err.println(e.getMessage());
        return null;
    }
}

default OutputStream toStream(Person person) {
    try (OutputStream outputStream = new ByteArrayOutputStream()) {
        ObjectOutput objectOutput = new ObjectOutputStream(outputStream);
        objectOutput.writeObject(person);
        objectOutput.flush();
        return outputStream;
    } catch (IOException e) {
        System.err.println(e.getMessage());
        return null;
    }

}

}
Mohamed.Abdo
quelle
0

Für den Fall, dass Sie eine nette Lösung zum Kopieren und Einfügen ohne Abhängigkeiten wünschen. Holen Sie sich den Code unten.

Beispiel

MyObject myObject = ...

byte[] bytes = SerializeUtils.serialize(myObject);
myObject = SerializeUtils.deserialize(bytes);

Quelle

import java.io.*;

public class SerializeUtils {

    public static byte[] serialize(Serializable value) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        try(ObjectOutputStream outputStream = new ObjectOutputStream(out)) {
            outputStream.writeObject(value);
        }

        return out.toByteArray();
    }

    public static <T extends Serializable> T deserialize(byte[] data) throws IOException, ClassNotFoundException {
        try(ByteArrayInputStream bis = new ByteArrayInputStream(data)) {
            //noinspection unchecked
            return (T) new ObjectInputStream(bis).readObject();
        }
    }
}
Ilya Gazman
quelle
0

Dies ist nur eine optimierte Codeform der akzeptierten Antwort, falls jemand dies in der Produktion verwenden möchte:

    public static void byteArrayOps() throws IOException, ClassNotFoundException{

    String str="123";
     byte[] yourBytes = null;

    // Convert to byte[]

    try(ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream out =  new ObjectOutputStream(bos);) {


      out.writeObject(str);
      out.flush();
      yourBytes = bos.toByteArray();

    } finally {

    }

    // convert back to Object

    try(ByteArrayInputStream bis = new ByteArrayInputStream(yourBytes);
            ObjectInput in = new ObjectInputStream(bis);) {

      Object o = in.readObject(); 

    } finally {

    }




}
Nishant_Singh
quelle