Javaシリアライズ可能オブジェクトからバイト配列


292

シリアル化可能なクラスがあるとしましょう AppMessage

byte[]ソケットを介して別のマシンに送信し、受信したバイトから再構築します。

どうすればこれを達成できますか?


5
なぜbyte[]ですか?なぜそれを直接ソケットに書き込んでObjectOutputStream、それを読んでみObjectInputStreamませんか?
ローン侯爵2015

アパッチキャメルを使用する
NODの手

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

回答:


411

送信するバイト配列を準備します。

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

バイト配列からオブジェクトを作成します。

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
それは私が質問を読む方法ではありません。私には、彼の問題はオブジェクトをbyte []に​​変換する方法にあるように思えます。送信する方法ではありません。
テイラーリース

1
テイラー:そうだね。オブジェクトをbyte []に​​変換して送信したい。このbyte []をオブジェクトに変換する方法に関するコードも提供していただけますか?
iTEgg

常にストリームを閉じて、システムリソースを解放してください。(コードで編集)
LuckyMalaka 2011

これは、シリアライズ可能を実装できないオブジェクトで機能しますか?
KJW 2011年

2
ObjectInputObjectOuputByteArrayOutputStreamおよびByteArrayInputStreamすべての実装AutoCloseableインタフェースを、誤ってそれらを閉じる行方不明避けるためにそれを使用することをお勧めではないでしょうか?(これがベストプラクティスであるかどうかは完全にはわかりません。そのため、疑問に思っています。)例:try(ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutput out = new ObjectOutputStream(bos)){ /*Do stuff*/ }catch(IOException e){/*suppress exception*/}。また、final条項とその追加の必要性を排除しますtry-catch
Ludvig Rydahl

307

これを行う最良の方法はSerializationUtils、Apache Commons Langから使用することです。

シリアル化するには:

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

逆シリアル化するには:

YourObject yourObject = SerializationUtils.deserialize(data)

前述のように、これにはCommons Langライブラリが必要です。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>

JARファイル

そしてここで言及されたより多くの方法

または、コレクション全体をインポートすることもできます。参照してくださいこのリンクを


56
追加されたオーバーヘッド?この時点でホイールを再構築することもできます。真剣に、このワンライナーを理解し、起こり得るエラー(適切なタイミングでストリームを閉じないなど)を減らすのははるかに簡単です。
ALOToverflow 2013

2
提供する共通ライブラリを使用するための最良の方法:1)堅牢性:人々はこれを使用しており、動作することが検証されています。2)上記(最も一般的な答え)を1行だけで実行するため、コードはクリーンなままです。3)ダンがそう言ったから。4)3に関しては冗談です:-)
Lawrence

2
残念ながら、このメソッドは出力サイズを1024に制限しています。ファイルをバイトストリームに変換する必要がある場合は、これを使用しないことをお勧めします。
Abilash 2016年

マイクロサービスにはこれを好みません。ライブラリは、直接的な方法よりもサイズが大きくなる可能性があります。
Zon

89

Java> = 7を使用している場合は、try with resourcesを使用して、受け入れられているソリューションを改善できます。

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

そしてその逆:

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

7

SerializationUtilsで実行できます@urisの回答で述べられているように、オブジェクトをbyte []に​​、またはその逆に変換するために、ApacheUtilsのserialize&deserializeメソッドを使用しで。

シリアル化してオブジェクトをbyte []に​​変換するには:

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

逆シリアル化によってbyte []をオブジェクトに変換するには::

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

org-apache-commons-lang.jarダウンロードするリンクをクリックします。

以下をクリックして.jarファイルを統合します。

FileName- > Medule設定を開く -> モジュールを選択 -> 依存関係 -> Jarファイル追加すれば完了です。

これがお役に立てば幸いです。


3
このような依存関係を追加しないでください。maven/ gradleを使用して依存関係をダウンロードし、ビルドパスに追加してください
Daniel Bo

4

SerializationUtilsツールの使用もお勧めします。@Abilashの間違ったコメントを調整したい。このSerializationUtils.serialize()方法は、ここでの別の回答とは異なり、1024バイトに制限されていません

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

一見new ByteArrayOutputStream(1024)すると、固定サイズしか許されないと思うかもしれません。しかし、をよく見ると、ByteArrayOutputStream必要に応じてストリームが大きくなることがわかります。

このクラスは、データがバイト配列に書き込まれる出力ストリームを実装します。データが書き込まれると、バッファは自動的に大きくなります。データはtoByteArray()およびを使用して 取得できますtoString()


逆を行う方法を追加できますか?だからオブジェクトにbyte []?他の人がこれを持っていることは知っていますが、あなたの答えがもっと好きで、逆シリアル化を機能させることができません。どのような場合でもnullを返さないようにします。
Tobias Kolb

1

ソケットを介して別のマシンにbyte []として送信したい

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

受信したバイトから再構築されます。

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

1

別の興味深い方法はからです com.fasterxml.jackson.databind.ObjectMapper

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

Mavenの依存関係

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

1

Spring Framework org.springframework.util.SerializationUtils

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

1

Springを使用している場合は、spring-coreでutilクラスを使用できます。簡単にできます

import org.springframework.util.SerializationUtils;

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

0

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

依存関係のないコピーと貼り付けのソリューションが必要な場合。以下のコードを入手してください。

MyObject myObject = ...

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

ソース

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

これは、誰かが本番環境でこれを使用したい場合に備えて、受け入れられた回答の最適化されたコード形式です。

    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 {

    }




}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.