22

私はJavaでのソケットプログラミングについて学んでいます。DataOutputStreamを使用しているものと、を使用しているものがあるクライアント/サーバーアプリの例を見てきましたObjectOutputStream

2つの違いは何ですか?

パフォーマンスに違いはありますか?

4

4 に答える 4

30

DataInput / OutputStreamは、はるかに単純であるため、一般的にパフォーマンスが向上します。プリミティブタイプと文字列の読み取り/書き込みのみが可能です。

ObjectInput / OutputStreamは、プリミティブと同様に任意のオブジェクトタイプの読み取り/書き込みを行うことができます。効率は劣りますが、複雑なデータを送信する場合ははるかに使いやすくなります。

パフォーマンスが問題であることがわかるまでは、Object*Streamが最良の選択であると思います。

于 2012-07-17T11:01:02.823 に答える
11

これは、数年後もまだ答えを探している人に役立つかもしれません...最近のJVM(1.8_51)での私のテストによると、これは、doubleの巨大な配列の読み取り/書き込みObjectOutput/InputStreamよりも驚くほどほぼ2倍高速です。DataOutput/InputStream

以下は、1,000万アイテムの配列を書き込んだ結果です(100万の場合、結果は基本的に同じです)。完全を期すために、テキスト形式(BufferedWriter / Reader)も含めました。

TestObjectStream written 10000000 items, took: 409ms, or 24449.8778 items/ms, filesize 80390629b
TestDataStream written 10000000 items, took: 727ms, or 13755.1582 items/ms, filesize 80000000b
TestBufferedWriter written 10000000 items, took: 13700ms, or 729.9270 items/ms, filesize 224486395b

読む:

TestObjectStream read 10000000 items, took: 250ms, or 40000.0000 items/ms, filesize 80390629b
TestDataStream read 10000000 items, took: 424ms, or 23584.9057 items/ms, filesize 80000000b
TestBufferedWriter read 10000000 items, took: 6298ms, or 1587.8057 items/ms, filesize 224486395b

OracleはObjectStream、前回のJavaリリースでsを使用するためにJVMを大幅に最適化したと思います。これは、データの書き込み/読み取り(シリアル化を含む)の最も一般的な方法であり、Javaパフォーマンスのクリティカルパスにあるためです。

したがって、今日のように、DataStreamsを使用する理由はもうありません。「JVMの裏をかくことを試みないでください」、最も簡単な方法を使用してください。それはObjectStreams :)

テストのコードは次のとおりです。

class Generator {
    private int seed = 1235436537;
    double generate(int i) {
        seed = (seed + 1235436537) % 936855463;
        return seed / (i + 1.) / 524323.;
    }
}

class Data {
    public final double[] array;
    public Data(final double[] array) {
        this.array = array;
    }
}

class TestObjectStream {
    public void write(File dest, Data data) {
        try (ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(dest)))) {
            for (int i = 0; i < data.array.length; i++) {
                out.writeDouble(data.array[i]);
            }
        } catch (IOException e) {
            throw new RuntimeIoException(e);
        }
    }
    public void read(File dest, Data data) {
        try (ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(dest)))) {
            for (int i = 0; i < data.array.length; i++) {
                data.array[i] = in.readDouble();
            }
        } catch (IOException e) {
            throw new RuntimeIoException(e);
        }
    }
}

class TestDataStream {
    public void write(File dest, Data data) {
        try (DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dest)))) {
            for (int i = 0; i < data.array.length; i++) {
                out.writeDouble(data.array[i]);
            }
        } catch (IOException e) {
            throw new RuntimeIoException(e);
        }
    }
    public void read(File dest, Data data) {
        try (DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(dest)))) {
            for (int i = 0; i < data.array.length; i++) {
                data.array[i] = in.readDouble();
            }
        } catch (IOException e) {
            throw new RuntimeIoException(e);
        }
    }
}

class TestBufferedWriter {
    public void write(File dest, Data data) {
        try (BufferedWriter out = new BufferedWriter(new FileWriter(dest))) {
            for (int i = 0; i < data.array.length; i++) {
                out.write(Double.toString(data.array[i]));
                out.newLine();
            }
        } catch (IOException e) {
            throw new RuntimeIoException(e);
        }
    }
    public void read(File dest, Data data) {
        try (BufferedReader in = new BufferedReader(new FileReader(dest))) {
            String line = in.readLine();
            int i = 0;
            while (line != null) {
                if(!line.isEmpty()) {
                    data.array[i++] = Double.parseDouble(line);
                }
                line = in.readLine();
            }
        } catch (IOException e) {
            throw new RuntimeIoException(e);
        }
    }
}

@Test
public void testWrite() throws Exception {
    int N = 10000000;
    double[] array = new double[N];
    Generator gen = new Generator();
    for (int i = 0; i < array.length; i++) {
        array[i] = gen.generate(i);
    }
    Data data = new Data(array);

    Map<Class, BiConsumer<File, Data>> subjects = new LinkedHashMap<>();
    subjects.put(TestDataStream.class, new TestDataStream()::write);
    subjects.put(TestObjectStream.class, new TestObjectStream()::write);
    subjects.put(TestBufferedWriter.class, new TestBufferedWriter()::write);

    subjects.forEach((aClass, fileDataBiConsumer) -> {

        File f = new File("test." + aClass.getName());

        long start = System.nanoTime();
        fileDataBiConsumer.accept(f, data);
        long took = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);

        System.out.println(aClass.getSimpleName() + " written " + N + " items, took: " + took + "ms, or " + String.format("%.4f", (N / (double)took)) + " items/ms, filesize " + f.length() + "b");
    });
}


@Test
public void testRead() throws Exception {
    int N = 10000000;
    double[] array = new double[N];
    Data data = new Data(array);

    Map<Class, BiConsumer<File, Data>> subjects = new LinkedHashMap<>();
    subjects.put(TestDataStream.class, new TestDataStream()::read);
    subjects.put(TestObjectStream.class, new TestObjectStream()::read);
    subjects.put(TestBufferedWriter.class, new TestBufferedWriter()::read);

    subjects.forEach((aClass, fileDataBiConsumer) -> {
        File f = new File("test." + aClass.getName());

        long start = System.nanoTime();
        fileDataBiConsumer.accept(f, data);
        long took = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);

        System.out.println(aClass.getSimpleName() + " read " + N + " items, took: " + took + "ms, or " + String.format("%.4f", (N / (double)took)) + " items/ms, filesize " + f.length() + "b");
    });
}
于 2015-11-17T09:47:57.163 に答える
7

DataOutputStreamおよび:基本型を処理する場合、作成ObjectOutputStreamするヘッダー以外に違いはありません。ObjectOutputStream

このクラスを使用ObjectOutputStreamすると、実装するクラスのインスタンスをSerializable出力ストリームに書き込んだり、を使用して読み戻したりすることができますObjectInputStream

DataOutputStream基本タイプのみ処理できます。

于 2012-07-17T11:01:10.920 に答える
-1

java.io.Serializableインターフェイスを実装するオブジェクトのみが、ObjectOutputStream.Primitiveデータ型を使用してストリームに書き込むことができます。また、DataOutputの適切なメソッドを使用してストリームに書き込むこともできます。文字列は、writeUTFメソッドを使用して書き込むこともできます。しかしDataInputStream一方で、アプリケーションは、移植可能な方法でプリミティブJavaデータ型を出力ストリームに書き込むことができます。

オブジェクトOutputStream

データ入力ストリーム

于 2012-07-17T11:02:25.457 に答える