IO流分類:
(1):按照流向可以分爲:輸入流:讀取數據;
輸出流:寫出數據;
(2):按照數據類型:
字節流
字節輸入流:讀取數據 InputStream 需要有文件。
字節輸出流:寫出數據 OutputStream 不需要自己再創建文件
字符流
字符輸入流:讀取數據 Reader
字符輸出流:寫出數據 Writer
字符流是在字節流之後纔出現的。
字節流輸出:
構造方法:
FileOutputStream(File file)
FileOutputStream(String name)
通過查API可知public abstract class OutputStream extends Object implements Closeable, Flushable{}OutputStream實爲抽象類。因此需要創建對象時,要麼使用多態,要麼通過其子類創建對象。
OutputStream寫出常用操作:
public void write(int a);
public void write(byte [] b);
public void write(byte[] b,int off,int len);
寫出數據案例:
第一種方法:
import java.io.FileOutputStream;
import java.io.IOException;
public class WriterDemo{
public static void main(String [] args)throws IOException{
FileOutputStream fos=new FileOutputStream("e:\\it.txt");
//將字符串轉爲字節數組。
fos.write("我愛黑馬".getBytes());
fos.close();
}
}
第二種方法:
import java.io.FileOutputStream;
import java.io.IOException;
public class WriterDemo{
public static void main(String [] args)throws IOException{
FileOutputStream fos=new FileOutputStream("e:\\it.txt");
fos.write(97);//寫入a;
fos.close();
}
}
第三種方法:
import java.io.FileOutputStream;
import java.io.IOException;
public class WriterDemo{
public static void main(String [] args)throws IOException{
FileOutputStream fos=new FileOutputStream("e:\\it.txt");
byte [] by={97,98,99,100,101};
fos.write(by,1,2);//輸出bc
fos.close();
}
}
創建字節輸出流,對象做了三件事:
1、調用系統功能創建文件。
2、創建fos對象。
3、將fos對象指向這個文件。
爲什麼一定要加close?
1、讓流對象關閉。讓流對象變成垃圾,這樣就可以被垃圾回收器回收了。
2、通知系統釋放與該文件相關的資源。
換行符:
windows:\r\n
linux:\n
Mac:\r
追加寫入:用構造方法帶第二個參數是true的情況即可。
字節流中處理異常:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Copy{
public static void main(String[] args) {
FileOutputStream fos= null;
try{
fos=new FileOutputStream("e:\\it.txt");
fos.write("java".getBytes());
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}finally{
if(fos!=null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
讀取數據:InputStream:抽象類。
int read();一次讀取一個字節;返回的是int值,需要我們用char轉爲字符。
int read(byte [] b);一次讀取一個字節數組
一次讀取一個字節讀取數據:
import java.io.FileInputStream;
import java.io.IOException;
public class ReaderDemo{
public static void main(String [] args)throws IOException{
FileInputStream fis=new FileOutputStream("e:\\it.txt");
int by=0;
//讀取完成,返回的是-1;
while((by=fis.read())!=-1){
//char強制轉換,將讀取的值轉變爲字符。如果此時我們輸出的是fos.read()的話,它就會像迭代器中的it.next()一樣,會出現跳躍輸出。因爲fos.read()已經在while循環的條件控制中已經出現了,如果在輸出中繼續出現,實際就是輸出下一個了。
System.out.print((char)by);
}
fis.close();
}
}
注意:上面的例子我們可以看到,當一個字節,一個字節讀取的時候,中文字符會被解析爲亂碼。這是因爲中文字符實爲兩個字節,不能拆開。之所以是-1;是因爲JDK中,當文件讀完時,會返回-1.由於讀取的是字節,在控制檯顯示的是二進制轉化爲十進制後的數字,因此要用char強制轉換成字符。
計算機如何讀取中文。
這是由於中文的一個字符,分爲兩個字節,每個字節都是負數。這兩個負數都是在0到-128之間,因此可以使用byte數組。128*128等於16384,所以漢字常用字符夠用。
一次讀取一個字節來複制文件:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyDemo{
public static void main(String [] args)throws IOException{
//複製到e盤的it.txt文件
FileOutputStream fos=new FileOutputStream("e:\\it.txt");
//創建對象,讀取D盤中的it.txt文件。
FileInputStream fis=new FileInputStream("d:\\it.txt");
int by=0;
while((by=fis.read())!=-1){
fos.write(by);
}
fos.close();
fis.close();
}
}
注意:通過字節讀取寫出,不僅可以賦值txt文檔,還可以賦值jpg,map4等多種文件。只需要將文件名換一下就可以了。
一次讀取一個字節數組:
import java.io.FileInputStream;
import java.io.IOException;
public class ReadDemo{
public static void main(String [] args)throws IOException{
FileInputStream fos=new FileInputStream("e:\\it.txt");
byte [] by=new byte[1024];
int len=0;
//fis.read(by)將會返回實際讀取到的字節個數。
while((len=fis.read(by))!=-1){
System.out.print(new String(by,0,len));
}
fis.close();
}
}
注意:通過一次讀取一個字節數組的長度來讀取文件,這裏的字節數組的長度需要自己規定。每次讀取文件的時候,都會讀取規定長度個字節,其中包括\r、\n這樣的轉義字符。因此當規定長度小於文件字節長度時,最後一次讀取到的字節,就無法覆蓋完上一次讀取的長度的個元素,因此就會多出一些上一次讀取最後多餘的元素。
一次讀取一個字節數組來複制文件:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyDemo{
public static void main(String [] args)throws IOException{
<span style="white-space:pre"> </span>//複製到e盤的it.txt文件
<span style="white-space:pre"> </span>FileOutputStream fos=new FileOutputStream("e:\\it.txt");
<span style="white-space:pre"> </span>//創建對象,讀取D盤中的it.txt文件。
<span style="white-space:pre"> </span>FileInputStream fis=new FileInputStream("d:\\it.txt");
<span style="white-space:pre"> </span>byte [] by=new byte[1024];
<span style="white-space:pre"> </span>int len =0;
<span style="white-space:pre"> </span>while((len=fis.read(by))!=-1){
<span style="white-space:pre"> </span>fos.write(by,0,len);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>fos.close();
<span style="white-space:pre"> </span>fis.close();
<span style="white-space:pre"> </span>}
}
緩衝區類:
寫數據:BufferedOutputStream
讀數據:BufferedInputStream
字節緩衝區流,僅僅提供緩衝區,其是爲高效而設計的。真正的讀寫操作還得靠基本的流對象實現。
構造方法可以指定緩衝區大小,但是默認緩衝區就夠用了。
寫出案例:
import java.io.IOException;
import java.io.FileOutputStream;
class BufferedOutputStreamDemo{
public static void main(String [] args)throws IOException{
FileOutputStream fos=new FileOutputStream("e:\\it.txt");
BufferedOutputStream bos=new BufferedOutputStream(fos);
bos.write("hello".getBytes());
bos.close();
}
}
讀取案例:
import java.io.IOException;
import java.io.FileInputStream;
class BufferedInputStreamDemo{
public static void main(String [] args)throws IOException{
FileInputStream fis=new FileInputStream("e:\\it.txt");
BufferedInputStream bis=new BufferedInputStream(fis);
int by=0;
while((by=bis.read()!=-1){
System.out.print((char)by);
}
bis.close();
}
}