JavaでInputStreamをバイト配列に変換します


回答:


1135

Apache Commons IOを使用して、これと同様のタスクを処理できます。

このIOUtils型には、を読み込んInputStreamで返す静的メソッドがありますbyte[]

InputStream is;
byte[] bytes = IOUtils.toByteArray(is);

内部的にこれはa ByteArrayOutputStreamを作成し、バイトを出力にコピーしてから、を呼び出しますtoByteArray()。4KiBのブロック単位でバイトをコピーすることにより、大きなファイルを処理します。


188
4行のコードを記述したいのに、サードパーティの依存関係をインポートする価値があると思いますか?
oxbow_lakes 2009

217
要件を処理し、大きなファイルの処理を処理するライブラリがあり、十分にテストされている場合、確かに問題はなぜ自分で作成するのかということです。jarはわずか107KBで、1つのメソッドが必要な場合は、他のメソッドも使用する可能性があります
リッチセラー

242
@oxbow_lakes:のずらす量を考慮間違って私は開発者の生活の中で見てきたこの機能の実装は、私がいることを感じてはい、それはです非常に多くの価値が右のそれを取得するための外部依存関係。
Joachim Sauer

17
行って、Apache commonsのようなものFastArrayListや、それらのソフトで弱いリファレンスマップを見て、このライブラリの「十分にテストされた」方法を教えてください。ゴミの山です
oxbow_lakes

87
Apache commons-ioに加えて、Google GuavaのByteStreamsクラスをチェックしてください。 InputStream is; byte[] filedata=ByteStreams.toByteArray(is);
michaelok 2011

446

から各バイトを読み取り、InputStreamそれをに書き込む必要がありますByteArrayOutputStream

次に、以下を呼び出して、基礎となるバイト配列を取得できますtoByteArray()

InputStream is = ...
ByteArrayOutputStream buffer = new ByteArrayOutputStream();

int nRead;
byte[] data = new byte[16384];

while ((nRead = is.read(data, 0, data.length)) != -1) {
  buffer.write(data, 0, nRead);
}

return buffer.toByteArray();

17
新しく作成されたbyte []のサイズはどうですか。なぜ16384なのですか?正確なサイズを判断するにはどうすればよいですか?どうもありがとうございました。
Ondrej Bozek

6
16384はかなり恣意的な選択ですが、2の累乗を優先して、配列が単語の境界に整列する可能性を高めます。pihentagyの答えは、中間バッファーの使用を回避しながら、正しいサイズの配列を割り当てる方法を示しています。大きなファイルを扱っているのでない限り、私は個人的に上記のコードを好みます。これはよりエレガントで、読み取るバイト数が事前にわからないInputStreamに使用できます。
アダムスキー

@Adamskiデータがストリームにあると予想されるよりもはるかに大きいバイトの配列を作成していませんか?メモリを浪費していますか?
Paul Brewczynski 2013年

@bluesm:はい、そうです。ただし、私の例では、バイト配列はわずか16Kbであり、今日の標準では非常に小さいです。また、もちろんこのメモリは後で再び解放されます。
アダムスキー2013

5
@Adamski多くのインフラストラクチャハードウェア、Webサーバー、OSレイヤーコンポーネントが4Kバッファーを使用してデータを移動しているため、正確な数になるのはそのためですが、主なポイントは、4Kを超えるとパフォーマンスが少し向上することです。それは一般的にメモリの浪費と考えられていること。それは私が持っていた10年の古い知識なので、これはまだ本当だと思います!


132

バニラJava DataInputStreamとそのreadFullyメソッドを使用(少なくともJava 1.4以降に存在):

...
byte[] bytes = new byte[(int) file.length()];
DataInputStream dis = new DataInputStream(new FileInputStream(file));
dis.readFully(bytes);
...

この方法には他にもいくつかの種類がありますが、この使用例ではこれを常に使用しています。


45
サードパーティの依存関係の代わりに標準ライブラリを使用するための+1。残念ながら、私は前もってストリームの長さを知らないので、私にはうまくいきません。
アンドリュースペンサー

2
imgFileとは このメソッドの入力であるはずのInputStreamにすることはできません
Janus Troelsen

4
@janusそれは「ファイル」です。この方法は、ファイルの長さまたは読み取るバイト数がわかっている場合にのみ機能します。
dermoritz 2013

5
興味深いことですが、読み取る(ストリームの)ストリームの正確な長さを知っている必要があります。さらに、クラスDataInputStreamはストリームからプライマリタイプ(Longs、Shorts、Chars ...)を読み取るために主に使用されるため、この使用法をクラスの誤用と見なすことができます。
Olivier Faucheux

17
ストリームから読み取るデータの長さがすでにわかっている場合、これはと同じですInputStream.read
Logan Pickup


46

いつものように、Springフレームワーク(3.2.2以降のspring-core)にもいくつかの機能があります。StreamUtils.copyToByteArray()


他のほとんどの人と同じように、私はサードパーティのライブラリをそれほど単純なものに使用しないようにしたかったのですが、現時点ではJava 9はオプションではありません...幸いにも、私はすでにSpringを使用していました。
scottysseus

42
public static byte[] getBytesFromInputStream(InputStream is) throws IOException {
    ByteArrayOutputStream os = new ByteArrayOutputStream(); 
    byte[] buffer = new byte[0xFFFF];
    for (int len = is.read(buffer); len != -1; len = is.read(buffer)) { 
        os.write(buffer, 0, len);
    }
    return os.toByteArray();
}

2
これは一例であり、簡潔さはその日の順序です。また、場合によってはここでnullを返すことが適切な選択になります(ただし、運用環境では、適切な例外処理とドキュメントも用意されています)。

11
私は例の簡潔さを理解していますが、例のメソッドにそれを飲み込んで意味のない値を返すのではなく、単にIOExceptionをスローさせるだけではどうですか?
ペンドール2014年

4
私は自由を 'return null'から 'throw IOException'に変更しました
kritzikratzi

3
ByteArrayOutputStream#close()は何もしないため、ここではtry-with-resourcesは必要ありません。(ByteArrayOutputStream#flush()は不要であり、何も行いません。)
ルークハッチソン

25

安全なソリューションcloseストリームの機能を正しく使用):

  • Java 9+バージョン:

    final byte[] bytes;
    try (inputStream) {
        bytes = inputStream.readAllBytes();
    }
  • Java 8バージョン:

    public static byte[] readAllBytes(InputStream inputStream) throws IOException {
        final int bufLen = 4 * 0x400; // 4KB
        byte[] buf = new byte[bufLen];
        int readLen;
        IOException exception = null;
    
        try {
            try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                while ((readLen = inputStream.read(buf, 0, bufLen)) != -1)
                    outputStream.write(buf, 0, readLen);
    
                return outputStream.toByteArray();
            }
        } catch (IOException e) {
            exception = e;
            throw e;
        } finally {
            if (exception == null) inputStream.close();
            else try {
                inputStream.close();
            } catch (IOException e) {
                exception.addSuppressed(e);
            }
        }
    }
  • Kotlinバージョン(Java 9+にアクセスできない場合):

    @Throws(IOException::class)
    fun InputStream.readAllBytes(): ByteArray {
        val bufLen = 4 * 0x400 // 4KB
        val buf = ByteArray(bufLen)
        var readLen: Int = 0
    
        ByteArrayOutputStream().use { o ->
            this.use { i ->
                while (i.read(buf, 0, bufLen).also { readLen = it } != -1)
                    o.write(buf, 0, readLen)
            }
    
            return o.toByteArray()
        }
    }

    ネストを回避するにuseは、こちらをご覧ください


バッファとバイト配列の両方があるので、ある時点でメモリが2倍になることを意味しませんか?バイトを出力バイト配列に直接送信する方法はありませんか?
Android開発者

@androiddeveloper; 申し訳ありません。答えがわかりません!しかし、私はそうは思いません。この方法(バッファーを使用)は最適化された方法だと思います。
Mir-Ismaili

私は確認しましたが、サイズがわからない場合に選択できる唯一のソリューションのようです。すでにサイズがわかっている場合は、指定されたサイズのバイト配列を直接作成して、それを埋めることができます。したがって、バイトサイズのパラメーターを取得する関数を使用し、それが有効な場合は、他のラージオブジェクトを作成せずに、バイト配列を直接作成して埋めるために使用します。
Android開発者

@androiddeveloper; 情報ありがとうございます。私はそれらを知りませんでした。
Mir-Ismaili

19

本当に画像が必要byte[]ですか?正確には何を期待していますかbyte[]-画像ファイルの完全なコンテンツ、画像ファイルの形式でエンコードされたもの、またはRGBピクセル値?

ここでの他の回答は、ファイルをに読み込む方法を示していますbyte[]。あなたbyte[]はファイルの正確な内容を含みます、そしてあなたは画像データで何かをするためにそれをデコードする必要があるでしょう。

画像の読み取り(および書き込み)のためのJavaの標準APIは、パッケージにあるImageIO APIですjavax.imageio。1行のコードでファイルから画像を読み取ることができます。

BufferedImage image = ImageIO.read(new File("image.jpg"));

これにより、BufferedImageではなくが提供されますbyte[]。画像データを取得するには、呼び出すことができますgetRaster()BufferedImage。これによりRaster、ピクセルデータにアクセスするためのメソッドを持つオブジェクトが提供されます(いくつかのgetPixel()/ getPixels()メソッドがあります)。

APIドキュメントを検索用javax.imageio.ImageIOjava.awt.image.BufferedImagejava.awt.image.Rasterなど

ImageIOは、デフォルトで、JPEG、PNG、BMP、WBMP、GIFの多くの画像形式をサポートしています。さらに多くの形式のサポートを追加することが可能です(ImageIOサービスプロバイダーインターフェイスを実装するプラグインが必要です)。

次のチュートリアルも参照してください:画像の操作


16

誰かがまだ依存関係のない解決策を探している場合、ファイルがある場合

1)DataInputStream

 byte[] data = new byte[(int) file.length()];
 DataInputStream dis = new DataInputStream(new FileInputStream(file));
 dis.readFully(data);
 dis.close();

2)ByteArrayOutputStream

 InputStream is = new FileInputStream(file);
 ByteArrayOutputStream buffer = new ByteArrayOutputStream();
 int nRead;
 byte[] data = new byte[(int) file.length()];
 while ((nRead = is.read(data, 0, data.length)) != -1) {
     buffer.write(data, 0, nRead);
 }

3)RandomAccessFile

 RandomAccessFile raf = new RandomAccessFile(file, "r");
 byte[] data = new byte[(int) raf.length()];
 raf.readFully(data);

たとえば、バイト配列が大きすぎてヒープにOOMが発生する可能性がある場合はどうでしょうか。JNIを使​​用してバイトを格納する同様のソリューションはありますか?後でそこに格納されたデータ(一時キャッシュの一種)からinputStreamを使用できますか?
Android開発者

14

Apache commons-ioライブラリを使用したくない場合、このスニペットはsun.misc.IOUtilsクラスから取得されます。ByteBuffersを使用した一般的な実装のほぼ2倍の速さです。

public static byte[] readFully(InputStream is, int length, boolean readAll)
        throws IOException {
    byte[] output = {};
    if (length == -1) length = Integer.MAX_VALUE;
    int pos = 0;
    while (pos < length) {
        int bytesToRead;
        if (pos >= output.length) { // Only expand when there's no room
            bytesToRead = Math.min(length - pos, output.length + 1024);
            if (output.length < pos + bytesToRead) {
                output = Arrays.copyOf(output, pos + bytesToRead);
            }
        } else {
            bytesToRead = output.length - pos;
        }
        int cc = is.read(output, pos, bytesToRead);
        if (cc < 0) {
            if (readAll && length != Integer.MAX_VALUE) {
                throw new EOFException("Detect premature EOF");
            } else {
                if (output.length != pos) {
                    output = Arrays.copyOf(output, pos);
                }
                break;
            }
        }
        pos += cc;
    }
    return output;
}

これは、奇妙な溶液のビットであり、長さは、上側アレイの長さにバインドされています。長さがわかっている場合、必要なのは次のとおりです。byte[] output = new byte [length]; is.read(output); (しかし、私の答えを参照してください)
ルーク・ハチソン

@ luke-hutchison私が言ったように、これはsun.misc.IOUtilsの解決策です。最も一般的なケースでは、事前にInputStreamのサイズがわからないため、(length == -1)length = Integer.MAX_VALUE;の場合、適用されます。このソリューションは、指定された長さがInputStreamの長さよりも長い場合でも機能します。
Kristian Kraljic 2015

@LukeHutchison長さがわかっている場合は、数行で処理できます。それぞれの答えを見ると、長さが分からないと不平を言っています。最後に、標準で、Java 7 Androidで使用でき、外部ライブラリを必要としない回答。
Csaba Toth

11
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
while (true) {
    int r = in.read(buffer);
    if (r == -1) break;
    out.write(buffer, 0, r);
}

byte[] ret = out.toByteArray();

8

@Adamski:バッファを完全に回避できます。

http://www.exampledepot.com/egs/java.io/File2ByteArray.htmlからコピーされたコード(はい、非常に冗長ですが、他のソリューションの半分のサイズのメモリが必要です)

// Returns the contents of the file in a byte array.
public static byte[] getBytesFromFile(File file) throws IOException {
    InputStream is = new FileInputStream(file);

    // Get the size of the file
    long length = file.length();

    // You cannot create an array using a long type.
    // It needs to be an int type.
    // Before converting to an int type, check
    // to ensure that file is not larger than Integer.MAX_VALUE.
    if (length > Integer.MAX_VALUE) {
        // File is too large
    }

    // Create the byte array to hold the data
    byte[] bytes = new byte[(int)length];

    // Read in the bytes
    int offset = 0;
    int numRead = 0;
    while (offset < bytes.length
           && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
        offset += numRead;
    }

    // Ensure all the bytes have been read in
    if (offset < bytes.length) {
        throw new IOException("Could not completely read file "+file.getName());
    }

    // Close the input stream and return bytes
    is.close();
    return bytes;
}

5
事前にサイズを知っていることに依存します。
stolsvik 2013

2
もちろん、しかし、彼らはサイズを知っている必要があります:「画像を読みたい」
pihentagy

1
サイズがわかっている場合は、javaがコードを提供します。私の答えまたは「DataInputStream」のグーグルを参照してください。それはreadFullyメソッドです。
dermoritz 2013年

その例外がスローされた場合にクローズするis.close()かどうoffset < bytes.lengthかを追加する必要InputStreamがあります。
Jared Rummler、2015

3
次に、try-with-resourcesを使用することをお勧めします
pihentagy

8
Input Stream is ...
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int next = in.read();
while (next > -1) {
    bos.write(next);
    next = in.read();
}
bos.flush();
byte[] result = bos.toByteArray();
bos.close();

ただし、通常、OSはすでにこれを十分にバッファリングしているので、ファイルが小さい場合は大きな心配はありません。ハードディスクヘッドが各バイトを個別に読み取るのとは異なります(ハードディスクは、磁気コーディングされた情報が入った回転ガラスプレートであり、データの保存に使用する奇妙なアイコン:Pのようなものです)。
Maarten Bodewes

6
@Maarten Bodewes:ほとんどのデバイスには一種のブロック転送があるため、すべてのread()が実際にデバイスにアクセスするわけではありませんが、バイトごとにOS呼び出しを行うだけでパフォーマンスが低下します。ラップしながらInputStream中にBufferedInputStreamOS-呼び出しを削減し、大幅にパフォーマンスの欠点を緩和するだろうとコードの前に、そのコードはまだ別のバッファから不要な手動コピー作業を行います。
Holger


2

手遅れだと知っていますが、ここではより読みやすい、よりクリーンな解決策だと思います...

/**
 * method converts {@link InputStream} Object into byte[] array.
 * 
 * @param stream the {@link InputStream} Object.
 * @return the byte[] array representation of received {@link InputStream} Object.
 * @throws IOException if an error occurs.
 */
public static byte[] streamToByteArray(InputStream stream) throws IOException {

    byte[] buffer = new byte[1024];
    ByteArrayOutputStream os = new ByteArrayOutputStream();

    int line = 0;
    // read bytes from stream, and store them in buffer
    while ((line = stream.read(buffer)) != -1) {
        // Writes bytes from byte array (buffer) into output stream.
        os.write(buffer, 0, line);
    }
    stream.close();
    os.flush();
    os.close();
    return os.toByteArray();
}

4
try-with-resourcesを使用する必要があります。
Victor Stafusa

エラーが発生した場合は、最後に片付けを最終ブロックで行う必要があります。そうしないと、メモリリークが発生する可能性があります。
MGDavies

2

Java 8 way(BufferedReaderAdam Bienに感謝)

private static byte[] readFully(InputStream input) throws IOException {
    try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) {
        return buffer.lines().collect(Collectors.joining("\n")).getBytes(<charset_can_be_specified>);
    }
}

このソリューションはキャリッジリターン( '\ r')を消去するため、不適切な場合があることに注意しください


4
それはですString。OPが求めていbyte[]ます。
FrozenFire

それ\rが問題になるだけではありません。このメソッドは、バイトを文字に変換し、再び戻します(InputStreamReaderのデフォルトの文字セットを使用)。デフォルトの文字エンコーディング(たとえば、LinuxのUTF-8の場合は-1)で無効なバイトは破損し、バイト数が変更される可能性もあります。
seanf

これは良い答えのようですが、テキスト指向です。バイヤーは注意してください。
Wheezil 2018

1

@numanの回答をガベージデータの書き込みを修正して編集しようとしましたが、編集が拒否されました。この短いコードは素晴らしいものではありませんが、他にもっと良い答えはありません。これが私にとって最も意味のあることです:

ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024]; // you can configure the buffer size
int length;

while ((length = in.read(buffer)) != -1) out.write(buffer, 0, length); //copy streams
in.close(); // call this in a finally block

byte[] result = out.toByteArray();

ところで、ByteArrayOutputStreamを閉じる必要はありません。読みやすくするために、try / finally構文は省略


1

InputStream.available()ドキュメントを参照してください:

このメソッドを使用してコンテナのサイズを変更することはできず、コンテナのサイズを変更することなくストリーム全体を読み取ることができると想定することが重要です。そのような呼び出し元は、おそらくすべてをByteArrayOutputStreamに書き込み、それをバイト配列に変換する必要があります。または、ファイルから読み取る場合、File.lengthはファイルの現在の長さを返します(ただし、ファイルの長さが変更できないと仮定すると正しくない場合がありますが、ファイルの読み取りは本質的に際どいものです)。


1

何らかの理由でテーブルから外れている場合は、DataInputStreamでラップします。-1または要求されたブロック全体が得られるまで、readを使用してハンマーします。

public int readFully(InputStream in, byte[] data) throws IOException {
    int offset = 0;
    int bytesRead;
    boolean read = false;
    while ((bytesRead = in.read(data, offset, data.length - offset)) != -1) {
        read = true;
        offset += bytesRead;
        if (offset >= data.length) {
            break;
        }
    }
    return (read) ? offset : -1;
}

1

S3オブジェクトをByteArrayに変換している間、いくつかのAWSトランザクションで遅延が発生しています。

注:S3オブジェクトはPDFドキュメントです(最大サイズは3 MB)。

オプション#1(org.apache.commons.io.IOUtils)を使用して、S3オブジェクトをByteArrayに変換しています。S3がS3オブジェクトをByteArrayに変換するためのinbuild IOUtilsメソッドを提供していることを確認しました。遅延を回避するためにS3オブジェクトをByteArrayに変換する最良の方法を確認するように要求されます。

オプション1:

import org.apache.commons.io.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);

オプション#2:

import com.amazonaws.util.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);

また、s3オブジェクトをバイト配列に変換する他のより良い方法があるかどうかも教えてください


0

サーバーにリクエストを送信し、レスポンスを待った後、ストリームを介して正しいバイト配列を取得するもう1つのケース。

/**
         * Begin setup TCP connection to PC app
         * to open integrate connection between mobile app and pc app (or mobile app)
         */
        mSocket = new Socket(IP, port);
       // mSocket.setSoTimeout(30000);

        DataOutputStream mDos = new DataOutputStream(mSocket.getOutputStream());

        String str = "MobileRequest#" + params[0] + "#<EOF>";

        mDos.write(str.getBytes());

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        /* Since data are accepted as byte, all of them will be collected in the
        following byte array which initialised with accepted data length. */
        DataInputStream mDis = new DataInputStream(mSocket.getInputStream());
        byte[] data = new byte[mDis.available()];

        // Collecting data into byte array
        for (int i = 0; i < data.length; i++)
            data[i] = mDis.readByte();

        // Converting collected data in byte array into String.
        String RESPONSE = new String(data);

0

ByteArrayOutputStreamを使用する場合は、追加のコピーを実行しています。読み取りを開始する前にストリームの長さがわかっている場合(たとえば、InputStreamは実際にはFileInputStreamであり、ファイルに対してfile.length()を呼び出すことができます。または、InputStreamがzipfileエントリのInputStreamであり、zipEntryを呼び出すことができます。 length())の場合、byte []配列に直接書き込む方がはるかに優れています。メモリの半分を使用し、時間を節約できます。

// Read the file contents into a byte[] array
byte[] buf = new byte[inputStreamLength];
int bytesRead = Math.max(0, inputStream.read(buf));

// If needed: for safety, truncate the array if the file may somehow get
// truncated during the read operation
byte[] contents = bytesRead == inputStreamLength ? buf
                  : Arrays.copyOf(buf, bytesRead);

上記の最後の行は、ストリームの読み取り中にファイルが切り捨てられることを扱っています。その可能性を処理する必要がある場合は、ストリームの読み取り中にファイルが長くなると、byte []配列の内容は長くなりません。新しいファイルの内容を含めるために、配列は単に古い長さのinputStreamLengthに切り捨てられます。


0

私はこれを使います。

public static byte[] toByteArray(InputStream is) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        try {
            byte[] b = new byte[4096];
            int n = 0;
            while ((n = is.read(b)) != -1) {
                output.write(b, 0, n);
            }
            return output.toByteArray();
        } finally {
            output.close();
        }
    }

2
現在の問題を修正する方法で、この答えのヘルプOPのための答えを持ついくつかの説明を追加
ρяσѕρєяK

0

これは私のコピー貼り付けバージョンです:

@SuppressWarnings("empty-statement")
public static byte[] inputStreamToByte(InputStream is) throws IOException {
    if (is == null) {
        return null;
    }
    // Define a size if you have an idea of it.
    ByteArrayOutputStream r = new ByteArrayOutputStream(2048);
    byte[] read = new byte[512]; // Your buffer size.
    for (int i; -1 != (i = is.read(read)); r.write(read, 0, i));
    is.close();
    return r.toByteArray();
}

2
このコードスニペットは問題を解決する可能性がありますが、説明を含めると、投稿の品質を向上させるのに役立ちます。あなたは将来の読者のための質問に答えていることを覚えておいてください、そしてそれらの人々はあなたのコード提案の理由を知らないかもしれません。
Ferrybig 2016

0

Java 7以降:

import sun.misc.IOUtils;
...
InputStream in = ...;
byte[] buf = IOUtils.readFully(in, -1, false);

20
sun.misc.IOUtils「Java 7」ではありません。これは、他のJRE実装には存在しない独自の実装固有のクラスであり、次のリリースのいずれかで警告なしに消えることがあります。
Holger


0

これは最適化されたバージョンで、データバイトをできるだけコピーしないようにしています。

private static byte[] loadStream (InputStream stream) throws IOException {
   int available = stream.available();
   int expectedSize = available > 0 ? available : -1;
   return loadStream(stream, expectedSize);
}

private static byte[] loadStream (InputStream stream, int expectedSize) throws IOException {
   int basicBufferSize = 0x4000;
   int initialBufferSize = (expectedSize >= 0) ? expectedSize : basicBufferSize;
   byte[] buf = new byte[initialBufferSize];
   int pos = 0;
   while (true) {
      if (pos == buf.length) {
         int readAhead = -1;
         if (pos == expectedSize) {
            readAhead = stream.read();       // test whether EOF is at expectedSize
            if (readAhead == -1) {
               return buf;
            }
         }
         int newBufferSize = Math.max(2 * buf.length, basicBufferSize);
         buf = Arrays.copyOf(buf, newBufferSize);
         if (readAhead != -1) {
            buf[pos++] = (byte)readAhead;
         }
      }
      int len = stream.read(buf, pos, buf.length - pos);
      if (len < 0) {
         return Arrays.copyOf(buf, pos);
      }
      pos += len;
   }
}

0

Kotlinのソリューション(もちろんJavaでも機能します)。これには、サイズがわかっているかどうかの両方のケースが含まれます。

    fun InputStream.readBytesWithSize(size: Long): ByteArray? {
        return when {
            size < 0L -> this.readBytes()
            size == 0L -> ByteArray(0)
            size > Int.MAX_VALUE -> null
            else -> {
                val sizeInt = size.toInt()
                val result = ByteArray(sizeInt)
                readBytesIntoByteArray(result, sizeInt)
                result
            }
        }
    }

    fun InputStream.readBytesIntoByteArray(byteArray: ByteArray,bytesToRead:Int=byteArray.size) {
        var offset = 0
        while (true) {
            val read = this.read(byteArray, offset, bytesToRead - offset)
            if (read == -1)
                break
            offset += read
            if (offset >= bytesToRead)
                break
        }
    }

サイズがわかっている場合は、他のソリューションと比較して2倍のメモリを使用する手間が省けます(一瞬ですが、それでも役立つ場合があります)。これは、ストリーム全体を最後まで読み取り、それをバイト配列に変換する必要があるためです(配列に変換するArrayListと同様)。

たとえば、Androidを使用していて、処理するUriがいくつかある場合は、これを使用してサイズを取得できます。

    fun getStreamLengthFromUri(context: Context, uri: Uri): Long {
        context.contentResolver.query(uri, arrayOf(MediaStore.MediaColumns.SIZE), null, null, null)?.use {
            if (!it.moveToNext())
                return@use
            val fileSize = it.getLong(it.getColumnIndex(MediaStore.MediaColumns.SIZE))
            if (fileSize > 0)
                return fileSize
        }
        //if you wish, you can also get the file-path from the uri here, and then try to get its size, using this: https://stackoverflow.com/a/61835665/878126
        FileUtilEx.getFilePathFromUri(context, uri, false)?.use {
            val file = it.file
            val fileSize = file.length()
            if (fileSize > 0)
                return fileSize
        }
        context.contentResolver.openInputStream(uri)?.use { inputStream ->
            if (inputStream is FileInputStream)
                return inputStream.channel.size()
            else {
                var bytesCount = 0L
                while (true) {
                    val available = inputStream.available()
                    if (available == 0)
                        break
                    val skip = inputStream.skip(available.toLong())
                    if (skip < 0)
                        break
                    bytesCount += skip
                }
                if (bytesCount > 0L)
                    return bytesCount
            }
        }
        return -1L
    }

-1
/*InputStream class_InputStream = null;
I am reading class from DB 
class_InputStream = rs.getBinaryStream(1);
Your Input stream could be from any source
*/
int thisLine;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((thisLine = class_InputStream.read()) != -1) {
    bos.write(thisLine);
}
bos.flush();
byte [] yourBytes = bos.toByteArray();

/*Don't forget in the finally block to close ByteArrayOutputStream & InputStream
 In my case the IS is from resultset so just closing the rs will do it*/

if (bos != null){
    bos.close();
}

bosのクローズとフラッシュはキーボードクリックの無駄です。入力ストリームを閉じる方が役立つ可能性が高くなります。一度に1バイトを読み取るのは非効率的です。numanの回答を参照してください。
akostadinov 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.