web-dev-qa-db-ja.com

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

InputStream全体をバイト配列に読み込むにはどうすればいいですか?

750
JGC

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

IOUtils型はInputStreamを読み込み、byte[]を返す静的メソッドを持ちます。

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

内部的にこれはByteArrayOutputStreamを作成してバイトを出力にコピーしてからtoByteArray()を呼び出します。それは4KiBのブロックのバイトをコピーすることによって大きなファイルを扱います。

1019
Rich Seller

あなたは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();
416
Adamski

最後に、20年後、 Java 9 のおかげで、サードパーティのライブラリを必要としない簡単な解決策があります。

InputStream is;
…
byte[] array = is.readAllBytes();

便利なメソッド readNBytes(byte[] b, int off, int len) および transferTo(OutputStream) にも注意が必要です。

230
Holger

Vanilla JavaのDataInputStreamとそのreadFullyメソッドを使用してください(少なくともJava 1.4以降に存在します)

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

このメソッドには他にもいくつかの種類がありますが、このユースケースでは常にこれを使用します。

113
dermoritz

google guava を使用した場合、次のように簡単になります。

byte[] bytes = ByteStreams.toByteArray(inputStream);
112
bertie
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();
}
37
oliverkn

いつものように、 Spring framework (3.2.2からのspring-core)もあなたのために何かを持っています:StreamUtils.copyToByteArray()

34
Arne Burmeister

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

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

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

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

これはbyte[]ではなくBufferedImageを与えるでしょう。画像データを取得するには、BufferedImagegetRaster()を呼び出します。これはあなたにRasterオブジェクトを与えるでしょう、それはピクセルデータにアクセスするためのメソッドを持っています(それはいくつかのgetPixel()/getPixels()メソッドを持っています)。

javax.imageio.ImageIOJava.awt.image.BufferedImageJava.awt.image.RasterなどのAPIドキュメントを参照してください。

ImageIOはデフォルトでいくつかの画像フォーマットをサポートします:JPEG、PNG、BMP、WBMPおよびGIF。より多くのフォーマットのサポートを追加することが可能です(ImageIOサービスプロバイダーインターフェースを実装するプラグインが必要です)。

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

20
Jesper

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

場合によっては、依存関係やファイルがある場合のない解決策を探している人もいます。

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);
12
harsh_v
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();
9
YulCheney

@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;
}
8
pihentagy
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();
8
Aturio

Safe solution 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 version(Java≤8と互換性があります):

    @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を避けるには here を参照してください。

4
Mir-Ismaili

Java 9はやっとあなたにいい方法を与えるでしょう:

InputStream in = ...;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
in.transferTo( bos );
byte[] bytes = bos.toByteArray();
3

私はそれが遅すぎることを知っていますが、ここで私はもっと読みやすいきれいな解決策だと思います...

/**
 * 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();
}
2
Simple-Solution

Java 7以降

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

Java 8の方法( BufferedReader および Adam 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')が消去され、不適切な場合があります。

1
Ilya Bystrov

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

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

1
yichouangle

@ 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
akostadinov

S3オブジェクトをByteArrayに変換している間に、いくつかのAWSトランザクションに対して若干の遅延が見られます。

注:S3オブジェクトはPDF documentです(最大サイズは3 MB)。

S3オブジェクトをByteArrayに変換するために、オプション#1(org.Apache.commons.io.IOUtils)を使用しています。 S3は、S3オブジェクトをByteArrayに変換するための組み込みの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オブジェクトをbytearrayに変換するための他のより良い方法があるかどうかも教えてください。

0
Bharathiraja S

あなたは試すことができます サボテン

byte[] array = new BytesOf(stream).bytes();
0
yegor256

それが何らかの理由でテーブルから外れている場合は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;
}
0
Tatarize

私はこれを使います。

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

サーバーにリクエストを送信し、応答を待った後、ストリームを介して正しいバイト配列を取得するもう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
Huy Tower

これは私のコピー&ペースト版です:

@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();
}
0
Daniel De León

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

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

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

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

0
Luke Hutchison