【个人笔记】关于IO类中流的整理
生活随笔
收集整理的這篇文章主要介紹了
【个人笔记】关于IO类中流的整理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
? ?學習IO部分的知識后,被處理流的各種類搞得有點亂,所以得寫篇文章總結下。IO包里面有很多輸入輸出類,一般我們是通過控制流來控制輸入輸出的。 ? ?IO包里面對于控制流分為兩大類,一類是字節流,一類是字符流。字符流的兩個大類是Reader,Writer,字節流的是InputSream和OutputStream。通過這兩個流以及其子類,我們可以控制系統與程序的輸入輸出。1. ?從類名看流(以字符流為例)1.1 根據命名規則來選擇類 ? ? ?由上圖可以看出Reader、Writer類有很多子類,每個子類的名稱構造都是“功能+對應的類別”,這就是IO包類命名的規則。所以我們可以從類名的后一部分看出它是屬于字符流還是字節流的,然后從前一部分看出它的功能是什么。根據這個規則,我們可以選擇合適的類來處理流。1.2 各類的作用以及關系 ? IO包的類不少,但是他們之間都是有關系的,想Reader用來讀取字節流,其子類是根據要讀取不同的源而需要不同的功能而劃分的。比如Reader的子類BufferedReader就是提供緩沖讀取,提高效率。CharArrayReader則是把字符數組當做源來讀取流數據,FilterReader則是對已過濾流的讀取,OutputStreamReader則是轉換流,是字符流與字節流之間的橋梁,因為他可以把字節流當做源,讀取數據,當做字節流輸出,所以它在初始化可以選擇編碼,如果不設置,則設置為系統的默認編碼。這個類會被經常用到。而StringReader跟CharArrayReader類似,只是他是把字符串當做源來讀數據。另外常用到的還有InputSreamReader的子類FileReader,它可以直接從File對象讀取數據,一般能直接操作文件的類都會比較常用到。至于Writer類跟Reader類似,但是它有個功能比較強大的子類,就是PrintWriter。該類在開發中很經常用到。 ? ? ? 上圖是PrintWriter的構造方法,可以看出他面向的目的流是多樣化的,可以直接往File對象(同時可以為其采用相應的字符集)、OutputStream輸出流(可設置是否每次寫入后自動flush)寫數據,可以通過字符串構造的文件路徑名建立文件并寫寫入,同時可以傳入Writer對象,增強Writer的功能。而且它還可以使用print,printf,println往目的流輸入各種數據。一下是其使用的一個案例:package ? tst.IODemo;
import ? java.io. * ;
publicclass ? PrintWriterDemo {
publicstaticvoid ? main(String[] args) ? throws ? IOException {
? ? ? ? writeMethods ();
}
publicstaticvoid ? writeMethods() ? throws ? FileNotFoundException {
? ? ? ?PrintWriter pw =new ? PrintWriter( "d:\\a.txt" ); ? ?//可以寫到指定的文件里
char [] buf = { 'a' , 'b' , 'c' };
? ? ? ?pw.write(buf); ? ? ?//可以寫入字符數據
? ? ? ?pw.println( "123" ); ? //可以直接用 println 方法往目的流輸入數據
? ? ? ?pw.print( "456" );
? ? ? ?pw.println(); ? ?//寫入一個換行符
? ? ? ?pw.write( 49 ); ? ?//可以寫入整數,但是寫到文本里會根據ASCII表寫入相應的字符
? ? ? ?pw.write( "weuroei" ); ? //可以直接寫字符串
? ? ? ?pw.format( "%s" , ? "wcc" ); ? ?//可以給字符串規定格式寫入
? ? ? ?pw.close();
? ?}
} ? ?各類的關系:雖然上面講的都是字符流,但是他們的道理是相同的,只是一個是以字符形式讀取和寫入,而一個是以字節形式讀取寫入。他們的區別是源或目的不同,所以他們的構造方法傳入的參數不同,會根據是什么作用而傳入何種參數,比如StringReader的構造參數會傳入字符串,而CharArrayReader傳入的則是字節數組。大體方法相同,但是不同功能的類會有區別于其他類的特有功能,比如處理字符串的,處理字節數組的,緩沖的。2. 程序實踐2.1 實踐中使用的思路總結 ? ?一般該類的使用前,首先判斷是要操作字節流還是字符流,再者確定是要讀取或者是寫入。確定后一般分三層進行,必須要有源流或是目的流,然后根據該流是文件的,字符串的還是字節的。接下來就是是否需要字節流與字符流之間的轉換,需要則選InputSreamReader、OutputStreamWriter。然后就考慮讀寫效率的提高,這個就可以選擇帶Buffered的了。還有其他各種各樣的功能,比如合并流的SequenceInputStream、處理音頻的AudioInputStream等等,記住大概使用思路,使用時忘記不懂再查API就OK了。2.2 各種程序實踐
import ?java.io.*;
publicclass ?FileReaderDemo {
publicstaticvoid ?main(String[] args) ?throws ?IOException {
? ? ? ?FileReader fr =new ?FileReader( "WriterException.java" );
char [] buf =newchar [1024];
int ?num;
while ((num = fr.read(buf)) !=-1) {
? ? ? ? ? ?System. out .print( new ?String(buf,0,num));
? ? ? ?} ? ? ? ?
? ? ? ?fr.close();
? ?}
}(2)擁戴Buffered相關類提高FileReader和FileWriter讀寫效率: ? ?該時間里面寫用BufferedWriter但是自己根據BufferedReader的原理,自己寫了一個MyBufReader模擬BufferedReader的運行,結果同樣可讀取數據。該例子里的BufferedReader和BufferedWriter主要是用于提高FileReader和FileWriter兩者個工作效率,讀N個數據放到緩存,再一次性寫到輸出流,避免讀一個字節寫一次,提高效率。package ?tst.IODemo;
import ?java.io.*;
publicclass ?BufCopyText {
publicstaticvoid ?main(String[] args) {
? ? ? ?MyBufReader fr = ?null ;
? ? ? ?BufferedWriter fw = ?null ;
try ?{
? ? ? ? ? ?fr =new ?MyBufReader( new ?FileReader( "E:\\學習資源\\cmd.exe" ));
? ? ? ? ? ?fw =new ?BufferedWriter( new ?FileWriter( "E:\\學習資源\\cmd1.exe" ));
? ? ? ? ? ?String buf = ?null ;
while ((buf = fr.myReadLine()) != ?null ) {
? ? ? ? ? ? ? ?fw.write(buf);
? ? ? ? ? ? ? ?fw.newLine();
? ? ? ? ? ? ? ?fw.flush();
? ? ? ? ? ?}
? ? ? ?} ?catch ?(IOException e) {
thrownew ?RuntimeException( "讀寫失敗!" );
? ? ? ?} ?finally ?{
if ?(fr != ?null ) {
try ?{
? ? ? ? ? ? ? ? ? ?fr.close();
? ? ? ? ? ? ? ?} ?catch ?(IOException e) {
thrownew ?RuntimeException( "讀緩存關閉失敗。" );
? ? ? ? ? ? ? ?}
? ? ? ? ? ?}
if ?(fw != ?null ) {
try ?{
? ? ? ? ? ? ? ? ? ?fw.close();
? ? ? ? ? ? ? ?} ?catch ?(IOException e) {
thrownew ?RuntimeException( "寫緩存關閉失敗。" );
? ? ? ? ? ? ? ?}
? ? ? ? ? ?}
? ? ? ?} ? ?
? ?}
}
/**
* 該類模擬BufferedReader的工作原理,作用相同。
* */
class ?MyBufReader {
? ?FileReader ?r ;
int ? buf ;
public ?MyBufReader(FileReader r) {
this . r ?= r;
? ?}
public ?String myReadLine() ?throws ?IOException {
? ? ? ?StringBuilder sb =new ?StringBuilder();
while (( buf ?= ?r .read()) !=-1) {
if ( buf ?=='\r' ) {
continue ;
? ? ? ? ? ?}
if ( buf ?=='\n' ) {
return ?sb.toString();
? ? ? ? ? ?}
? ? ? ? ? ?sb.append(( char ) buf );
? ? ? ?}
if (sb.length() !=0) {
return ?sb.toString();
? ? ? ?}
return ? null ;
? ?}
publicvoid ?close() ?throws ?IOException {
? ? ? ? r .close();
? ?}
}
import ?java.io.*;
publicclass ?OutputStreamWriterDemo {
publicstaticvoid ?main(String[] args) ?throws ?IOException {
? ? ? ?BufferedReader br =new ?BufferedReader( new ?InputStreamReader(System. in ));
? ? ? ?BufferedWriter bw =new ?BufferedWriter( new ?OutputStreamWriter( new ?FileOutputStream( "a.txt" ), "UTF-8" ));
? ? ? ?String buf = ?null ;
while ((buf = br.readLine()) != ?null ) {
if (buf.equals( "over" )) ?break ; ? ?//當輸入“over”時則寫入結束,over不寫入文件
? ? ? ? ? ?bw.write(buf);
? ? ? ? ? ?bw.newLine();
? ? ? ?} ? ? ? ?
? ? ? ?br.close();
? ? ? ?bw.close(); ? ? ? ?
? ?}
}(4)讀取一個文件的內容,并輸出到控制臺上: ? ? 讀取一個文件,把內容輸出到控制臺上,同時獲取開始和結束時間,比較BufferedInputSream和BufferedOutputStream與DataInputStream和DataOutputStream的效率,果然發現Buffered類的效率搞了將近一倍,使用Buffered類的我們不需要去控制他的緩沖區,只要跟其他類一樣正常使用就行,他內部自己有使用緩沖方法的機制。package ?tst.IODemo;
import ?java.io.*;
publicclass ?BufInputStream {
publicstaticvoid ?main(String[] args) ?throws ?IOException {
? ? ? ? ?BufferedInputStream bis =new ?BufferedInputStream( new ?FileInputStream( "SysInfo.txt" ));
? ? ? ? ?BufferedOutputStream bop =new ?BufferedOutputStream(System. out );
// ? ? ? ?DataInputStream ?bis ?= new DataInputStream(new FileInputStream("SysInfo.txt"));
// ? ? ? ?DataOutputStream ?bop ?= new DataOutputStream(System.out);
int ?buf;
long ?start = System. currentTimeMillis ();
while ((buf = bis.read()) !=-1) {
? ? ? ? ? ?bop.write(buf);
? ? ? ? ? ?bop.flush(); ? ? ? ? ? ?
? ? ? ? } ? ? ? ?
long ?end = System. currentTimeMillis ();
? ? ? ? ?System. out .println((end - start) +"毫秒" );
? ? ? ? ?bis.close();
? ? ? ? ?bop.close();
? ?}
}(5)合并流 ? ? 把多個輸入流合并成一個大的輸入流,然后一起寫到輸出流中。package tst.IODemo;
import java.io.*;
import java.util.*;
publicclass SequenceDemo {
publicstaticvoid main(String[] args) throws IOException {
? ? ? ?Vector<FileInputStream> v =new Vector<FileInputStream>();
? ? ? ?PrintWriter pw;
try {
//從當前目錄讀取三個txt文件1.txt,2.txt,3.txt
? ? ? ? ? ?FileInputStream fis1 =new FileInputStream("D:\\1.txt");
? ? ? ? ? ?FileInputStream fis2 =new FileInputStream("D:\\2.txt");
? ? ? ? ? ?FileInputStream fis3 =new FileInputStream("D:\\3.txt");
//創建4.txt文件
? ? ? ? ? ?pw =new PrintWriter(new FileOutputStream("D:\\4.txt"));
//把3個文件存入向量集合v中,是為了生成下面的Enumeration<FileInputStream>集合
? ? ? ? ? ?v.add(fis1);
? ? ? ? ? ?v.add(fis2);
? ? ? ? ? ?v.add(fis3);
? ? ? ?} catch(FileNotFoundException e) {
thrownew RuntimeException("文件打開失敗。請查詢文件是否存在!");
? ? ? ?}
? ? ? ?Enumeration<FileInputStream> e = v.elements();
//SequenceInputStream構造函數只要兩個方法,一個是傳入兩個InputSream,這只能合并兩個流,
//想要合并多個流,則需要傳入一個Enumeration集合才可以。
? ? ? ?SequenceInputStream sis =new SequenceInputStream(e);
int buf;
while((buf = sis.read()) !=-1) {
? ? ? ? ? ?pw.write(buf); ? ? ? ? ? ? ? ? ?//三個流一起寫入到輸出流
? ? ? ?} ?
? ? ? ?sis.close();
? ? ? ?pw.close();
? ? ? ?System.out.println("Done!");
? ?}
}
import ? java.io. * ;
publicclass ? PrintWriterDemo {
publicstaticvoid ? main(String[] args) ? throws ? IOException {
? ? ? ? writeMethods ();
}
publicstaticvoid ? writeMethods() ? throws ? FileNotFoundException {
? ? ? ?PrintWriter pw =new ? PrintWriter( "d:\\a.txt" ); ? ?//可以寫到指定的文件里
char [] buf = { 'a' , 'b' , 'c' };
? ? ? ?pw.write(buf); ? ? ?//可以寫入字符數據
? ? ? ?pw.println( "123" ); ? //可以直接用 println 方法往目的流輸入數據
? ? ? ?pw.print( "456" );
? ? ? ?pw.println(); ? ?//寫入一個換行符
? ? ? ?pw.write( 49 ); ? ?//可以寫入整數,但是寫到文本里會根據ASCII表寫入相應的字符
? ? ? ?pw.write( "weuroei" ); ? //可以直接寫字符串
? ? ? ?pw.format( "%s" , ? "wcc" ); ? ?//可以給字符串規定格式寫入
? ? ? ?pw.close();
? ?}
} ? ?各類的關系:雖然上面講的都是字符流,但是他們的道理是相同的,只是一個是以字符形式讀取和寫入,而一個是以字節形式讀取寫入。他們的區別是源或目的不同,所以他們的構造方法傳入的參數不同,會根據是什么作用而傳入何種參數,比如StringReader的構造參數會傳入字符串,而CharArrayReader傳入的則是字節數組。大體方法相同,但是不同功能的類會有區別于其他類的特有功能,比如處理字符串的,處理字節數組的,緩沖的。2. 程序實踐2.1 實踐中使用的思路總結 ? ?一般該類的使用前,首先判斷是要操作字節流還是字符流,再者確定是要讀取或者是寫入。確定后一般分三層進行,必須要有源流或是目的流,然后根據該流是文件的,字符串的還是字節的。接下來就是是否需要字節流與字符流之間的轉換,需要則選InputSreamReader、OutputStreamWriter。然后就考慮讀寫效率的提高,這個就可以選擇帶Buffered的了。還有其他各種各樣的功能,比如合并流的SequenceInputStream、處理音頻的AudioInputStream等等,記住大概使用思路,使用時忘記不懂再查API就OK了。2.2 各種程序實踐
(1)FileReader的使用(Reader-InputSreamReader子類)
? ?由該類的名字我們可以知道他是操作文件的,可以直接打開文件,讀取文件的數據到輸入流。
package ?tst.IODemo;import ?java.io.*;
publicclass ?FileReaderDemo {
publicstaticvoid ?main(String[] args) ?throws ?IOException {
? ? ? ?FileReader fr =new ?FileReader( "WriterException.java" );
char [] buf =newchar [1024];
int ?num;
while ((num = fr.read(buf)) !=-1) {
? ? ? ? ? ?System. out .print( new ?String(buf,0,num));
? ? ? ?} ? ? ? ?
? ? ? ?fr.close();
? ?}
}(2)擁戴Buffered相關類提高FileReader和FileWriter讀寫效率: ? ?該時間里面寫用BufferedWriter但是自己根據BufferedReader的原理,自己寫了一個MyBufReader模擬BufferedReader的運行,結果同樣可讀取數據。該例子里的BufferedReader和BufferedWriter主要是用于提高FileReader和FileWriter兩者個工作效率,讀N個數據放到緩存,再一次性寫到輸出流,避免讀一個字節寫一次,提高效率。package ?tst.IODemo;
import ?java.io.*;
publicclass ?BufCopyText {
publicstaticvoid ?main(String[] args) {
? ? ? ?MyBufReader fr = ?null ;
? ? ? ?BufferedWriter fw = ?null ;
try ?{
? ? ? ? ? ?fr =new ?MyBufReader( new ?FileReader( "E:\\學習資源\\cmd.exe" ));
? ? ? ? ? ?fw =new ?BufferedWriter( new ?FileWriter( "E:\\學習資源\\cmd1.exe" ));
? ? ? ? ? ?String buf = ?null ;
while ((buf = fr.myReadLine()) != ?null ) {
? ? ? ? ? ? ? ?fw.write(buf);
? ? ? ? ? ? ? ?fw.newLine();
? ? ? ? ? ? ? ?fw.flush();
? ? ? ? ? ?}
? ? ? ?} ?catch ?(IOException e) {
thrownew ?RuntimeException( "讀寫失敗!" );
? ? ? ?} ?finally ?{
if ?(fr != ?null ) {
try ?{
? ? ? ? ? ? ? ? ? ?fr.close();
? ? ? ? ? ? ? ?} ?catch ?(IOException e) {
thrownew ?RuntimeException( "讀緩存關閉失敗。" );
? ? ? ? ? ? ? ?}
? ? ? ? ? ?}
if ?(fw != ?null ) {
try ?{
? ? ? ? ? ? ? ? ? ?fw.close();
? ? ? ? ? ? ? ?} ?catch ?(IOException e) {
thrownew ?RuntimeException( "寫緩存關閉失敗。" );
? ? ? ? ? ? ? ?}
? ? ? ? ? ?}
? ? ? ?} ? ?
? ?}
}
/**
* 該類模擬BufferedReader的工作原理,作用相同。
* */
class ?MyBufReader {
? ?FileReader ?r ;
int ? buf ;
public ?MyBufReader(FileReader r) {
this . r ?= r;
? ?}
public ?String myReadLine() ?throws ?IOException {
? ? ? ?StringBuilder sb =new ?StringBuilder();
while (( buf ?= ?r .read()) !=-1) {
if ( buf ?=='\r' ) {
continue ;
? ? ? ? ? ?}
if ( buf ?=='\n' ) {
return ?sb.toString();
? ? ? ? ? ?}
? ? ? ? ? ?sb.append(( char ) buf );
? ? ? ?}
if (sb.length() !=0) {
return ?sb.toString();
? ? ? ?}
return ? null ;
? ?}
publicvoid ?close() ?throws ?IOException {
? ? ? ? r .close();
? ?}
}
(3)接下來則是字節流的實踐,從鍵盤往文件里面寫數據:
? ? 該例子實現的功能是在控制臺通過鍵盤輸入數據,然后通過FileOutputStream打開一個文件,通過OutputStreamWriter把輸入的字節流轉換成字符流輸出到a.txt文本,同時運用BufferedWriter提高寫入效率。
package ?tst.IODemo;import ?java.io.*;
publicclass ?OutputStreamWriterDemo {
publicstaticvoid ?main(String[] args) ?throws ?IOException {
? ? ? ?BufferedReader br =new ?BufferedReader( new ?InputStreamReader(System. in ));
? ? ? ?BufferedWriter bw =new ?BufferedWriter( new ?OutputStreamWriter( new ?FileOutputStream( "a.txt" ), "UTF-8" ));
? ? ? ?String buf = ?null ;
while ((buf = br.readLine()) != ?null ) {
if (buf.equals( "over" )) ?break ; ? ?//當輸入“over”時則寫入結束,over不寫入文件
? ? ? ? ? ?bw.write(buf);
? ? ? ? ? ?bw.newLine();
? ? ? ?} ? ? ? ?
? ? ? ?br.close();
? ? ? ?bw.close(); ? ? ? ?
? ?}
}(4)讀取一個文件的內容,并輸出到控制臺上: ? ? 讀取一個文件,把內容輸出到控制臺上,同時獲取開始和結束時間,比較BufferedInputSream和BufferedOutputStream與DataInputStream和DataOutputStream的效率,果然發現Buffered類的效率搞了將近一倍,使用Buffered類的我們不需要去控制他的緩沖區,只要跟其他類一樣正常使用就行,他內部自己有使用緩沖方法的機制。package ?tst.IODemo;
import ?java.io.*;
publicclass ?BufInputStream {
publicstaticvoid ?main(String[] args) ?throws ?IOException {
? ? ? ? ?BufferedInputStream bis =new ?BufferedInputStream( new ?FileInputStream( "SysInfo.txt" ));
? ? ? ? ?BufferedOutputStream bop =new ?BufferedOutputStream(System. out );
// ? ? ? ?DataInputStream ?bis ?= new DataInputStream(new FileInputStream("SysInfo.txt"));
// ? ? ? ?DataOutputStream ?bop ?= new DataOutputStream(System.out);
int ?buf;
long ?start = System. currentTimeMillis ();
while ((buf = bis.read()) !=-1) {
? ? ? ? ? ?bop.write(buf);
? ? ? ? ? ?bop.flush(); ? ? ? ? ? ?
? ? ? ? } ? ? ? ?
long ?end = System. currentTimeMillis ();
? ? ? ? ?System. out .println((end - start) +"毫秒" );
? ? ? ? ?bis.close();
? ? ? ? ?bop.close();
? ?}
}(5)合并流 ? ? 把多個輸入流合并成一個大的輸入流,然后一起寫到輸出流中。package tst.IODemo;
import java.io.*;
import java.util.*;
publicclass SequenceDemo {
publicstaticvoid main(String[] args) throws IOException {
? ? ? ?Vector<FileInputStream> v =new Vector<FileInputStream>();
? ? ? ?PrintWriter pw;
try {
//從當前目錄讀取三個txt文件1.txt,2.txt,3.txt
? ? ? ? ? ?FileInputStream fis1 =new FileInputStream("D:\\1.txt");
? ? ? ? ? ?FileInputStream fis2 =new FileInputStream("D:\\2.txt");
? ? ? ? ? ?FileInputStream fis3 =new FileInputStream("D:\\3.txt");
//創建4.txt文件
? ? ? ? ? ?pw =new PrintWriter(new FileOutputStream("D:\\4.txt"));
//把3個文件存入向量集合v中,是為了生成下面的Enumeration<FileInputStream>集合
? ? ? ? ? ?v.add(fis1);
? ? ? ? ? ?v.add(fis2);
? ? ? ? ? ?v.add(fis3);
? ? ? ?} catch(FileNotFoundException e) {
thrownew RuntimeException("文件打開失敗。請查詢文件是否存在!");
? ? ? ?}
? ? ? ?Enumeration<FileInputStream> e = v.elements();
//SequenceInputStream構造函數只要兩個方法,一個是傳入兩個InputSream,這只能合并兩個流,
//想要合并多個流,則需要傳入一個Enumeration集合才可以。
? ? ? ?SequenceInputStream sis =new SequenceInputStream(e);
int buf;
while((buf = sis.read()) !=-1) {
? ? ? ? ? ?pw.write(buf); ? ? ? ? ? ? ? ? ?//三個流一起寫入到輸出流
? ? ? ?} ?
? ? ? ?sis.close();
? ? ? ?pw.close();
? ? ? ?System.out.println("Done!");
? ?}
}
轉載于:https://blog.51cto.com/cthhqu/1262101
總結
以上是生活随笔為你收集整理的【个人笔记】关于IO类中流的整理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux/Unix环境下的make命令
- 下一篇: root目录空间不够的问题