Использование BufferedInputStream

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

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

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

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

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

5 ответов


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

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

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


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


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

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


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


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

            }

    }