java io 输出流_Java IO 输入和输出流
數(shù)據(jù)流是指一組有順序的,有起點(diǎn)和終點(diǎn)的字節(jié)集合。
最初的版本中,java.io 包中的流只有普通的字節(jié)流,即以 byte 為基本處理單位的流。字節(jié)流用來讀寫 8 位的數(shù)據(jù),由于不會(huì)對(duì)數(shù)據(jù)做任何轉(zhuǎn)換,因此可以用來處理二進(jìn)制的數(shù)據(jù)。在后來的版本中,java.io 包中又加入了專門用于字符流處理的類,這個(gè)以 Reader 和 Writer 為基礎(chǔ)派生的一系列的類。
另外,為了使對(duì)象的狀態(tài)能夠方便地永久保存下來,java.io 包中又提供了以字節(jié)流為基礎(chǔ)的用于對(duì)象的永久化保存狀態(tài)的機(jī)制,通過實(shí)現(xiàn) ObjectInput 和 ObjectOutput 接口來完成。
InputStream 和 OutputStream 兩個(gè)類都是抽象類,抽象類不能進(jìn)行實(shí)例化。在實(shí)際應(yīng)用中我們要用到一系列基本數(shù)據(jù)流類,都是他們的子類,在實(shí)現(xiàn)其父類方法的同時(shí)又都定義了其特有的功能。
輸入數(shù)據(jù)流
輸入數(shù)據(jù)流中提供的主要數(shù)據(jù)操作方法
int read():從輸入流中讀取一個(gè)字節(jié)的二進(jìn)制數(shù)據(jù)
int read(byte[] b):將多個(gè)字節(jié)讀到數(shù)組中,填滿整個(gè)數(shù)組
int read(byte[] b, int off, int len):從輸入流中讀取長(zhǎng)度為len的數(shù)據(jù),從數(shù)組 b 中下標(biāo)為 off 的位置開始放置讀入的數(shù)據(jù),讀畢返回讀取的字節(jié)數(shù)
以上三個(gè)方法中,所讀取的數(shù)據(jù)都默認(rèn)為字節(jié)類型。當(dāng)輸入流讀取結(jié)束時(shí),會(huì)得到 -1,以標(biāo)志數(shù)據(jù)流的結(jié)束。第一個(gè) read() 方法將讀取的一個(gè)字節(jié)作為低位,形成一個(gè) 0~255 的 int 類型的數(shù)值返回
void close():關(guān)閉數(shù)據(jù)流
long skip(long l):跳過數(shù)據(jù)流中指定數(shù)量的字節(jié)不讀取,返回值表示實(shí)際跳過的字節(jié)數(shù)
對(duì)于數(shù)據(jù)流中的字節(jié)的讀取通常是按從頭到尾順序進(jìn)行的,如果需要以反方向讀取,則需要使用回推(Push Back)操作,支持回推操作的數(shù)據(jù)流中常用的方法如下
boolean markSupported():用于測(cè)試數(shù)據(jù)流是否支持回推操作,當(dāng)一個(gè)數(shù)據(jù)流支持 mark() 和 reset() 方法時(shí)返回 true,否則返回 false
void mark(int markarea):用于標(biāo)記數(shù)據(jù)流的當(dāng)前位置,并劃出一個(gè)緩沖區(qū),其大小至少為指定參數(shù)的大小
void reset():將輸入流重新定位到對(duì)此流最后調(diào)用 mark 方法時(shí)的位置
輸出數(shù)據(jù)流
輸出數(shù)據(jù)流中提供的主要數(shù)據(jù)操作方法
void write(int i):將字節(jié) i 寫入到數(shù)據(jù)流中,它只輸出所讀入?yún)?shù)的最低 8 位
void write(byte b[]):將數(shù)組 b[] 中的全部 b.length 個(gè)字節(jié)寫入數(shù)據(jù)流
void write(byte b[], int off, int len):將數(shù)組 b[] 中從下標(biāo) off 開始的 len 個(gè)字節(jié)寫入數(shù)據(jù)流。元素 b[off] 是此操作寫入的第一個(gè)字節(jié), b[off + len - 1] 是此操作寫入的最后一個(gè)字節(jié)
void close():當(dāng)結(jié)束對(duì)輸出數(shù)據(jù)流的操作時(shí)應(yīng)該將其關(guān)閉
void flush():刷新此輸出流并強(qiáng)制寫出所有緩沖的輸出字節(jié)
基本字節(jié)數(shù)據(jù)流類
文件數(shù)據(jù)流
文件數(shù)據(jù)流包括 FileInputStream 和 FileOutputStream,這兩個(gè)類用來進(jìn)行文件的I/O處理,其數(shù)據(jù)源或數(shù)據(jù)終點(diǎn)都應(yīng)當(dāng)是文件。通過所提供的方法可以對(duì)本機(jī)上的文件進(jìn)行操作,但是不支持方法 mark() 和 reset()
示例(1)
FileInputStream fis = new FileInputStream("myFile.txt");//同樣可以使用 FileOutputStream 向文件中輸出字節(jié)
FIleOutputStream out = new FileOutputStream("myFile.txt");
示例(2)
FIleOutputStream out = new FileOutputStream("myFile.txt");
out.wirte('H');
out.wirte(69);
out.wirte(76);
out.wirte('L');
out.wirte('O');
out.close();
FIleInputStream fis = new FileInputStream("myFile.txt");
while(fis.available() > 0){
System.out.print(fis.read()+ " ");
}
fis.close();
過濾器數(shù)據(jù)流(直接繼承與FilterInputStream、FilterOutputStream)
緩沖區(qū)數(shù)據(jù)流
一個(gè)過濾器數(shù)據(jù)流在創(chuàng)建時(shí)與一個(gè)已經(jīng)存在的數(shù)據(jù)流相連,這樣在從這樣的數(shù)據(jù)流中讀取數(shù)據(jù)時(shí),它提供的是對(duì)一個(gè)原始輸入數(shù)據(jù)流的內(nèi)容進(jìn)行了特定處理的數(shù)據(jù)。緩沖區(qū)數(shù)據(jù)流有BufferedInputStream 和 BufferedOutinputStream,它們是在數(shù)據(jù)流上增加了一個(gè)緩沖區(qū),都屬于過濾器數(shù)據(jù)流。當(dāng)讀寫數(shù)據(jù)時(shí),數(shù)據(jù)以塊為單位先進(jìn)入緩沖區(qū)(塊大小可以進(jìn)行設(shè)置),其后的讀寫操作則作用于緩沖區(qū)。采用這個(gè)辦法可以降低不同硬件設(shè)備之間速度的差異,提高I/O操作的效率
示例(使用默認(rèn)緩沖區(qū)大小)
FileInputStream fis = new FileInputStream("myFile.txt");
InputStream is = newBufferedInputStream(fis);
FileOutputStream fos= new FileOutputStream("myFile.txt");
OutputStream is = new BufferedOutputStream(fos);
示例(自定義設(shè)置緩沖區(qū)大小)
FileInputStream fis = new FileInputStream("myFile.txt");
InputStream is = new BufferedInputStream(fis, 1024);
FileOutputStream fos= new FileOutputStream("myFile.txt");
OutputStream is = new BufferedOutputStream(fos, 1024);
一般在關(guān)閉一個(gè)緩沖區(qū)輸出流之前,應(yīng)先使用 flush() 方法,強(qiáng)制輸出剩余數(shù)據(jù),以確保緩沖區(qū)內(nèi)的所有數(shù)據(jù)全部寫入輸出流
數(shù)據(jù)數(shù)據(jù)流
前面提到的數(shù)據(jù)流中處理數(shù)據(jù)都是指字節(jié)或字節(jié)數(shù)組,這是進(jìn)行數(shù)據(jù)傳輸時(shí)系統(tǒng)默認(rèn)的數(shù)據(jù)類型。但實(shí)際上所處理的數(shù)據(jù)并非只有這兩種類型,遇到這種情況時(shí)就要應(yīng)用一種專門的數(shù)據(jù)流來處理。DataInputStream 和 DataOutputStream 就是這樣的兩個(gè)過濾器數(shù)據(jù)流,它們?cè)试S通過數(shù)據(jù)流來讀寫 Java 基本類型
示例
DataInputStream dis = newDataInputStream(is);
DataOutputStream ous= new DataOutputStream(os);
常用方法
//DataInputStream 常用方法
bytereadByte()longreadLong()
doublue readDouble()booleanreadBoolean()
String readUTF()intreadInt()floatreadFloat()shortreadShort()charreadChar()//DataOutputStream 常用方法
void writeByte(intaByte)void writeLong(longaLong)void writeDouble(doubleaBouble)void writeBoolean(booleanaBool)voidwriteUTF(String aString)void writeInt(intaInt)void writeFloat(floataFloat)void writeShort(shortaShort)void rwriteChar(char aChar)
雖然這兩個(gè)數(shù)據(jù)流定義了對(duì)字符串進(jìn)行讀寫的方法,但是由于字符編碼的原因,應(yīng)該避免使用這些方法。Reader 和 Writer 重載了這兩個(gè)方法,對(duì)字符進(jìn)行操作時(shí)應(yīng)當(dāng)使用 Reader 和 Writer 兩個(gè)系列類中的方法
對(duì)象流
能夠輸入/輸出對(duì)象的流稱為對(duì)象流。Java 通過 java.io 包中的 ObjectInputStream 和 ObjectOutputStream 兩個(gè)類實(shí)現(xiàn)把對(duì)象寫入文件數(shù)據(jù)流或從文件數(shù)據(jù)流中讀出的功能
示例
//寫對(duì)象數(shù)據(jù)流
Date date= newDate();
FileOutputStream fos= new FileOutputStream("date.ser");
ObjectOutputStream oos = newObjectOutputStream(fos);
oos.writeObject(date);
oos.close();//讀對(duì)象數(shù)據(jù)流
Date date= null;
FileInputStream fis= new FileInputStream("date.ser");
ObjectInputStream ois = newObjectInputStream(fis);
date=(Date) ois.readObject(date);
ois.close();
System.out.println("Date serialized at " + date);
序列化
序列化的概念
能夠記錄自己的狀態(tài)以便將來得到復(fù)原的能力,稱為對(duì)象的持久性(Persistence)。一個(gè)對(duì)象時(shí)可持久的,意味著它可以把這個(gè)對(duì)象存入內(nèi)存或者磁盤等介質(zhì)中,也就是把對(duì)象存為某種永久存儲(chǔ)類型。對(duì)象通過數(shù)值來描述自己的狀態(tài),記錄對(duì)象也就是記錄下這些數(shù)值。把對(duì)象轉(zhuǎn)換為字節(jié)序列的過程稱為對(duì)象的序列化,把字節(jié)序列恢復(fù)為對(duì)象的過程稱為對(duì)象的反序列化。序列化的主要任務(wù)是寫出對(duì)象實(shí)例變量的數(shù)值。序列化是一種用來處理對(duì)象流的機(jī)制,所謂的對(duì)象流也就是將對(duì)象的內(nèi)容進(jìn)行流化。序列化是為了解決在對(duì)對(duì)象流進(jìn)行讀寫操作時(shí)所引發(fā)的問題
Serializable 接口中沒有定義任何方法,只是作為一個(gè)標(biāo)記來指示實(shí)現(xiàn)該接口的類可以進(jìn)行序列化,只有實(shí)現(xiàn) Serializable 接口的類才能被序列化。當(dāng)一個(gè)類實(shí)現(xiàn) Serializable 接口時(shí),表明該類加入了對(duì)象序列化協(xié)議
序列化一個(gè)對(duì)象,必須與特定的對(duì)象輸出/輸入流聯(lián)系起來,通過對(duì)象輸出流/輸入流將對(duì)象狀態(tài)保存下來或者將對(duì)象狀態(tài)恢復(fù)。通過 java.io 包中的 ObjectInputStream 和 ObjectOutputStream 兩個(gè)類可以實(shí)現(xiàn)。writeObject() 和 readObject() 方法可以直接將對(duì)象保存到輸出流中或者從輸出流中讀取一個(gè)對(duì)象
//序列化
public class Student implementsSerializable {intid;
String name;intage;
String department;public Student(int id, String name, intage, String department) {this.id =id;this.name =name;this.age =age;this.department =department;
}
}//對(duì)象的存儲(chǔ)
Student stu= new Student(927103, "Li Ming", 16, "CSD");
FileOutputStream fo= new FileOutputStream("data.ser");
ObjectOutputStream so = newObjectOutputStream(fo);
so.writeObject(stu);
so.close();//對(duì)象的恢復(fù)
Student stu;
FileInputStream fi= new FileInputStream("data.ser");
ObjectInputStream si = newObjectInputStream(fi);
stu=(Student)si.readObject();
si.close();
System.out.println("ID:" + stu.id + ";name:" + stu.name);
對(duì)象結(jié)構(gòu)表
序列化只能保存對(duì)象的非靜態(tài)成員變量,而不能保存任何成員方法和靜態(tài)成員變量,并且保存的只是變量的值,對(duì)于變量的任何修飾符都不能保存,訪問權(quán)限(public, protected, private)對(duì)于數(shù)據(jù)域的序列化沒有影響
有一些對(duì)象不具有可持久性,因?yàn)槠鋽?shù)據(jù)的特性決定了它會(huì)經(jīng)常變化,其狀態(tài)只是瞬時(shí)的,這樣的對(duì)象是無法保存起狀態(tài)的,如 Thread 對(duì)象。對(duì)于這樣的成員變量,必須用 transient 關(guān)鍵字標(biāo)明,否則編譯器將報(bào)錯(cuò)。任何用 transient 關(guān)鍵字標(biāo)明的成員變量都不會(huì)被保存
序列化可能涉及將對(duì)象存放到磁盤上或者再網(wǎng)絡(luò)上發(fā)送數(shù)據(jù),這時(shí)會(huì)產(chǎn)生安全問題。對(duì)于一些保密的數(shù)據(jù),為了保證安全,不應(yīng)保存在永久介質(zhì)中,應(yīng)在這些變量前加上?transient 關(guān)鍵字
當(dāng)數(shù)據(jù)變量是一個(gè)對(duì)象時(shí),該對(duì)象的數(shù)據(jù)成員也可以被持久化。對(duì)象的數(shù)據(jù)結(jié)構(gòu)或結(jié)構(gòu)樹,包括其子對(duì)象樹在內(nèi),構(gòu)成了這個(gè)對(duì)象的結(jié)構(gòu)表
示例
public class Student implementsSerializable {public transientThread myThread;private transientString customerID;private inttotal;
}
基本字符流
從 JDK1.1 開始,java.io 包中加入了專門用于字符流處理的類,它們是以 Reader 和 Writer 為基礎(chǔ)派生的一系列類。
一、讀者(Reader)和寫者(Writer)
同其他語言使用 ASCII 字符集不同,Java 使用 Unicode 字符集來表示和字符。ASCII 字符集以一個(gè)字節(jié)(8bit)表示一個(gè)字符,可以認(rèn)為一個(gè)字符就是一個(gè)字節(jié)(byte)。但是 Java 使用的 Unicode 是一種大字符集,用兩個(gè)字節(jié)(16bit)來表示一個(gè)字符,這時(shí)字節(jié)與字符就不再相同。為實(shí)現(xiàn)與其他程序語言及不同平臺(tái)的交互,Java 提供一種新的數(shù)據(jù)流處理方案稱作 Reader 和 Writer。在 java.io 包中有許多不同類對(duì)其進(jìn)行支持,其中最重要的是 InputStreamReader 和 OutputStreamWriter 類。這兩個(gè)類是字節(jié)流和 Reader 和 Writer 的接口,用來在字節(jié)流和字符流之間作為中介。
在英語國(guó)家中,字節(jié)編碼采用 ISO8859_1 協(xié)議。ISO8859_1 是 Latin-1 編碼系統(tǒng)映射到 ASCII 標(biāo)準(zhǔn),能夠在不同平臺(tái)之間正確轉(zhuǎn)換字符。
//構(gòu)造映射到 ASCII 碼的標(biāo)準(zhǔn)的 InputStreamReader 的方法
InputStreamReader ir= new InputStreamReader(System.in, "8859_1");//Reader 提供的方法
voidclose();void mark(intreadAheadLimit);booleanmarkSupported();intread();int read(char[] cbuf);int read(char[] cbuf, int off, intlen);booleanready();voidreset();long skip(longn);//Writer 提供的方法
voidclose();voidflush();void write(char[] cbuf);void write(char[] cbuf, int off, intlen);void write(intc);voidwrite(String str);void write(String str, int off, int len);
二、緩沖區(qū)讀者和緩沖區(qū)寫者
java.io 中提供流緩沖流 BufferedReader 和 BufferedWriter。其構(gòu)造方法與 BufferedInputStream 和 BufferedOutputStream 類似。另外,除了 read() 和 write() 方法外,還提供了整行字符的處理方法
方法如下
public String readLine():BufferedReader 的方法,從輸入流中讀取一行字符,行結(jié)束標(biāo)志為 '\n' 、'\r' 或者兩者一起
public void newLine():BufferedWriter 的方法,向輸出流中寫入一個(gè)行結(jié)束標(biāo)志
示例
FileInputStream fis = new FileInputStream("data.ser");
InputStreamReader dis= newInputStreamReader(fis);
BufferedReader reader= newBufferedReader(dis);//BufferedReader reader = new BufferedReader(new FileReader("data.ser"));
String s;while((s = reader.readLine()) != null) {
System.out.println("read:" +s);
}
dis.close();
當(dāng)你寫文件的時(shí)候,為了提高效率,寫入的數(shù)據(jù)會(huì)先放入緩沖區(qū),然后寫入文件。因此有時(shí)候你需要主動(dòng)調(diào)用 flush()方法
//FileWriter
FileWriter fw = new FileWriter("D:/Test.txt");
String s= "hello world";
fw.write(s,0, s.length());
fw.flush();//flush將緩沖區(qū)內(nèi)容寫入到問題件//OutputStreamWriter
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:/Test1.txt"));
osw.write(s,0, s.length());
osw.flush();//PrintWriter
PrintWriter pw = new PrintWriter(new OutputStreamWriter(newFileOutputStream("D:/Test2.txt")), true);//PrintWriter pw = new PrintWriter(new FileWriter("D:/Test2.txt"));
pw.println(s);//close AllWriter
fw.close();
osw.close();
pw.close();
文件拷貝
File file = new File("D:/Test.txt");
File dest= new File("D:/new.txt");try{
BufferedReader reader= new BufferedReader(newFileReader(file));
BufferedWriter writer= new BufferedWriter(new FileWriter(dest));
String line=reader.readLine();while(line!=null){
writer.write(line);
line=reader.readLine();
}
writer.flush();
reader.close();
writer.close();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}
總結(jié)
以上是生活随笔為你收集整理的java io 输出流_Java IO 输入和输出流的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java模态_java – 如何在另一个
- 下一篇: java try resource_从