Java的IO总结
非流式文件類--File類
??從定義看,File類是Object的直接子類,同時它繼承了Comparable接口可以進行數組的排序。
File類的操作包括文件的創建、刪除、重命名、得到路徑、創建時間等,以下是文件操作常用的函數。
?
?
File類是對文件系統中文件以及文件夾進行封裝的對象,可以通過對象的思想來操作文件和文件夾。File類保存文件或目錄的各種元數據信息,包括文件名、文件長度、最后修改時間、是否可讀、獲取當前文件的路徑名,判斷指定文件是否存在、獲得當前目錄中的文件列表,創建、刪除文件和目錄等方法。?
File類共提供了三個不同的構造函數,以不同的參數形式靈活地接收文件和目錄名信息。
構造函數:
1)File (String ? pathname) ??
? ? ?例:File ?f1=new File("FileTest1.txt"); //創建文件對象f1,f1所指的文件是在當前目錄下創建的FileTest1.txt
2)File (String ?parent ?, ?String child)
? ? ?例:File f2=new ?File(“D:\\dir1","FileTest2.txt") ;// ?注意:D:\\dir1目錄事先必須存在,否則異常
3)File (File ? ?parent ?, String child)
? ? ?例:File ?f4=new File("\\dir3");
? ? ? ? ? File ?f5=new File(f4,"FileTest5.txt"); ?//在如果 \\dir3目錄不存在使用f4.mkdir()先創建
? ? ? ? 一個對應于某磁盤文件或目錄的File對象一經創建, 就可以通過調用它的方法來獲得文件或目錄的屬性。 ? ?
? ? ? ?1)public boolean exists( ) 判斷文件或目錄是否存在
? ? ? ?2)public boolean isFile( ) 判斷是文件還是目錄?
? ? ? ?3)public boolean isDirectory( ) 判斷是文件還是目錄
? ? ? ?4)public String getName( ) 返回文件名或目錄名
? ? ? ?5)public String getPath( ) 返回文件或目錄的路徑。
? ? ? ?6)public long length( ) 獲取文件的長度?
? ? ? ?7)public String[ ] list ( ) 將目錄中所有文件名保存在字符串數組中返回。?
? ? ? ?File類中還定義了一些對文件或目錄進行管理、操作的方法,常用的方法有:
? ? ? ?1) public boolean renameTo( File newFile ); ? ?重命名文件
? ? ? ?2) public void delete( ); ? 刪除文件
? ? ? ?3) ?public boolean mkdir( ); 創建目錄
流簡單概念介紹
在Java程序中,對于數據的輸入/輸出操作以"流" (stream) 方式進行;
J2SDK提供了各種各樣的"流"類,用以獲取不同種類的數據;程序中通過標準的方法輸入或輸出數據。
Java的流類型一般位于java.io包中
流的方向:
輸入流:數據源到程序(InputStream、Reader讀進來)
輸出流:程序到目的地(OutPutStream、Writer寫出去)
處理數據單元:
字節流:按照字節讀取數據(InputStream、OutputStream)
字符流:按照字符讀取數據(Reader、Writer)
功能不同:
節點流:可以直接從數據源或目的地讀寫數據。
處理流(包裝流):不直接連接到數據源或目的地,是其他流進行封裝。目的主要是簡化操作和提高性能.
節點流和處理流的關系:
節點流處于io操作的第一線,所有操作必須通過他們進行;
處理流可以對其他流進行處理(提高效率或操作靈活性).
字節流基類
1).InputStream
InputStream:字節輸入流基類,抽象類是表示字節輸入流的所有類的超類。
常用方法:// 從輸入流中讀取數據的下一個字節abstract int read()// 從輸入流中讀取一定數量的字節,并將其存儲在緩沖區數組 b中int read(byte[] b)// 將輸入流中最多 len 個數據字節讀入 byte 數組int read(byte[] b, int off, int len)// 跳過和丟棄此輸入流中數據的 n個字節long skip(long n)// 關閉此輸入流并釋放與該流關聯的所有系統資源void close()2).OutputStream
OutputStream:字節輸出流基類,抽象類是表示輸出字節流的所有類的超類。
常用方法:// 將 b.length 個字節從指定的 byte 數組寫入此輸出流void write(byte[] b)// 將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此輸出流void write(byte[] b, int off, int len)// 將指定的字節寫入此輸出流abstract void write(int b)// 關閉此輸出流并釋放與此流有關的所有系統資源void close()// 刷新此輸出流并強制寫出所有緩沖的輸出字節void flush()字節流FileInputStream和FileOuputStream
介紹
1).FileInputStream
FileInputStream:字節文件輸入流,從文件系統中的某個文件中獲得輸入字節,用于讀取諸如圖像數據之類的原始字節流。
構造方法:// 通過打開一個到實際文件的連接來創建一個FileInputStream,該文件通過文件系統中的File對象file指定FileInputStream(File file)// 通過打開一個到實際文件的連接來創建一個FileInputStream,該文件通過文件系統中的路徑name指定FileInputStream(String name)常用方法:覆蓋和重寫了父類的的常用方法。2).FileOutputStream
FileOutputStream:字節文件輸出流是用于將數據寫入到File,從程序中寫入到其他位置。
構造方法:// 創建一個向指定File對象表示的文件中寫入數據的文件輸出流FileOutputStream(File file)// 創建一個向指定File對象表示的文件中寫入數據的文件輸出流FileOutputStream(File file, boolean append)// 創建一個向具有指定名稱的文件中寫入數據的輸出文件流FileOutputStream(String name)// 創建一個向具有指定name的文件中寫入數據的輸出文件流FileOutputStream(String name, boolean append)常用方法:覆蓋和重寫了父類的的常用方法。文件復制
(熟悉操作):
/** * 功能:文件復制 * 技能:FileInputStream和FileOuputStream * * 總結 * 如何創建流 * InputStream is = new FileInputStream(new File("e:/readme.txt")); * OutputStream os = new FileOutputStream(new File("e:\\readme2.txt")); * * * 流使用完畢一定要關閉 * * 如何使用流 * n = is.read(); * os.write(n); * * 缺點: * @author Administrator * */ public class TestCopy1 {public static void main(String[] args) throws IOException {//創建一個輸入流和輸出流 // File file = new File("e:/readme.txt"); // InputStream is = new FileInputStream(file);InputStream is = new FileInputStream(new File("e:/readme.txt")); // File file2 = new File("e:\readme2.txt"); // OutputStream os = new FileOutputStream(file2);OutputStream os = new FileOutputStream(new File("e:\\readme2.txt"));//使用輸入流和輸出流完成文件復制int n;//中轉站,比較小(水杯)//讀一個字節n = is.read();//從輸入流讀取一個字節的內容賦給nwhile(n != -1){//沒有到達末尾//寫一個字節os.write(n);//輸出一個字節//System.out.print((char)n);//讀一個字節n = is.read();} //關閉輸入流和輸出流is.close();os.close();}}正式標準實現:(一次1024)
/** * 功能:文件復制 * 技能:FileInputStream和FileOuputStream * * 總結 * 如何創建流 * InputStream is = new FileInputStream(new File("e:/readme.txt")); * OutputStream os = new FileOutputStream(new File("e:\\readme2.txt")); * * * 流使用完畢一定要關閉 * * 如何使用流 * n = is.read(); * os.write(n); * * 缺點:中轉站太小 * * @author Administrator * */ public class TestCopy2 {public static void main(String[] args) throws IOException {//創建輸入流和輸出流InputStream fis = new FileInputStream("e:/JDK_API_1_6_zh_CN.CHM");OutputStream fos = new FileOutputStream("e:/JDK_API_1_6_zh_CN2.CHM");//使用輸入流和輸出流byte [] buf = new byte[1024];//讀一次int len = fis.read(buf);//將源文件的內容寫入到buf中,返回真實讀取的字節數while(len != -1){//寫一次//fos.write(buf);//寫1024fos.write(buf, 0, len);//讀一次len = fis.read(buf);}//關閉輸入流和輸出流fis.close();fos.close();}}?
字符流Reader和Writer
字符流基類
1).Reader
Reader:讀取字符流的抽象類.
常用方法:// 讀取單個字符int read()// 將字符讀入數組int read(char[] cbuf)// 將字符讀入數組的某一部分abstract int read(char[] cbuf, int off, int len)// 跳過字符long skip(long n)// 關閉該流并釋放與之關聯的所有資源abstract void close()2).Writer
Writer:寫入字符流的抽象類.
常用方法:// 寫入字符數組void write(char[] cbuf)// 寫入字符數組的某一部分abstract void write(char[] cbuf, int off, int len)// 寫入單個字符void write(int c)// 寫入字符串void write(String str)// 寫入字符串的某一部分void write(String str, int off, int len)// 將指定字符添加到此 writerWriter append(char c)// 將指定字符序列添加到此 writerWriter append(CharSequence csq)// 將指定字符序列的子序列添加到此 writer.AppendableWriter append(CharSequence csq, int start, int end)// 關閉此流,但要先刷新它abstract void close()// 刷新該流的緩沖abstract void flush()文件復制:
熟悉操作? ? ?
/** * * 1.字節流可以讀寫任何文件(文本文件、二進制文件(音頻視頻圖片 chm)) * 字符流只可以讀寫文本文件(word不是文本文件) * 但是字符串處理非英文字符文本文件非常方便 * * 2.其實只有字節流,沒有字符流 * 字符流底層使用的還是字節流 * Java在字節流基礎上提供了字符流,給編程帶來便利 * * 3.字符流如何是英文字符還是中文字符 * 英文占一個字節,最高位是0 0111 0011 * 中文占兩個字節,最高位是1 1011 1011 1001 1101 * * 4.缺陷:沒有進行異常處理 * * * @author Administrator * */ public class TestCopy1 {public static void main(String[] args) throws IOException {//創建輸入流和輸出流Reader fr = new FileReader(new File("e:/readme.txt"));Writer fw = new FileWriter(new File("e:\\readme2.txt"));//默認是false 覆蓋//Writer fw = new FileWriter(new File("e:\\readme2.txt"), true);//使用輸入流和輸出流 // //讀一個字符 // int ch = fr.read(); //中轉站是一個字符 // while(ch !=-1){ // //寫一個字符 // fw.write(ch); // //輸出 // System.out.println((char)ch); // //讀一個字符 // ch = fr.read(); // } char cbuf [] = new char[1024];//讀一次int len = fr.read(cbuf);//將讀取的內容放入cbuf數組,返回的是真正讀取的字符個數while(len != -1){//寫一次//fw.write(cbuf);fw.write(cbuf, 0, len);//讀一次len = fr.read(cbuf); } //關閉輸入流和輸出流fr.close();fw.close();}}加上缺陷處理完整版:
/** * * 1.字節流可以讀寫任何文件(文本文件、二進制文件(音頻視頻圖片 chm)) * 字符流只可以讀寫文本文件(word不是文本文件) * 但是字符串處理非英文字符文本文件非常方便 * * 2.其實只有字節流,沒有字符流 * 字符流底層使用的還是字節流 * Java在字節流基礎上提供了字符流,給編程帶來便利 * * 3.字符流如何是英文字符還是中文字符 * 英文占一個字節,最高位是0 0111 0011 * 中文占兩個字節,最高位是1 1011 1011 1001 1101 * * 4.缺陷:沒有進行異常處理 * * * @author Administrator * */ public class TestCopy2 {public static void main(String[] args){Reader fr = null;Writer fw = null;try {//創建輸入流和輸出流fr = new FileReader(new File("e:/readme.txt"));fw = new FileWriter(new File("e:\\readme2.txt"));//默認是false 覆蓋char cbuf [] = new char[1024];//讀一次int len = fr.read(cbuf);//將讀取的內容放入cbuf數組,返回的是真正讀取的字符個數while(len != -1){//寫一次//fw.write(cbuf);fw.write(cbuf, 0, len);//讀一次len = fr.read(cbuf); }} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally{//關閉輸入流和輸出流try {if(fr != null){fr.close();} } catch (IOException e) {e.printStackTrace();}try {if(fw != null){fw.close();} } catch (IOException e) {e.printStackTrace();}}}}緩沖字節流BufferedInputStream和BufferedOuputStream
介紹
BufferedInputStream
字節緩沖輸入流,提高了讀取效率。
構造方法:// 創建一個 BufferedInputStream并保存其參數,即輸入流in,以便將來使用。BufferedInputStream(InputStream in)// 創建具有指定緩沖區大小的 BufferedInputStream并保存其參數,即輸入流in以便將來使用BufferedInputStream(InputStream in, int size).BufferedOutputStream
字節緩沖輸出流,提高了寫出效率。
構造方法:// 創建一個新的緩沖輸出流,以將數據寫入指定的底層輸出流BufferedOutputStream(OutputStream out)// 創建一個新的緩沖輸出流,以將具有指定緩沖區大小的數據寫入指定的底層輸出流BufferedOutputStream(OutputStream out, int size)常用方法:// 將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此緩沖的輸出流void write(byte[] b, int off, int len)// 將指定的字節寫入此緩沖的輸出流void write(int b)// 刷新此緩沖的輸出流void flush()文件復制
/** * 功能:文件復制 * 技能:BufferedInputStream和BufferedOuputStream * * * 1.節點流和處理流 * 節點流 FileInputStream FileOutputStream * 處理流 BufferedInputStream BufferedOutputStream * * 2.處理流的好處 * 好處1:提供了性能 * * * 3.如何創建處理流 * BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("e:/JDK_API_1_6_zh_CN.CHM")));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("e:\\JDK_API_1_6_zh_CN2.CHM")));* 4.關閉流:只要關閉高層流即可,底層流可以不關閉 * 關閉高層流的會關閉底層流 * * * 5.何時將輸出緩沖區的內容更新到文件中(刷新 flush) * * 1.緩沖區滿了,自動刷新 * 2.關閉輸出流時,會先刷新再關閉 * 3.不滿的時候也可以手動刷新 * bos.flush(); * * * public void close() throws IOException {try {flush();//刷新緩沖區} catch (IOException ignored) {}out.close(); //關閉底層流} * * @author Administrator * */ public class TestCopy1 {public static void main(String[] args) throws IOException {//創建一個輸入流和輸出流 // InputStream is = new FileInputStream(new File("e:/JDK_API_1_6_zh_CN.CHM")); // OutputStream os = new FileOutputStream(new File("e:\\JDK_API_1_6_zh_CN2.CHM")); // BufferedInputStream bis = new BufferedInputStream(is);//默認輸入緩沖區大小8192 // BufferedOutputStream bos = new BufferedOutputStream(os);//默認輸出緩沖區大小8192BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("e:/JDK_API_1_6_zh_CN.CHM")));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("e:\\JDK_API_1_6_zh_CN2.CHM")));//使用輸入流和輸出流完成文件復制int n;//中轉站,比較小(水杯)//讀一個字節n = bis.read();//從輸入流讀取一個字節的內容賦給nwhile(n != -1){//沒有到達末尾//寫一個字節bos.write(n);//讀一個字節n = bis.read();} //關閉輸入流和輸出流bis.close();bos.close();}}緩沖字符流BufferedReader和BufferedWriter
?
1).BufferedReader
BufferedReader:字符緩沖流,從字符輸入流中讀取文本,緩沖各個字符,從而實現字符、數組和行的高效讀取。
構造方法:// 創建一個使用默認大小輸入緩沖區的緩沖字符輸入流BufferedReader(Reader in)// 創建一個使用指定大小輸入緩沖區的緩沖字符輸入流BufferedReader(Reader in, int sz)特有方法:// 讀取一個文本行String readLine()2).BufferedWriter
BufferedWriter:字符緩沖流,將文本寫入字符輸出流,緩沖各個字符,從而提供單個字符、數組和字符串的高效寫入。
構造方法:// 創建一個使用默認大小輸出緩沖區的緩沖字符輸出流BufferedWriter(Writer out)// 創建一個使用給定大小輸出緩沖區的新緩沖字符輸出流BufferedWriter(Writer out, int sz)特有方法:// 寫入一個行分隔符void newLine()?
文件復制
/** * 按行讀取文件并復制 * * 只要文本文件才有行的概念 字符流 * 提高速度:緩沖流 * BufferedReader和BufferedWriter * * * * 1.處理流的好處 * 1.提高性能 * 2.簡化操作 * * 2.readLine的實現原理 * 底層還是按照字符一個個讀取, 由于采用了緩沖區,性能是提高 * 基本思路:* StringBuilder builder = new StringBuilder("");* ch = br.read();* while(讀取的這個字符是換行符的時候){* builder.append(ch);* ch = br.read();* }* return builder.toString(); * * 3.bw.newLine(); 不同的操作系統,換行符不同 * (1)在微軟的MS-DOS和Windows中,使用"回車CR('\r')"和"換行LF('\n')"兩個字符作為換行符;Windows系統里面,每行結尾是 回車+換行(CR+LF),即"\r\n";(2)Unix系統里,每行結尾只有 換行CR,即"\n";(3)Mac系統里,每行結尾是 回車CR 即'\r'。 * * * * @author Administrator * */ public class TestCopy2 {public static void main(String[] args) throws IOException {//創建輸入流和輸出流 // Reader fr = new FileReader(new File("e:/java基礎題目以及答案1.txt")); // BufferedReader br = new BufferedReader(fr); // Writer fw = new FileWriter(new File("e:/java基礎題目以及答案2.txt")); // BufferedWriter bw = new BufferedWriter(fw);BufferedReader br = new BufferedReader(new FileReader(new File("e:/java基礎題目以及答案1.txt")));BufferedWriter bw = new BufferedWriter(new FileWriter(new File("e:/java基礎題目以及答案2.txt")));//使用輸入流和輸出流//讀一行String str = br.readLine();while(str != null){//寫一行bw.write(str);bw.newLine();//換一行//讀一行str = br.readLine();} //關閉輸入流和輸出流 br.close();bw.close();}}字符轉換流
何時使用轉換流?
1.????當字節和字符之間有轉換動作時;
2.????流操作的數據需要編碼或解碼時。
?
1).InputStreamReader
InputStreamReader:字節流轉字符流,它使用的字符集可以由名稱指定或顯式給定,否則將接受平臺默認的字符集。
構造方法:// 創建一個使用默認字符集的 InputStreamReaderInputStreamReader(InputStream in)// 創建使用給定字符集的 InputStreamReaderInputStreamReader(InputStream in, Charset cs)// 創建使用給定字符集解碼器的 InputStreamReaderInputStreamReader(InputStream in, CharsetDecoder dec)// 創建使用指定字符集的 InputStreamReaderInputStreamReader(InputStream in, String charsetName)特有方法://返回此流使用的字符編碼的名稱 String getEncoding() /** * * * 功能:將從鍵盤輸入的一行行數據復制到另外一個文件中 * * 1.轉換流 * InputStreamReader 將InputStream轉換成Reader * OutputStreamWriter 將OutputStream轉換成Writer * ReaderInputStream 這個真沒有 * WriterOutputStream 這個也沒有 * * * 2.InputStreamReader到底是個InputStream還是一個Reader * Reader reader = new InputStreamReader(is); * * public class InputStreamReader extends Reader * * 3.轉換流使用了一個設計模式:適配器(轉換器)模式 * * 手機耳機口(大口)------------(大頭)轉換頭(小口)------ 耳機(小頭) * * Reader(readLine()) ------------ (Reader)轉換流InputStreamReader(InputStream) --------- InputStream(System.in) * * * * * @author Administrator * */ public class TestCopy1 {public static void main(String[] args) throws IOException {//創建輸入流和輸出流//Reader reader = new FileReader(new File("e:/java基礎題目以及答案1.txt")); // InputStream is = System.in; // Reader reader = new InputStreamReader(is); // BufferedReader br = new BufferedReader(reader);Scanner input = new Scanner(System.in);BufferedWriter bw = new BufferedWriter(new FileWriter(new File("e:/java.txt")));//使用輸入流和輸出流//讀一行// String str = br.readLine();String str = input.next();while(!"bye".equals(str)){ //"null"//寫一行bw.write(str);bw.newLine();//換一行//讀一行//str = br.readLine();str = input.next();} //關閉輸入流和輸出流 //br.close();input.close();bw.close();}}?
2).OutputStreamWriter
OutputStreamWriter:字節流轉字符流。
構造方法:// 創建使用默認字符編碼的 OutputStreamWriterOutputStreamWriter(OutputStream out)// 創建使用給定字符集的 OutputStreamWriterOutputStreamWriter(OutputStream out, Charset cs)// 創建使用給定字符集編碼器的 OutputStreamWriterOutputStreamWriter(OutputStream out, CharsetEncoder enc)// 創建使用指定字符集的 OutputStreamWriterOutputStreamWriter(OutputStream out, String charsetName)特有方法://返回此流使用的字符編碼的名稱 String getEncoding()(3).FileReader、FileWriter
FileReader:InputStreamReader類的直接子類,用來讀取字符文件的便捷類,使用默認字符編碼。FileWriter:OutputStreamWriter類的直接子類,用來寫入字符文件的便捷類,使用默認字符編碼。?性能測試和調優
之前說帶緩沖區會快很多,到底是不是這樣呢?
我們復制一個MP4文件來測試一下
不帶緩沖的用例兩秒,這對于一個IO操作來說顯然太長了。
我們用帶緩沖區的試一下:
可以看到,讀取次數一樣,時間少了很多。
但是,讀取次數還是太多了,我們可以通過擴大byte數組的方式來減少讀寫次數。
很明顯,速度進一步加快。
但是請注意:也不是數組越大越好,視情況而定。
我們確定了數組大小之后,我們還可以設置緩沖區的大小進一步優化時間。
因為我們是從緩沖區讀數據,緩沖區從硬盤讀數據,形成這個體系可以加快我們的速度。
實際中可以多次調整嘗試,確定最優的方案
System類對IO的支持
?針對一些頻繁的設備交互,Java語言系統預定了3個可以直接使用的流對象,分別是:
·????????System.in(標準輸入),通常代表鍵盤輸入。
·????????System.out(標準輸出):通常寫往顯示器。
·????????System.err(標準錯誤輸出):通常寫往顯示器。
PrintStream
/** * * System.out 是PrintStream類的一個實例 * public final static PrintStream out = null; * Student stu = null; * * PrintStream 輸出流 字節流 處理流 * 打印流只有輸出流,沒有輸入流 * * * PrintStream類的方法println() 這個方法功能簡直太強大了!!! * 可以直接講各種數據類型(基本數據類型、引用數據類型)直接寫入到文件中,并且換行。太方便了,太強大了!! * 不管什么類型,寫入到文件中全部變成字符串 * 缺點1: 123#3.14#true#bjsxt 需要使用特殊的字符來區分各個內容,防止混淆 * 缺點2: 123#3.14#true======="123" "3.14" "true" 讀出來之后都是字符串,還需要將字符串轉換成真實類型 * * DataInputStream和DataOutputStream * * @author Administrator * */ public class TestPrintStream {public static void main(String[] args) throws FileNotFoundException {//PrintStream ps = System.out;PrintStream ps = new PrintStream(new FileOutputStream(new File("e:/bjsxt.txt")));ps.println(123);ps.println('A');ps.println(3.14);ps.println(true);ps.println("bjsxt");ps.println(new Date().toString());OutputStream os =new FileOutputStream(new File("e:/bjsxt.txt"));// os.write(一個字節); // String datestr = new Date().toString();; // byte [] buf = datestr.getBytes(); // os.write(buf); // BufferedWriter bw; // bw.newLine();ps.close();}public void method1(){PrintStream ps = System.out;ps.println(123);ps.println('A');ps.println(3.14);ps.println(true);ps.println("111");ps.println(new Date().toString());// System.out.println(123); // System.out.println('A'); // System.out.println(3.14); // System.out.println(true); // System.out.println("111"); // System.out.println(new Date().toString());}}PrintWriter
/** * * 裝飾模式 * * this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),false); * * 減少了子類的數量,是繼承的一種替代方案 * * @author Administrator * */ public class TestPrintWriter {public static void main(String[] args) throws IOException {PrintWriter pw1 = new PrintWriter(new FileWriter("e:/bjsxt.txt"));PrintWriter pw2 = new PrintWriter(new FileOutputStream("e:/bjsxt.txt"));PrintWriter pw3 = new PrintWriter(new File("e:/bjsxt.txt"));PrintWriter pw = new PrintWriter("e:/bjsxt.txt");pw.println(123);pw.println('A');pw.println(3.14);pw.println(true);pw.println("1111t");pw.println(new Date().toString());pw.close();}}ACM IO 快速讀寫
輸出
第一種使用傳統的System.out.println()方式輸出。
public class Main {public static void main(String[] args) {long start = System.currentTimeMillis();for(int i=0;i<100000;i++)System.out.println(i);long end = System.currentTimeMillis();System.out.println("time="+(end-start)+"ms");} }
time=3443ms
顯然在ACM中會超時
第二種使用PrintWriter輸出:
public class Main {public static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));public static void main(String[] args) {long start = System.currentTimeMillis();for(int i=0;i<100000;i++)out.println(i);out.flush();long end = System.currentTimeMillis();System.out.println("time="+(end-start)+"ms");out.close();} }
結果:
time=328ms
雖然每次輸出的結果會有大致幾十毫秒的偏差,但總體上來看,PrintWriter輸出要比用System.out.println()輸出快上10倍左右。這個結果就比較讓人滿意了。
輸入
Scanner類讀取文件(in.txt,里面有從一到一百萬的的整數)
public class Main {public static void main(String[] args) throws IOException{Scanner sc = new Scanner(new FileInputStream("in.txt"));long start = System.currentTimeMillis();for(int i=1;i<=1000000;i++)sc.nextInt();long end = System.currentTimeMillis();System.out.println("time="+(end-start)+"ms");} }
運行結果:
time=2930ms ??
大概3秒,實際上如果ACM中真有一百萬的數據,若用Scanner讀取,還沒開始計算,就已經超時了。
用StreamTokenizer讀取
public class Main {public static StreamTokenizer in;static {try{in = new StreamTokenizer(new BufferedReader(new InputStreamReader(new FileInputStream("in.txt"))));}catch (Exception e){e.printStackTrace();}}public static int nextInt() throws IOException{ in.nextToken(); return (int)in.nval; }public static void main(String[] args) throws IOException{long start = System.currentTimeMillis();for(int i=1;i<=1000000;i++)nextInt();?? ?//這里僅讀取,不輸出long end = System.currentTimeMillis();System.out.println("time="+(end-start)+"ms");} }運行結果:
time=397ms
要注意的是,用StreamTokenizer讀取字符串時,只能讀取純字母字符串,如果包含數字或者其他字符會返回null。這是用StreamTokenizer讀取的缺點。但是用它讀取數字時沒有問題的。
總結一下:
如果數據量比較小,用Scanner是比較方便的
如果數據量很大的話,那么用StreamTokenizer 是一個很好的選擇
最后是模板:
import java.io.*;public class Main {public static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in),32768));public static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));public static double nextDouble() throws IOException{ in.nextToken(); return in.nval; }public static float nextFloat() throws IOException{ in.nextToken(); return (float)in.nval; }public static int nextInt() throws IOException{ in.nextToken(); return (int)in.nval; }public static String next() throws IOException{ in.nextToken(); return in.sval;}public static void main(String[] args) throws IOException{ //?? ??? ?獲取輸入while(in.nextToken()!=StreamTokenizer.TT_EOF){break;}int x = (int)in.nextToken(); ?//第一個數據應當通過nextToken()獲取int y = nextInt();float f = nextFloat();double d = nextDouble();String str = next();//?? ??? ?輸出out.println("abc");out.flush();out.close();} }至此,Java的IO總結完啦
總結
- 上一篇: string相关库函数
- 下一篇: 终于,我读懂了所有Java集合——set