Использование BufferedInputStream - PullRequest
35 голосов
/ 26 июня 2010

Позвольте мне предисловие к этому посту с одной осторожностью. Я абсолютный новичок в том, что касается Java. Некоторое время я программировал PHP и выключал его, но я был готов сделать настольное приложение, поэтому я решил использовать Java по разным причинам.

Приложение, над которым я работаю, находится на начальных этапах (менее 5 классов), и мне нужно прочитать байты из локального файла. Как правило, файлы в настоящее время имеют размер менее 512 КБ (но могут увеличиться в будущем). В настоящее время я использую FileInputStream для чтения файла в трехбайтовые массивы, что полностью соответствует моим требованиям. Тем не менее, я видел упомянутое BufferedInputStream и задавался вопросом, лучше ли то, как я сейчас это делаю, или мне следует также использовать BufferedInputStream.

Я провел некоторое исследование и прочитал несколько вопросов здесь о переполнении стека, но у меня все еще есть проблемы с пониманием наилучшей ситуации, когда использовать и не использовать BufferedInputStream. В моей ситуации первый массив, в который я считал байты, занимает всего несколько байтов (меньше 20). Если данные, которые я получаю, хороши в этих байтах, тогда я читаю остальную часть файла в еще два байтовых массива различного размера.

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

Извините за такой длинный пост, но я действительно хочу узнать и понять, как лучше всего делать эти вещи. У меня всегда есть плохая привычка угадывать мои решения, поэтому я хотел бы получить обратную связь. Спасибо!

Ответы [ 5 ]

78 голосов
/ 26 июня 2010

Если вы постоянно выполняете небольшие операции чтения, то BufferedInputStream даст вам значительно лучшую производительность. Каждый запрос на чтение в небуферизованном потоке обычно приводит к системному вызову операционной системы для считывания запрошенного количества байтов. Затраты на выполнение системного вызова могут составлять тысячи машинных инструкций на системный вызов. Буферизованный поток уменьшает это, делая одно большое чтение (скажем) до 8 Кбайт во внутренний буфер, а затем раздает байты из этого буфера. Это может значительно сократить количество системных вызовов.

Однако, если вы последовательно выполняете большие операции чтения (например, 8 КБ или более), то BufferedInputStream замедляет работу. Обычно вы не уменьшаете количество системных вызовов, а буферизация вводит дополнительный шаг копирования данных.

В вашем случае использования (когда вы сначала читаете 20-байтовый блок, затем много больших блоков), я бы сказал, что использование BufferedInputStream скорее снизит производительность, чем увеличит ее. Но, в конечном счете, это зависит от фактических шаблонов чтения.

5 голосов
/ 26 июня 2010

Если вы используете относительно большие массивы для чтения данных порцией за раз, тогда BufferedInputStream просто представит расточительную копию.(Помните, что read не обязательно читает весь массив - вы можете захотеть DataInputStream.readFully).BufferedInputStream выигрывает при большом количестве маленьких чтений.

1 голос
/ 26 июня 2010

Я не могу говорить с профилированием, но из своего опыта разработки Java-приложений я обнаружил, что при использовании любого из буферных классов - BufferedInputStream, StringBuffer - мои приложения исключительно быстры.Из-за этого я использую их даже для самых маленьких файлов или строковых операций.

1 голос
/ 26 июня 2010

BufferedInputStream считывает больше файла, который вам нужен заранее.Насколько я понимаю, он проделывает большую работу заранее, например, 1 чтение большого непрерывного диска по сравнению с многим в тесном цикле.

Что касается профилирования - мне нравится профилировщик, встроенный в netbeans.Начать действительно легко.: -)

0 голосов
/ 26 июня 2013
    import java.io.*;
    class BufferedInputStream
    {
            public static void main(String arg[])throws IOException
            {
                FileInputStream fin=new FileInputStream("abc.txt");
                BufferedInputStream bis=new BufferedInputStream(fin);
                int size=bis.available();
                while(true)
                {
                        int x=bis.read(fin);
                        if(x==-1)
                        {
                                bis.mark(size);
                                System.out.println((char)x);
                        }
                }
                        bis.reset();
                        while(true)
                        {
                                int x=bis.read();
                                if(x==-1)
                                {
                                    break;
                                    System.out.println((char)x);
                                }
                        }

            }

    }
...