Diziden Byte Dizine Java Serileştirilebilir Nesne


292

Diyelim ki serileştirilebilir bir sınıfım var AppMessage.

byte[]Alınan baytlardan yeniden oluşturulduğu başka bir makineye soket olarak iletmek istiyorum .

Bunu nasıl başarabilirim?


5
Neden böyle byte[]? Neden sadece doğrudan sokete yazıp ObjectOutputStreamokuyamıyorsunuz ObjectInputStream?
Lorne Marquis

apache deve kullanın
el NOD el

1
new ObjectMapper().writeValueAsBytes(JAVA_OBJECT_HERE)
Asad Shakeel

Yanıtlar:


411

Gönderilecek bayt dizisini hazırlayın:

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

Bayt dizisinden nesne oluşturma:

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
Soruyu bu şekilde okumadım. Bana göre onun sorunu, nesneyi bir bayta [] nasıl dönüştüreceğidir - nasıl gönderileceği değil.
Taylor Leese

1
Taylor: evet doğru anladın. nesneyi bir bayt [] haline getirmek ve iletmek istiyorum. Lütfen bu baytın [] bir nesneye nasıl dönüştürüleceğine ilişkin kodu da verebilir misiniz?
iTEgg

Sistem kaynaklarını serbest bırakmak için lütfen her zaman akışı kapatın. (
Kodda

bu serileştirilemediğim nesnelerle çalışabilir mi?
KJW

2
ObjectInput, ObjectOuput, ByteArrayOutputStreamVe ByteArrayInputStreamtüm uygulamak AutoCloseableo iyi bir uygulama yanlışlıkla bunları kapatmadan eksik önlemek için kullanmak olmaz, arayüz? (Ben merak ediyorum neden olduğunu, tamamen emin bu en iyi yöntem ise değilim.) Örnek: try(ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutput out = new ObjectOutputStream(bos)){ /*Do stuff*/ }catch(IOException e){/*suppress exception*/}. Ayrıca finalmadde ve ek maddesine olan ihtiyacı da ortadan kaldırır try-catch.
Ludvig Rydahl

308

Bunu yapmanın en iyi yolu SerializationUtilsApache Commons Lang'dan kullanmaktır .

Serileştirmek için:

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

Serisini kaldırmak için:

YourObject yourObject = SerializationUtils.deserialize(data)

Belirtildiği gibi, bu Commons Lang kütüphanesini gerektirir. Gradle kullanılarak içe aktarılabilir:

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

Uzman:

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

Jar dosyası

Ve burada bahsedilen daha fazla yol

Alternatif olarak, tüm koleksiyon içe aktarılabilir. Bu bağlantıya bakın


56
Ek yük mü eklendi? Bu noktada tekerleği yeniden inşa edebilir. Ciddi olarak, bu tek astarı anlamak ve olası hataları azaltmak çok daha kolaydır (akışı doğru zamanda kapatmamak ve ne olursa olsun).
ALOToverflow

2
En iyi yol, size aşağıdakileri sunan ortak bir kütüphane kullanmanızdır: 1) Sağlamlık: İnsanlar bunu kullanmaktadır ve bu nedenle çalışması onaylanmıştır. 2) Sadece 1 satır ile yukarıdaki (en popüler cevap) yapar, böylece kodunuz temiz kalır. 3) Çünkü Dan öyle dedi. 4) Sadece 3 :-) ile ilgili şaka yapıyorum
Lawrence

2
Ne yazık ki, yöntem çıktı boyutunu 1024 ile sınırlar. Bir dosyanın bir bayt akışına dönüştürülmesi gerekiyorsa, bunu kullanmayın.
Abilash

Bunu mikro hizmetler için tercih etmem. Kütüphane onları doğrudan yöntemlerden daha ağır hale getirebilir.
Zon

89

Java> = 7 kullanıyorsanız, denemeyi kaynaklarla kullanarak kabul edilen çözümü geliştirebilirsiniz :

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

Ve tam tersi:

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

7

@Erial yanıtında belirtildiği gibi, nesneyi byte [] ve tersine dönüştürmek için ApacheUtils tarafından serileştirme ve serisini kaldırma yöntemiyle SerializationUtils tarafından yapılabilir .

Bir nesneyi serileştirerek bayt [] biçimine dönüştürmek için:

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

Deserialize ederek byte [] öğesini nesneye dönüştürmek için ::

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

Org-apache-commons-lang.jar'ı indirmek için bağlantıya tıklayın

.Jar dosyasını tıklatarak entegre edin:

DosyaAdı -> Medule Ayarlarını Aç -> Modülünüzü seçin -> Bağımlılıklar -> Jar dosyası ekle ve işiniz bitti.

Umarım bu yardımcı olur .


3
asla böyle bir bağımlılık eklemeyin, bağımlılığı indirmek için maven / gradle kullanın ve oluşturma yoluna ekleyin
Daniel Bo

4

SerializationUtils aracını da kullanmanızı öneririm. @Alashlash tarafından yanlış bir yorumda ajust yapmak istiyorum. SerializationUtils.serialize()Yöntem olduğu değil burada başka bir cevap aykırı 1.024 bayt, sınırlı.

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

İlk bakışta that new ByteArrayOutputStream(1024)bunun sadece sabit bir boyuta izin vereceğini düşünebilirsiniz . Ancak, 'e yakından bakarsanız ByteArrayOutputStream, akışın gerekirse büyüyeceğini anlayacaksınız:

Bu sınıf, verilerin bir bayt dizisine yazıldığı bir çıkış akışı uygular. Veri yazılırken arabellek otomatik olarak büyür. Veriler toByteArray()ve kullanılarak alınabilir toString().


tersini nasıl ekleyebilirim? itiraz etmek için byte []? Başkalarının da buna sahip olduğunu biliyorum, ancak cevabınızı daha çok seviyorum ve serileştirmenin işe yaramasını sağlayamıyorum. Her durumda null döndürmekten kaçınmak istiyorum.
Tobias Kolb

1

Soketler üzerinden bayt [] olarak başka bir makineye iletmek istiyorum

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

burada alınan baytlardan yeniden oluşturulur.

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

1

Bir başka ilginç yöntem ise com.fasterxml.jackson.databind.ObjectMapper

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

Maven Bağımlılığı

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

1

Bahar Çerçevesi org.springframework.util.SerializationUtils

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

1

Eğer yay kullanıyorsanız, yay çekirdeğinde bir util sınıfı vardır. Sadece yapabilirsin

import org.springframework.util.SerializationUtils;

byte[] bytes = SerializationUtils.serialize(anyObject);
Object object = SerializationUtils.deserialize(bytes);

0

java 8+ ile kod örneği:

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

Güzel bir bağımlılık istemiyorsanız kopyala-yapıştır çözümü. Aşağıdaki kodu alın.

Misal

MyObject myObject = ...

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

Kaynak

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

Bu, herkesin bunu üretimde kullanmak istemesi durumunda kabul edilen cevabın optimize edilmiş bir kod şeklidir:

    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 {

    }




}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.