CodeGym /Java блог /Случаен /Вход/изход в Java. Класове FileInputStream, FileOutputStr...
John Squirrels
Ниво
San Francisco

Вход/изход в Java. Класове FileInputStream, FileOutputStream и BufferedInputStream

Публикувано в групата
"Здравейте! В днешния урок ще продължим нашия разговор за входни и изходни потоци в Java ( Java I/O ). Това не е първият урок по тази тема и със сигурност няма да е последният :) Вход/изход в Java.  Класове FileInputStream, FileOutputStream и BufferedInputStream - 1Тъй като случва, езикът Java предоставя много начини за работа с I/O. Има доста класове, които прилагат тази функционалност, така че ги разделихме на няколко урока — така че да не се объркате от самото начало :) В миналото уроци, засегнахме BufferedReader, Howто и InputStreamабстрактните OutputStreamкласове и няколко наследника. Днес ще разгледаме 3 нови класа: FileInputStream,  FileOutputStreamи  BufferedInputStream.

Класът FileOutputStream

Основната цел на FileOutputStreamкласа е да записва byteове във файл. Нищо сложно :) FileOutputStreamе една от имплементациите на OutputStreamабстрактния клас. В конструктора обектите от този клас вземат or пътя до целевия файл (където трябва да бъдат записани byteовете), or обект File. Ще разгледаме примери за всеки:

public class Main { 

   public static void main(String[] args) throws IOException { 

       File file = new File("C:\\Users\\Username\\Desktop\\test.txt"); 
       FileOutputStream fileOutputStream = new FileOutputStream(file); 

       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!"; 

       fileOutputStream.write(greetings.getBytes()); 
       fileOutputStream.close(); 
   } 
}
При създаването на Fileобекта ние предаваме желания път на конструктора. Не е необходимо да го създаваме предварително: ако не съществува, програмата ще го създаде. Можете също така да минете без да създавате допълнителен обект, просто подавайки низ с пътя:

public class Main { 

    public static void main(String[] args) throws IOException { 

       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt"); 
       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!"; 

       fileOutputStream.write(greetings.getBytes()); 
       fileOutputStream.close(); 
   } 
} 
Резултатът и в двата случая ще бъде един и същ. Можем да отворим нашия файл и да видим следното там:

Hi! Welcome to CodeGym — The best site for would-be programmers!
Но тук има един нюанс. Опитайте да стартирате codeа от горния пример няколко пъти подред. След това погледнете във file и отговорете на този въпрос: колко реда има? Само един. Но ти пусна codeа няколко пъти. Оказва се, че данните се презаписват всеки път - старите се заменят с нови. Какво да правим, ако това не ни устройва и трябва да пишем последователно във file? Ами ако искаме да напишем нашия поздрав във файл три пъти подред? Всичко е много просто. Тъй като езикът не може да знае Howво поведение ни трябва във всеки отделен случай, конструкторът FileOutputStreamможе да вземе допълнителен параметър —boolean append. Ако стойността му е истина, данните ще бъдат записани в края на file. Ако е false (а по подразбиране е false), всички стари данни ще бъдат изтрити и заменени с нови данни. Нека проверим това, като изпълним нашия модифициран code три пъти:

public class Main { 

   public static void main(String[] args) throws IOException { 

       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt", true); 
       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!\r\n"; 

       fileOutputStream.write(greetings.getBytes()); 
       fileOutputStream.close(); 
   } 
} 
Съдържание на file:

Hi! Welcome to CodeGym — The best site for would-be programmers! 
Hi! Welcome to CodeGym — The best site for would-be programmers! 
Hi! Welcome to CodeGym — The best site for would-be programmers!
Сега е различно! Не забравяйте за тази функция, когато използвате I/O класове. Имаше време, когато прекарвах часове в задачи, разбивайки мозъка си с часове, опитвайки се да разбера How данните ми изчезват от файловете :) И разбира се, Howто при другите I/O класове, не забравяйте да използвате close()метода за освобождаване на ресурси.

Класът FileInputStream

Има FileInputStreamпротивоположната цел - четене на byteове от файл. Точно Howто FileOutputStreamнаследява OutputStream, този клас произлиза от InputStreamабстрактния клас. Ще напишем няколко реда текст в нашия файл " test.txt ":

"So close no matter how far 
Couldn't be much more from the heart 
Forever trusting who we are 
And nothing else matters"
Вход/изход в Java.  Класове FileInputStream, FileOutputStream и BufferedInputStream - 2Ето How изглежда да четете данни от файл с помощта на FileInputStream:

public class Main { 

   public static void main(String[] args) throws IOException { 

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\test.txt"); 

       int i; 

       while((i=fileInputStream.read())!= -1){ 

           System.out.print((char)i); 

       } 
   } 
}
Ние четем един byte от file, преобразуваме прочетените byteове в знаци и ги показваме на конзолата. И ето изхода от конзолата:

So close no matter how far 
Couldn't be much more from the heart 
Forever trusting who we are 
And nothing else matters

Класът BufferedInputStream

Мисля, че като се имат предвид знанията от минали уроци, можете лесно да кажете защо имаме нужда от класа BufferedInputStreamи Howви предимства има в сравнение с FileInputStream:) Вече се сблъскахме с буферирани потоци, така че опитайте да познаете (or запомните), преди да продължите да четете :) Буферираните потоци са необходими главно за оптимизиране на I/O. Достъпът до източник на данни, като например четене от файл, е скъпа операция по отношение на производителността, а достъпът до файл за четене на всеки byte е разточителен. Ето защо BufferedInputStreamчете данните не един byte наведнъж, а на блокове и временно ги съхранява в специален буфер. Това ни позволява да оптимизираме програмата, като намалим броя на достъпите до file. Нека да видим How изглежда това:

public class Main { 

   public static void main(String[] args) throws IOException { 

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\test.txt"); 

       BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream, 200); 

       int i; 

       while((i = bufferedInputStream.read())!= -1){ 

           System.out.print((char)i); 
       } 
   } 
} 
Тук създадохме BufferedInputStreamобект. Неговият конструктор взема екземпляр на InputStreamкласа or някой от неговите наследници, така FileInputStreamще направи. Като допълнителен аргумент той приема размера на буфера в byteове. Благодарение на този аргумент, данните вече ще се четат от file не един byte наведнъж, а 200 byteа наведнъж! Представете си колко сме намалor броя на достъпите до файлове. За да сравните производителността, можете да вземете голям текстов файл (няколко мегаbyteа текст) и да сравните колко време отнема в мorсекунди за четене и извеждане към конзолата с помощта на FileInputStreamи BufferedInputStream. Ето code, който демонстрира и двете опции:

public class Main { 

   public static void main(String[] args) throws IOException { 

       Date date = new Date(); 

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\textBook.rtf"); 
       BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream); 

       int i; 
       while((i = bufferedInputStream.read())!= -1){ 

           System.out.print((char)i); 
       } 

       Date date1 = new Date(); 
       System.out.println((date1.getTime() - date.getTime())); 
   } 
} 

 
public class Main { 

   public static void main(String[] args) throws IOException { 

       Date date = new Date(); 
       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\26951280.rtf"); 

       int i; 
       while((i = fileInputStream.read())!= -1){ 

           System.out.print((char)i); 
       } 


       Date date1 = new Date(); 
       System.out.println((date1.getTime() - date.getTime())); 
   }
}
При четене на файл от 1,5 MB на моя компютър FileInputStreamзавърших работата за ~3500 мorсекунди, но BufferedInputStreamя управлявах за ~1700 мorсекунди. Както можете да видите, буферираният поток оптимизира работата, намалявайки я наполовина! :) Ще продължим да изучаваме I/O класове — до скоро!
Коментари
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION