非流式文件類--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();//從輸入流讀取一個字節的內容賦給n
while(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);//寫1024
fos.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)
// 將指定字符添加到此 writer
Writer append(char c)
// 將指定字符序列添加到此 writer
Writer append(CharSequence csq)
// 將指定字符序列的子序列添加到此 writer.Appendable
Writer 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);//默認輸出緩衝區大小8192
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")));
//使用輸入流和輸出流完成文件複製
int n;//中轉站,比較小(水杯)
//讀一個字節
n = bis.read();//從輸入流讀取一個字節的內容賦給n
while(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:字節流轉字符流,它使用的字符集可以由名稱指定或顯式給定,否則將接受平臺默認的字符集。
構造方法:
// 創建一個使用默認字符集的 InputStreamReader
InputStreamReader(InputStream in)
// 創建使用給定字符集的 InputStreamReader
InputStreamReader(InputStream in, Charset cs)
// 創建使用給定字符集解碼器的 InputStreamReader
InputStreamReader(InputStream in, CharsetDecoder dec)
// 創建使用指定字符集的 InputStreamReader
InputStreamReader(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:字節流轉字符流。
構造方法:
// 創建使用默認字符編碼的 OutputStreamWriter
OutputStreamWriter(OutputStream out)
// 創建使用給定字符集的 OutputStreamWriter
OutputStreamWriter(OutputStream out, Charset cs)
// 創建使用給定字符集編碼器的 OutputStreamWriter
OutputStreamWriter(OutputStream out, CharsetEncoder enc)
// 創建使用指定字符集的 OutputStreamWriter
OutputStreamWriter(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總結完啦