流
在程序中所有的數據都是以流的方式進行傳輸或保存的,程序需要數據的時候要使用輸入流讀取數據,而當程序需要將一些數據保存起來的時候,就要使用輸出流完成。
程序中的輸入輸出都是以流的形式保存的,流中保存的實際上全都是字節文件。
在java.io包中操作文件內容的主要有兩大類:字節流、字符流、兩類都分爲輸入和輸出操作。在字節流中輸出數據主要是要使用OutputStream完成,輸入使用InputStream,在字符流中輸出主要是使用Writer類完成,輸入主要使用Reader類完成。
內容操作就四個類:OutputStream、InputStream、Writer、Reader
操作流程
在JAVA中IO操作也是有相應步驟的,以文件操作爲例,主要的操作流程如下:
A、 使用File類打開一個文件
B、 通過字節流或字符流的子類,指定輸出的位置
C、 進行讀/寫操作
D、 關閉輸入/輸出
使用File類操作的時候一定要有路徑的問題,注意分隔符。
實際上四個操作類都是抽象類
IO操作屬於資源操作,對於資源操作,操作的最後必須關閉,否則就有可能出現未知的 錯誤。
1、字節流OutputStream/InputStream
public class Main01 {
public static void main(String[] args) {
File file = new File("src//JavaIO/test.txt");
try {
//OutputStream out = new FileOutputStream(file);
OutputStream out = new FileOutputStream(file,true);//追加方式打開文件
String str = "\nhello word kkk!";//字符串中添加換行
byte b[] = str.getBytes();
out.write(b);
out.close();
InputStream input = new FileInputStream(file);
//byte b2[] = new byte[1024];第一種方式定義接收文件內容的二進制變量,固定值造成浪費。
byte b2[] = new byte[(int)file.length()];//第二種根據file長度定義二進制變量大小。
//第一種讀取文件內容的方式:input。read(b2);
//int len = input.read(b2);//不計算len,輸出的內容就是定義的1024,太長了
//第二種讀取方式
/*for(int i=0;i<b2.length;i++){
b2[i]=(byte)input.read();
}*/
//第三種讀取方式
int temp = 0;
int len = 0 ;
while((temp=input.read())!=-1){
b2[len++]=(byte)temp;
}
input.close();
//System.out.print("文件內容:"+new String(b2,0,len));
System.out.print("文件內容:"+new String(b2));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2、字符流(Reader/Writer)
在程序中一個字符等於2個字節,那麼JAVA提供了Reader、Writer連個專門操作字符流的類。
字符輸出流:Writer
字符輸入流:Reader
Writer本身只是一字符流的輸出類,此類的定義如下:
public abstract class Writer extends Object implements Appendable, Closeable,Flushable
此類本身也是一個抽象類,如果要想使用此類,則肯定要使用其子類,此時如果是向文件中寫入內容,所以應該使用FileWriter的子類。
FileWriter類的構造方法定義如下:
public FileWriter (File file) throws IOException
Writer類的常用方法
No. |
方法或常量 |
類型 |
描述 |
1 |
public abstract void close () throws IOException |
普通 |
關閉輸出流 |
2 |
public void write (String str) throws IOException |
普通 |
將字符串輸出 |
3 |
public void write (char [] cbuf) throws IOException |
普通 |
將字符數組輸出 |
4 |
public abstract void flush () throws IOException |
普通 |
強制清空緩存 |
字符流的操作比字節流操作好在一點,可以直接輸出字符串,不用進行轉換操作。
String str ="hello world!!!"; byteb[] =str.getBytes(); out.write(b); |
String str ="Hello World!!!"; out.write(str);
|
字符輸入流:Reader
Reader是使用使用字符的方式從文件中取出數據,Reader類的定義如下:
public abstract class Readerextends Object implements Readable, Closeable
Reader本身也是抽象類,如果現在要從文件中讀取內容,則可以直接使用FileReader子類。
FileReader的構造方法定義如下:
public FileReader (File file)throws FileNotFoudException
Reader類的常用方法
No. |
方法或常量 |
類型 |
描述 |
1 |
public abstract void close () throws IOException |
普通 |
關閉輸出流 |
2 |
public int read () throws IOException |
普通 |
讀取單個字符 |
3 |
public int read (char [] cbuf) throws IOException |
普通 |
讀到字符數組中,返回長度 |
public class Main02 {
public static void main(String[] args) {
File file = new File("src//JavaIO//test.txt");
try {
//Reader reader = new FileReader(file);
//使用字符字節流轉換
Reader reader = new InputStreamReader(new FileInputStream(file));
char[] ch = new char[(int)file.length()];
//讀取也是三種方式
reader.read(ch);
/*int len = 0;
int temp = 0;
while((temp=reader.read())!=-1){
ch[len++]=(char)temp;
}*/
reader.close();
System.out.println("Main02文件讀取:"+new String(ch));
String str = "what can I do for you?";
//Writer writer = new FileWriter(file,true);//寫入文件
Writer writer = new OutputStreamWriter(new FileOutputStream(file,true));
writer.write(str);
writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
字節流與字符流的區別是字節流在操作的時候本身是不會用到緩衝區(內存)的,是與文件本身直接操作的,而字符流在操作的時候是使用到緩衝區的。
注意:在所有的硬盤上保存文件或是進行傳輸的時候都是以字節的方式進行的。包括圖片也是按字節完成,而字符只是在內存中才會形成,所以使用字節的操作最多。
3、內存操作流
public class Main03 {
public static void main(String[] args){
String str = "HELLO WORD";
ByteArrayInputStream bais = new ByteArrayInputStream(str.getBytes());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int temp = 0;
while((temp=bais.read())!=-1){
baos.write(Character.toLowerCase((char)temp));
}
System.out.println(baos.toString());
try {
bais.close();
baos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
4、管道流
class Send implements Runnable{//線程類
private PipedOutputStream pos = null;//管道輸出流
public Send(){
this.pos = new PipedOutputStream();//實例化輸出流
}
@Override
public void run() {
// TODO Auto-generated method stub
String str = "hello word!!!!";
try {
this.pos.write(str.getBytes());
this.pos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public PipedOutputStream getPos(){
return this.pos;
}
}
class Receive implements Runnable{
private PipedInputStream pis = null;
public Receive(){
this.pis = new PipedInputStream();
}
@Override
public void run() {
// TODO Auto-generated method stub
byte b[] = new byte[1024];//接收內容
int len = 0;
try {
len = this.pis.read(b);
this.pis.close();
System.out.println(new String(b,0,len));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public PipedInputStream getPis(){
return this.pis;
}
}
public class Main04 {
public static void main(String args[]){
Send s = new Send();
Receive r = new Receive();
try {
s.getPos().connect(r.getPis());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new Thread(s).start();
new Thread(r).start();
}
}