문제

파일에 BigInteger를 쓰고 싶습니다.
이것을하는 가장 좋은 방법은 무엇입니까?
물론 읽고 싶어요 (인간이 아닌 프로그램과 함께) 입력 스트림에서.
ObjectOutputStream을 사용해야합니까, 아니면 더 좋은 방법이 있습니까?

목적은 가능한 한 적은 바이트를 사용하는 것입니다.

감사
마티 -

도움이 되었습니까?

해결책

Java 직렬화 (ObjectOutputStream/ObjectInputStream)는 옥켓 시퀀스로 객체를 직렬화하는 범용적인 방법입니다. 그러나 직렬화에는 문제가 있습니다.

효율적이기 위해 BigInteger 가지다 toByteArray 그리고 생성자 byte[]. 그런 다음 표현할 방법이 필요합니다 byte[] 스트림에서 (길이 포함). 예를 들어, 사용할 수 있습니다 DataOutputStream 에게 writeInt 길이를하고 원시 데이터로 따라갑니다.

물론 스트림은 선택한 적절한 데코레이터로 압축 할 수 있습니다.

다른 팁

나는 ObjectOutputStream과 함께 갈 것입니다. 그것이 바로 Biginteger가 아니라 클래스를 위해 설계된 것입니다.

다음은 압축 및 압축되지 않은 ObjectoutPustream의 오버 헤드를 보여주는 빠른 샘플 코드입니다.

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPOutputStream;


public class Main
{
    public static void main(String[] args)
        throws IOException
    {
        run(1);
        run(10);
        run(100);
        run(1000);
        run(10000);
        run(100000);
        run(1000000);
    }

    private static void run(final int size)
        throws IOException
    {
        final List<BigInteger> values;
        final int              uncompressedSize;
        final int              compressedSize;

        values           = createValues(size);
        uncompressedSize = storeUncompressed(values);
        compressedSize   = storeCompressed(values);

        System.out.println(size + " uncompressed is " + uncompressedSize + " ratio is: " + ((float)uncompressedSize / size));
        System.out.println(size + " compressed   is " + compressedSize   + " ratio is: " + ((float)compressedSize   / size));
    }

    private static List<BigInteger> createValues(final int size)
    {
        final List<BigInteger> values;

        values = new ArrayList<BigInteger>(size);

        for(int i = 0; i < size; i++)
        {
            values.add(BigInteger.ZERO);
        }

        return (values);
    }

    private static int storeUncompressed(final List<BigInteger> values)
        throws IOException
    {
        final ByteArrayOutputStream bytes;

        bytes = new ByteArrayOutputStream();
        store(values, bytes);

        return (bytes.size());
    }


    private static int storeCompressed(final List<BigInteger> values)
        throws IOException
    {
        final ByteArrayOutputStream bytes;
        final GZIPOutputStream      zip;

        bytes = new ByteArrayOutputStream();
        zip   = new GZIPOutputStream(bytes);
        store(values, zip);

        return (bytes.size());
    }

    private static void store(final List<BigInteger> values,
                              final OutputStream     sink)
        throws IOException
    {
        ObjectOutputStream stream;

        stream = null;

        try
        {
            stream = new ObjectOutputStream(sink);

            for(final BigInteger value : values)
            {
                stream.writeObject(value);
            }
        }
        finally
        {
            if(stream != null)
            {
                stream.close();
            }
        }
    }
}

출력은 다음과 같습니다.

1 uncompressed is 202 ratio is: 202.0
1 compressed   is 198 ratio is: 198.0
10 uncompressed is 247 ratio is: 24.7
10 compressed   is 205 ratio is: 20.5
100 uncompressed is 697 ratio is: 6.97
100 compressed   is 207 ratio is: 2.07
1000 uncompressed is 5197 ratio is: 5.197
1000 compressed   is 234 ratio is: 0.234
10000 uncompressed is 50197 ratio is: 5.0197
10000 compressed   is 308 ratio is: 0.0308
100000 uncompressed is 500197 ratio is: 5.00197
100000 compressed   is 962 ratio is: 0.00962
1000000 uncompressed is 5000197 ratio is: 5.000197
1000000 compressed   is 7516 ratio is: 0.007516

"values.add (biginteger.zero);" 테스트를보다 현실적으로 만들기위한 라인 - 나는 단지 그것의 기준을 원했습니다.

편집 : 나는 질문이 최적화에 관한 것이라는 것을 몰랐다.

나중에 직렬화 된 물체를 압축하여 바이트를 저장할 수 있습니다. 다음을 사용해보십시오.

FileOutputStream fos = new 
    FileOutputStream("db");
  GZIPOutputStream gz = new GZIPOutputStream(fos);

다음은 Sun의 기사입니다.

예, 단순성을 위해 ObjectOutputStream/ObjectInputStream을 사용하거나 BigInteger를 바이트 []로 변환하고 전체 객체 대신 해당 값을 직렬화 할 수 있습니다. 후자는 전체 객체를 직렬화하는 것보다 상당한 양의 저장 공간을 절약 할 수 있습니다.

또한 아직 버퍼링되지 않은 스트림 클래스를 사용하는 경우 BufferedOutputStream 및 BufferedInputStream에서 OutputStreams 및 InputStreams를 래핑하여 성능을 향상시키고 작성 후 (FlushedOutputStream을 플러시하지 않는 경우 () 입력 스트림은 입력을 기다리거나 매달릴 수 있습니다).

대역폭 또는 파일 크기에 대해 걱정이된다면 자동 압축을 위해 gzipoutputstream/gzipinputstream에서 스트림을 랩핑 할 수도 있습니다. 그러나 실제로 성능 저하 나 거대한 파일을 관찰하지 않는 한 데이터를 압축하는 것에 대해 걱정하지 않을 것입니다.

전체를 읽거나 쓰고 싶습니까? Object 아니면 그다 ? 전자라면 사용하십시오 직렬화. 후자라면, 그냥 사용하십시오 ByteArrayInputStream/ByteArrayOutputStream 여기서 당신은 결과를 씁니다 BigInteger#toByteArray() 그리고 도움으로 새로운 것을 건설하십시오 new BigInteger(byte[]) 각기. 마지막 방법은 파일에서 훨씬 적은 바이트를 생성합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top