Подтвердить что ты не робот

Чтение двоичного входного потока в один байтовый массив в Java

В документации говорится, что не следует использовать метод available() для определения размера InputStream. Как я могу прочитать все содержимое InputStream в массив байтов?

InputStream in; //assuming already present
byte[] data = new byte[in.available()];
in.read(data);//now data is filled with the whole content of the InputStream

Я мог читать несколько раз в буфер фиксированного размера, но тогда мне придется объединить данные, которые я прочитал, в один байт-массив, что для меня проблема.

4b9b3361

Ответ 1

Самый простой подход IMO - использовать Guava и его класс ByteStreams:

byte[] bytes = ByteStreams.toByteArray(in);

Или для файла:

byte[] bytes = Files.toByteArray(file);

Альтернативно (если вы не хотите использовать Guava), вы можете создать ByteArrayOutputStream и многократно считывать в байтовый массив и записывать в ByteArrayOutputStream (позволяя изменять размер дескриптора), а затем вызывать ByteArrayOutputStream.toByteArray().

Обратите внимание, что этот подход работает независимо от того, можете ли вы указать длину вашего ввода или нет - если у вас достаточно памяти, конечно.

Ответ 2

Помните, что в приведенных здесь ответах предполагается, что длина файла меньше или равна Integer.MAX_VALUE (2147483647).

Если вы читаете из файла, вы можете сделать что-то вроде этого:

    File file = new File("myFile");
    byte[] fileData = new byte[(int) file.length()];
    DataInputStream dis = new DataInputStream(new FileInputStream(file));
    dis.readFully(fileData);
    dis.close();

ОБНОВЛЕНИЕ (31 мая 2014 г.):

Java 7 добавляет некоторые новые функции в пакет java.nio.file, которые можно использовать, чтобы сделать этот пример на несколько строк короче. См. метод readAllBytes() в классе java.nio.file.Files. Вот краткий пример:

import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;

// ...
        Path p = FileSystems.getDefault().getPath("", "myFile");
        byte [] fileData = Files.readAllBytes(p);

Android имеет поддержку для этого, начиная с Api уровня 26 (8.0.0, Oreo).

Ответ 3

Вы можете использовать Apache commons-io для этой задачи:

Обратитесь к этот метод:

public static byte[] readFileToByteArray(File file) throws IOException

Update:

Java 7:

byte[] bytes = Files.readAllBytes(Paths.get(filename));

и если это текстовый файл, и вы хотите преобразовать его в String (при необходимости измените кодировку):

StandardCharsets.UTF_8.decode(ByteBuffer.wrap(bytes)).toString()

Ответ 4

Я считаю, что длина буфера должна быть указана, так как память конечна, и вы можете ее исчерпать

Пример:

InputStream in = new FileInputStream(strFileName);
    long length = fileFileName.length();

    if (length > Integer.MAX_VALUE) {
        throw new IOException("File is too large!");
    }

    byte[] bytes = new byte[(int) length];

    int offset = 0;
    int numRead = 0;

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

    if (offset < bytes.length) {
        throw new IOException("Could not completely read file " + fileFileName.getName());
    }

    in.close();

Ответ 5

Вы можете прочитать его кусками (byte buffer[] = new byte[2048]) и записать куски в ByteArrayOutputStream. Из ByteArrayOutputStream вы можете получить содержимое в виде байта [], не задумываясь заранее определить его размер.

Ответ 6

Максимальное значение для индекса массива - Integer.MAX_INT - около 2 Гб (2 ^ 31/2 147 483 647). Ваш входной поток может быть больше 2 ГБ, поэтому вам придется обрабатывать данные в кусках, извините.

        InputStream is;
        final byte[] buffer = new byte[512 * 1024 * 1024]; // 512Mb
        while(true) {
            final int read = is.read(buffer);
            if ( read < 0 ) {
                break;
            }
            // do processing 
        }