Загрузка с BufferInputStream не работает должным образом - PullRequest
2 голосов
/ 11 октября 2011

Следующий код не работает для загрузки файла (кстати, длина файла):

    int pos = 0, total_pos = 0;
    byte[] buffer = new byte[BUFFER_SIZE];
            while (pos != -1) {
                pos = in.read(buffer, 0, BUFFER_SIZE);
                total_pos += pos;
                out.write(buffer);
                setProgress((int) (total_pos * 100 / clen));
            }

... но это прекрасно работает:

    int buf;
    while ((buf = in.read()) != -1)
        out.write(buf);

Мне интересно, почему, хотя второй сегмент кода работает быстро. На этой ноте, есть ли какая-то особая причина для использования буфера byte [] (поскольку он, кажется, не быстрее, а BufferedInputStream уже использует собственный буфер ....?)

Ответы [ 2 ]

2 голосов
/ 11 октября 2011

Вот как это должно быть сделано.

public static void copyStream(InputStream is, OutputStream os)
    {
        byte[] buff = new byte[4096];
        int count;
        try {
            while((count = is.read(buff)) > 0)
                os.write(buff, 0, count);

        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if(is != null)
                    is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(os != null)
                    os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
0 голосов
/ 11 октября 2011

Я попытался внести минимальные изменения в ваш код, чтобы он заработал. st0le хорошо поработал, предоставив более точную версию потокового копирования.

public class Test {
    private static final String FORMAT = "UTF-8";
    private static final int BUFFER_SIZE = 10; // for demonstration purposes.
    public static void main(String[] args) throws Exception {
        String string = "This is a test of the public broadcast system";
        int clen = string.length();
        ByteArrayInputStream in = new ByteArrayInputStream(string.getBytes(FORMAT));
        OutputStream out = System.out;
        int pos = 0, total_pos = 0;
        byte[] buffer = new byte[BUFFER_SIZE];
        while (pos != -1) {
            pos = in.read(buffer, 0, BUFFER_SIZE);
            if (pos > 0) {
                total_pos += pos;
                out.write(buffer, 0, pos);
                setProgress((int) (total_pos * 100 / clen));
            }
        }
    }
    private static void setProgress(int i) {
    }
}
  • Вы игнорировали значение pos , когда записывали буфер в выходной поток.
  • Вам также необходимо еще раз проверить значение pos , поскольку оно, возможно, только что прочитало конец файла. В этом случае вы не увеличиваете total_pos (хотя вам, вероятно, следует сообщить, что вы на 100% выполнены)
  • Обязательно правильно обрабатывайте свои ресурсы с помощью close () в соответствующих местах.

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

Запись в консоль не может быть большой задержкой, но это может быть запись в сетевой сокет или другое медленное устройство. Как говорится в JavaDoc

Метод записи OutputStream вызывает метод записи одного аргумента для каждого байта, который должен быть записан. Подклассам рекомендуется переопределить этот метод и обеспечить более эффективную реализацию.

Преимущество использования его при использовании буферизованного потока ввода / вывода, вероятно, минимально.

...