web-dev-qa-db-fra.com

Utilisation de BufferedInputStream

Permettez-moi de commencer cette publication par une simple mise en garde. Je suis un débutant total en matière de Java. Je programme PHP depuis un moment, mais j'étais prêt à créer une application de bureau. J'ai donc décidé d'utiliser Java pour diverses raisons.

L'application sur laquelle je travaille en est au début (moins de 5 classes) et j'ai besoin de lire des octets à partir d'un fichier local. En règle générale, les fichiers pèsent actuellement moins de 512 Ko (mais peuvent s’agrandir ultérieurement). Actuellement, j’utilise FileInputStream pour lire le fichier en tableaux de trois octets, ce qui répond parfaitement à mes besoins. Cependant, j’ai vu une BufferedInputStream mentionnée, et je me demandais si la façon dont je le fais actuellement est la meilleure ou si je devrais aussi utiliser une BufferedInputStream.

J'ai fait quelques recherches et lu quelques questions ici sur Stack Overflow, mais j'ai toujours du mal à comprendre la meilleure situation pour savoir quand utiliser et ne pas utiliser la variable BufferedInputStream. Dans ma situation, le premier tableau dans lequel je lis des octets ne représente que quelques octets (moins de 20). Si les données que je reçois sont correctes dans ces octets, je lis le reste du fichier dans deux autres tableaux d'octets de taille variable.

J'ai également entendu beaucoup de gens mentionner le profilage pour voir ce qui est le plus efficace dans chaque cas particulier. Cependant, je n'ai aucune expérience en profilage et je ne sais pas trop par où commencer. J'aimerais quelques suggestions à ce sujet aussi.

Je suis désolé pour un si long post, mais je veux vraiment apprendre et comprendre la meilleure façon de faire ces choses. J'ai toujours la mauvaise habitude de remettre en question mes décisions, alors j'aimerais connaître votre avis. Merci!

32
Jason Watkins

Si vous effectuez régulièrement de petites lectures, une BufferedInputStream vous donnera des performances nettement meilleures. Chaque demande de lecture sur un flux non mis en mémoire tampon entraîne généralement un appel système au système d'exploitation pour lire le nombre d'octets demandé. Un appel système peut entraîner des milliers d'instructions machine par appel système. Un flux mis en mémoire tampon réduit cela en effectuant une lecture volumineuse pour (disons) jusqu'à 8 000 octets dans une mémoire tampon interne, puis en distribuant des octets à partir de cette mémoire tampon. Cela peut réduire considérablement le nombre d'appels système.

Toutefois, si vous effectuez régulièrement des lectures volumineuses (par exemple, 8 000 ou plus), la variable BufferedInputStream ralentit le processus. En règle générale, vous ne réduisez pas le nombre d'appels système et la mise en mémoire tampon introduit une étape supplémentaire de copie des données.

Dans votre cas d'utilisation (où vous lisez un bloc de 20 octets, puis beaucoup de gros morceaux), je dirais que l'utilisation d'un BufferedInputStream est plus susceptible de réduire les performances que de les augmenter. Mais finalement, cela dépend des modèles de lecture actuels.

77
Stephen C

Si vous utilisez un tableau relativement volumineux pour lire les données un morceau à la fois, alors BufferedInputStream introduira simplement une copie inutile. (N'oubliez pas que read ne lit pas nécessairement tout le tableau - vous voudrez peut-être DataInputStream.readFully). Où BufferedInputStream gagne est lorsque vous faites beaucoup de petites lectures.

4

BufferedInputStream lit plus du fichier dont vous avez besoin à l'avance. Si je comprends bien, il fait plus de travail à l’avance, par exemple, 1 gros disque en lecture continue par rapport à beaucoup de choses dans une boucle serrée.

En ce qui concerne le profilage, j'aime le profileur intégré à Netbeans. C'est vraiment facile de commencer avec. :-)

1
Jubal

Je ne peux pas parler du profilage, mais de par mon expérience en développement d'applications Java, j'ai constaté qu'en utilisant l'une des classes de tampons - BufferedInputStream, StringBuffer - mes applications sont exceptionnellement plus rapides. Pour cette raison, je les utilise même pour les plus petits fichiers ou les opérations sur les chaînes.

1
Jason McCreary
    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);
                                }
                        }

            }

    }
0
Octavians