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?


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

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


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

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 .


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().


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

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>

1

Kerangka Pegas org.springframework.util.SerializationUtils

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

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

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

}

}

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

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 {

    }




}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.