Objek Serializable Java ke Byte Array

292

Katakanlah saya memiliki kelas serializable AppMessage.

Saya ingin mengirimkannya sebagai byte[]soket ke mesin lain di mana ia dibangun kembali dari byte yang diterima.

Bagaimana saya bisa mencapai ini?

iTEgg
sumber
5
Mengapa seperti byte[]? Mengapa tidak langsung menulis saja ke soket ObjectOutputStream, dan membacanya dengan ObjectInputStream?
Marquis of Lorne
gunakan apache unta
tangan NOD
1
new ObjectMapper().writeValueAsBytes(JAVA_OBJECT_HERE)
Asad Shakeel

Jawaban:

411

Siapkan array byte untuk dikirim:

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
  }
}

Buat objek dari array byte:

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
sumber
48
Bukan begitu saya membaca pertanyaan. Bagi saya kedengarannya masalahnya adalah bagaimana mengkonversi objek ke byte [] - bukan cara mengirimnya.
Taylor Leese
1
Taylor: ya Anda benar. saya ingin mengubah objek menjadi byte [] dan mengirimkannya. dapatkah Anda juga memberikan kode mengenai cara mengubah byte ini [] menjadi objek?
iTEgg
Harap tutup selalu aliran apa pun untuk melepaskan sumber daya sistem. (Diedit dalam kode)
LuckyMalaka
dapatkah ini bekerja dengan objek yang tidak dapat saya implementasikan serializable?
KJW
2
ObjectInput, ObjectOuput, ByteArrayOutputStreamDan ByteArrayInputStreamsemua mengimplementasikan AutoCloseableantarmuka, tidak akan itu akan praktik yang baik untuk menggunakannya untuk menghindari hilang menutup mereka dengan kesalahan? (Saya tidak sepenuhnya yakin apakah ini adalah praktek terbaik, itu sebabnya aku bertanya-tanya.) Contoh: try(ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutput out = new ObjectOutputStream(bos)){ /*Do stuff*/ }catch(IOException e){/*suppress exception*/}. Ini juga menghilangkan kebutuhan untuk finalklausa dan tambahannya try-catch.
Ludvig Rydahl
307

Cara terbaik untuk melakukannya adalah menggunakan SerializationUtilsdari Apache Commons Lang .

Membuat cerita bersambung:

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

Deserialize:

YourObject yourObject = SerializationUtils.deserialize(data)

Seperti yang disebutkan, ini membutuhkan perpustakaan Commons Lang. Itu dapat diimpor menggunakan Gradle:

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>

File jar

Dan banyak lagi cara yang disebutkan di sini

Atau, seluruh koleksi dapat diimpor. Lihat tautan ini

uris
sumber
56
Menambahkan overhead? Mungkin juga membangun kembali roda pada saat ini. Serius, jauh lebih mudah untuk memahami one-liner ini dan mengurangi kemungkinan kesalahan (seperti tidak menutup aliran pada waktu yang tepat dan yang lainnya).
ALOToverflow
2
Cara terbaik karena Anda menggunakan perpustakaan umum yang menawarkan Anda: 1) Robustness: Orang-orang menggunakan ini dan dengan demikian itu divalidasi untuk berfungsi. 2) Ia melakukan hal di atas (jawaban paling populer) dengan hanya 1 baris sehingga kode Anda tetap bersih. 3) Karena Dan berkata demikian. 4) Saya hanya bercanda tentang 3 :-)
Lawrence
2
Sayangnya, metode ini membatasi ukuran output ke 1024. Jika seseorang perlu mengkonversi file ke aliran byte, lebih baik tidak menggunakan ini.
Abilash
Saya tidak akan memilih yang ini untuk layanan microser. Perpustakaan bisa membuat mereka lebih berat ukurannya, daripada metode langsung.
Zon
89

Jika Anda menggunakan Java> = 7, Anda dapat meningkatkan solusi yang diterima menggunakan coba dengan sumber daya :

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

Dan sebaliknya:

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
sumber
7

Dapat dilakukan dengan SerializationUtils , dengan metode serialisasi & deserialize oleh ApacheUtils untuk mengonversi objek ke byte [] dan sebaliknya, seperti yang dinyatakan dalam jawaban @uris.

Untuk mengonversi objek ke byte [] dengan membuat serial:

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

Untuk mengonversi byte [] ke objek dengan deserializing ::

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

Klik tautan untuk Unduh org-apache-commons-lang.jar

Integrasikan file .jar dengan mengklik:

FileName -> Buka Medule Settings -> Pilih modul Anda -> Dependensi -> Add file Jar dan Anda selesai.

Semoga ini bisa membantu .

Pankaj Lilan
sumber
3
jangan pernah menambahkan dependensi seperti ini, gunakan maven / gradle untuk mengunduh dependensi dan menambahkannya ke jalur build
Daniel Bo
4

Saya juga merekomendasikan untuk menggunakan alat SerializationUtils. Saya ingin membuat ajust pada komentar yang salah oleh @Abilash. The SerializationUtils.serialize()Metode ini tidak terbatas pada 1024 byte, bertentangan dengan jawaban lain di sini.

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

Pada pandangan pertama, Anda mungkin berpikir itu new ByteArrayOutputStream(1024)hanya akan memungkinkan ukuran yang tetap. Tetapi jika Anda mencermati ByteArrayOutputStream, Anda akan mengetahui aliran akan tumbuh jika perlu:

Kelas ini mengimplementasikan aliran output di mana data ditulis ke dalam array byte. Buffer secara otomatis tumbuh ketika data ditulis untuk itu. Data dapat diambil menggunakan toByteArray()dan toString().

gzg_55
sumber
dapatkah Anda menambahkan cara melakukan yang sebaliknya? jadi byte [] ke objek? Saya tahu orang lain memiliki ini, tetapi saya lebih menyukai jawaban Anda dan saya tidak bisa mendapatkan deserialisation untuk bekerja. Saya ingin menghindari pengembalian nol dalam hal apa pun.
Tobias Kolb
1

Saya ingin mengirimkannya sebagai byte [] melalui soket ke komputer lain

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

di mana itu dibangun kembali dari byte yang diterima.

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

Metode lain yang menarik adalah dari com.fasterxml.jackson.databind.ObjectMapper

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

Ketergantungan Maven

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

Kerangka Pegas org.springframework.util.SerializationUtils

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

Jika Anda menggunakan pegas, ada kelas util yang tersedia di pegas-inti. Anda cukup melakukannya

import org.springframework.util.SerializationUtils;

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

contoh kode dengan 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
sumber
0

Jika Anda menginginkan solusi copy-paste tanpa ketergantungan yang bagus. Ambil kode di bawah ini.

Contoh

MyObject myObject = ...

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

Sumber

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
sumber
0

Ini hanya bentuk kode yang dioptimalkan dari jawaban yang diterima jika ada yang ingin menggunakan ini dalam produksi:

    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
sumber