java io流 教程_Java基础教程:IO流与文件基础
Java:IO流與文件基礎(chǔ)
說(shuō)明:
本章內(nèi)容將會(huì)持續(xù)更新,大家可以關(guān)注一下并給我提供建議,謝謝啦。
走進(jìn)流
什么是流
流:指的是從源到目的地的字節(jié)的有序序列。
在Java中,可以從其中讀取一個(gè)字節(jié)序列的對(duì)象稱作 輸入流,可以向其中寫(xiě)入一個(gè)字節(jié)序列的對(duì)象稱作 輸出流。
? 這些字節(jié)序列的來(lái)源可以是:文件、網(wǎng)絡(luò)連接、內(nèi)存塊等。
? 抽象類InputStream和OutputStream是構(gòu)成輸入/輸出(I/O)的基礎(chǔ)。
? 因?yàn)槊嫦蜃止?jié)的流不便于處理以Unicode形式存儲(chǔ)的信息(字符),所以從抽象類Reader 和 Writer中繼承出來(lái)一個(gè)專門處理字符流的類層次結(jié)構(gòu)。
? 適配器類InputStreamReader將InputStream轉(zhuǎn)換為Reader,OutputStreamWriter將OutputStream轉(zhuǎn)換為Writer
IO流家族體系
對(duì)流的分類
? 依據(jù)流相對(duì)于程序的另一個(gè)端點(diǎn)的不同:? 節(jié)點(diǎn)流(全黃):以特定源(如磁盤文件、內(nèi)存某區(qū)域或線程之間的管道)為端點(diǎn)構(gòu)造的輸入/輸出流
? 過(guò)濾流(半黃):以其他已存在的流為端點(diǎn)構(gòu)造的輸入/輸出流。? 依據(jù)流中的數(shù)據(jù)單位不同:? 字節(jié)流:流中的數(shù)據(jù)以8位字節(jié)為單位進(jìn)行讀寫(xiě),以InputStream和OutputStream為共同父類
? 字符流:流中的數(shù)據(jù)以16位字符為單位進(jìn)行讀寫(xiě),以Reader和Writer為共同父類
家族體系圖(原創(chuàng))
家族體系的頂層方法
頂層方法不是很多,但是需要我們?nèi)ビ涀?#xff0c;下面列出了所有的頂層方法,遇到問(wèn)題是結(jié)合上圖和下表可以清理思路。
A.abstract classOutputStream
返回類型方法及解釋
void
close()? ??????????關(guān)閉此輸出流并釋放與此流有關(guān)的所有系統(tǒng)資源。
void
flush()? ??????????刷新此輸出流并強(qiáng)制寫(xiě)出所有緩沖的輸出字節(jié)。
void
write(byte[]?b)? ??????????將?b.length?個(gè)字節(jié)從指定的 byte 數(shù)組寫(xiě)入此輸出流。
void
write(byte[]?b, int?off, int?len)? ??????????將指定 byte 數(shù)組中從偏移量?off?開(kāi)始的?len?個(gè)字節(jié)寫(xiě)入此輸出流。
abstract ?void
write(int?b)? ??????????將指定的字節(jié)寫(xiě)入此輸出流。
B.abstract classInputStream
返回類型方法及解釋
int
available()? ??????????返回此輸入流下一個(gè)方法調(diào)用可以不受阻塞地從此輸入流讀取(或跳過(guò))的估計(jì)字節(jié)數(shù)。
void
close()? ??????????關(guān)閉此輸入流并釋放與該流關(guān)聯(lián)的所有系統(tǒng)資源。
void
mark(int?readlimit)? ??????????在此輸入流中標(biāo)記當(dāng)前的位置。
boolean
markSupported()? ??????????測(cè)試此輸入流是否支持?mark?和?reset?方法。
abstract ?int
read()? ??????????從輸入流中讀取數(shù)據(jù)的下一個(gè)字節(jié)。
int
read(byte[]?b)? ??????????從輸入流中讀取一定數(shù)量的字節(jié),并將其存儲(chǔ)在緩沖區(qū)數(shù)組?b?中。
int
read(byte[]?b, int?off, int?len)? ??????????將輸入流中最多?len?個(gè)數(shù)據(jù)字節(jié)讀入 byte 數(shù)組。
void
reset()? ??????????將此流重新定位到最后一次對(duì)此輸入流調(diào)用?mark?方法時(shí)的位置。
long
skip(long?n)? ??????????跳過(guò)和丟棄此輸入流中數(shù)據(jù)的?n?個(gè)字節(jié)。
C.abstract class Reader
返回類型方法及解釋
abstract ?void
close()? ??????????關(guān)閉該流并釋放與之關(guān)聯(lián)的所有資源。
void
mark(int?readAheadLimit)? ??????????標(biāo)記流中的當(dāng)前位置。
boolean
markSupported()? ??????????判斷此流是否支持 mark() 操作。
int
read()? ??????????讀取單個(gè)字符。
int
read(char[]?cbuf)? ??????????將字符讀入數(shù)組。
abstract ?int
read(char[]?cbuf, int?off, int?len)? ??????????將字符讀入數(shù)組的某一部分。
int
read(CharBuffer?target)? ??????????試圖將字符讀入指定的字符緩沖區(qū)。
boolean
ready()? ??????????判斷是否準(zhǔn)備讀取此流。
void
reset()? ??????????重置該流。
long
skip(long?n)? ??????????跳過(guò)字符。
D.abstract classWriter
返回類型方法及注釋
Writer
append(char?c)? ??????????將指定字符添加到此 writer。
Writer
append(CharSequence?csq)? ??????????將指定字符序列添加到此 writer。
Writer
append(CharSequence?csq, int?start, int?end)? ??????????將指定字符序列的子序列添加到此 writer.Appendable。
abstract ?void
close()? ??????????關(guān)閉此流,但要先刷新它。
abstract ?void
flush()? ??????????刷新該流的緩沖。
void
write(char[]?cbuf)? ??????????寫(xiě)入字符數(shù)組。
abstract ?void
write(char[]?cbuf, int?off, int?len)? ??????????寫(xiě)入字符數(shù)組的某一部分。
void
write(int?c)? ??????????寫(xiě)入單個(gè)字符。
void
write(String?str)? ??????????寫(xiě)入字符串。
void
write(String?str, int?off, int?len)? ??????????寫(xiě)入字符串的某一部分。
輸出輸入流的嵌套
說(shuō)明
單獨(dú)使用節(jié)點(diǎn)流的情況在程序中較少出現(xiàn)。
一般常通過(guò)過(guò)濾流將多個(gè)流套接在一起,利用各種流的特性共同處理數(shù)據(jù),套接的多個(gè)流構(gòu)成了一個(gè)流鏈
優(yōu)點(diǎn):
方便數(shù)據(jù)的處理并提高處理的效率。
著重介紹的幾個(gè)過(guò)濾流
? BufferedInputStream
? 在創(chuàng)建?BufferedInputStream?時(shí),會(huì)創(chuàng)建一個(gè)內(nèi)部緩沖區(qū)數(shù)組。
? 在讀取或跳過(guò)流中的字節(jié)時(shí),可根據(jù)需要從包含的輸入流再次填充該內(nèi)部緩沖區(qū),一次填充多個(gè)字節(jié)。
? BufferedOuputStream
? 該類實(shí)現(xiàn)緩沖的輸出流。通過(guò)設(shè)置這種輸出流,應(yīng)用程序就可以將各個(gè)字節(jié)寫(xiě)入底層輸出流中,而不必針對(duì)每次字節(jié)寫(xiě)入調(diào)用底層系統(tǒng)。
? BufferedReader和BufferedWriter同樣也是提供緩存區(qū)。
? DataInputStream
? 包含用于讀取基本類型數(shù)據(jù)的全部接口
說(shuō)明:所有的這些在下面我們都會(huì)重新強(qiáng)調(diào)并實(shí)現(xiàn)。
常用流
思維導(dǎo)圖
文件流
文件流包括
? FileReader/FileWriter類
? FileInputStream/FileOutputStream類
創(chuàng)建文件流
?FileInputStream(File?file)
通過(guò)打開(kāi)一個(gè)到實(shí)際文件的連接來(lái)創(chuàng)建一個(gè)?FileInputStream,該文件通過(guò)文件系統(tǒng)中的?File?對(duì)象?file?指定。
?FileInputStream(String?name)
通過(guò)打開(kāi)一個(gè)到實(shí)際文件的連接來(lái)創(chuàng)建一個(gè)?FileInputStream,該文件通過(guò)文件系統(tǒng)中的路徑名?name?指定。
實(shí)例
public class FileCopy{
public static void main(String[] args) throws IOException{
FileInputStream in=new FileInputStream("FileCopy.java");
FileOutputStream out=new FileOutputStream("FileCopy.txt");
int c;
while( (c=in.read())!=-1)
out.write(c);
in.close();
out.close();
}
}
緩存流
說(shuō)明:
緩存流是過(guò)濾流,以InputStream/OutputStream為前端流,并可指定緩沖區(qū)大小,如:
public BufferedInputStream(InputStream in)
public BufferedInputStream(InputStream in, int size)
BufferedReader增加readLine()
BufferedWriter增加newLine():寫(xiě)入一個(gè)換行符。
演示:
public class BufferedIO{
public static void main(String[] args) throws IOException{
BufferedReader in=new BufferedReader(
new FileReader("BufferedIO.java"));
PrintWriter out=new PrintWriter( new BufferedWriter(
new FileWriter("BufferedIO.txt")));
String s;
int linecnt=1;
StringBuilder sb=new StringBuilder();
while((s=in.readLine())!=null){
sb.append(linecnt+":"+s+"\n");
out.println(linecnt+":"+s);
linecnt++;
}
in.close();
out.close();
System.out.print(sb.toString());
}
}
說(shuō)明:
PrintWriter
向文本輸出流打印對(duì)象的格式化表示形式,即在寫(xiě)入的同時(shí)可以對(duì)寫(xiě)入的數(shù)據(jù)進(jìn)行格式化。
數(shù)據(jù)流
數(shù)據(jù)流包括:
DataInputStream/DataOutputStream類
讀寫(xiě)基本數(shù)據(jù)類型的接口方法:
演示:
public class DataIO{
public static void main(String[] args) throws IOException{
DataOutputStream out=new DataOutputStream(
new BufferedOutputStream(new FileOutputStream("data.txt")));
out.writeBoolean(false); out.writeChar('c');
out.writeByte(1); out.writeShort(2);
out.writeInt(3); out.writeLong(4L);
out.writeFloat(5.0f); out.writeDouble(6.0);
out.writeUTF("hello world!"); out.close();
DataInputStream in=new DataInputStream(
new BufferedInputStream( new FileInputStream("data.txt")));
System.out.println(in.readBoolean()+";"+in.readChar()+";");
System.out.println(in.readByte()+";"+in.readShort()+";");
System.out.println(+in.readInt()+";"+in.readLong());
System.out.println(in.readFloat()+";"+in.readDouble()+";");
System.out.println(in.readUTF()); in.close();
}
說(shuō)明:
?readUTF()與writeUTF()
writeBytes(String)和writeChars(String)方法在DataInputStream中沒(méi)有對(duì)應(yīng)的方法恢復(fù)出String
用DataOutputStream寫(xiě)字符串并使得DataInputStream能恢復(fù)出字符串的方法是使用writeUTF()和readUTF()
? UTF-8
ASCII字符→單字節(jié)形式;非ASCII字符→多字節(jié)形式
字符串長(zhǎng)度→UTF-8字符串的前兩字節(jié)中
Java中使用的是UTF-8的變體,UTF-8只是讀寫(xiě)過(guò)程中的字符串形式,程序中Unicode
標(biāo)準(zhǔn)IO:
標(biāo)準(zhǔn)輸入:鍵盤
標(biāo)準(zhǔn)輸出:加載Java程序的命令窗口
Java在System類中定義了三個(gè)標(biāo)準(zhǔn)I/O流,是System類的三個(gè)靜態(tài)變量:
?System.in(public static final InputStream in):標(biāo)準(zhǔn)輸入流
?System.out(public static final PrintStream out):標(biāo)準(zhǔn)輸出流
?System.err(public static final PrintStream err):標(biāo)準(zhǔn)錯(cuò)誤輸出流
程序從鍵盤讀入數(shù)據(jù):
? int ch=System.in.read();
? System.in.read()從鍵盤緩沖區(qū)讀入一個(gè)字節(jié)的數(shù)據(jù),返回的是整型值(低位字節(jié)為輸入數(shù)據(jù),高位字節(jié)全為零)
? System.in.read()的執(zhí)行使得整個(gè)程序被掛起,直到用戶從鍵盤輸入數(shù)據(jù)才繼續(xù)運(yùn)行
? 從鍵盤逐行讀入:嵌套BufferedReader和InputStreamReader
實(shí)例:
public class StandardIO {
public static void main(String[] args) {
String s;
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
System.out.println("Please input: ");
try {
s = in.readLine();
while (!s.equals("exit")) {
System.out.println(" read: " + s);
s = in.readLine();
}
System.out.println("End of Inputting");
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
java.util.Scanner類:從控制臺(tái)讀取輸入
說(shuō)明
Scanner sc=new Scanner(System.in);
Scanner將控制臺(tái)輸入按照分隔符模式進(jìn)行分割,分隔符模式默認(rèn)為匹配空格
掃描結(jié)果通過(guò)各種next*()方法轉(zhuǎn)化為不同類型的值
next()獲取一個(gè)字符串
nextByte() 獲取一個(gè)byte類型的整數(shù)
nextShort() 獲取一個(gè)short類型的整數(shù)
nextInt() 獲取一個(gè)int類型的整數(shù)
nextLong() 獲取一個(gè)long類型的整數(shù)
nextFloat() 獲取一個(gè)float類型的數(shù)
nextDouble() 獲取一個(gè)double類型的數(shù)
nextLine() 獲取一行文本(即以回車鍵為結(jié)束標(biāo)志)
輸入輸出的重定向
System.setIn(InputStream)
System.setOut(PrintStream)
System.setErr(PrintStream)
隨機(jī)存取文件
說(shuō)明
到目前為止所學(xué)習(xí)的Java流式輸入/輸出都是順序訪問(wèn)流,即流中的數(shù)據(jù)必須按順序進(jìn)行讀寫(xiě)當(dāng)需要隨機(jī)讀寫(xiě)磁盤文件中的內(nèi)容時(shí),用RandomAccessFile類(既可對(duì)文件讀,又可對(duì)文件寫(xiě))
RandomAccessFile與其他頂層類的關(guān)系
構(gòu)造方法
構(gòu)造方法摘要
RandomAccessFile(File?file,?String?mode)? ??????????創(chuàng)建從中讀取和向其中寫(xiě)入(可選)的隨機(jī)訪問(wèn)文件流,該文件由?File?參數(shù)指定。
RandomAccessFile(String?name,?String?mode)? ??????????創(chuàng)建從中讀取和向其中寫(xiě)入(可選)的隨機(jī)訪問(wèn)文件流,該文件具有指定名稱。
mode值含意
"r"
以只讀方式打開(kāi)。調(diào)用結(jié)果對(duì)象的任何?write?方法都將導(dǎo)致拋出?IOException。
"rw"
打開(kāi)以便讀取和寫(xiě)入。如果該文件尚不存在,則嘗試創(chuàng)建該文件。
"rws"
打開(kāi)以便讀取和寫(xiě)入,對(duì)于?"rw",還要求對(duì)文件的內(nèi)容或元數(shù)據(jù)的每個(gè)更新都同步寫(xiě)入到底層存儲(chǔ)設(shè)備。
"rwd"
打開(kāi)以便讀取和寫(xiě)入,對(duì)于?"rw",還要求對(duì)文件內(nèi)容的每個(gè)更新都同步寫(xiě)入到底層存儲(chǔ)設(shè)備。
操作
文件指針操作
long getFilePointer()//返回當(dāng)前文件指針
void seek(long pos)//文件指針定位到指定位置
long length()//返回文件長(zhǎng)度
int skipBytes(int n)//從當(dāng)前位置開(kāi)始跳過(guò)n字節(jié)
讀操作(實(shí)現(xiàn)了DataInput接口)
readBoolean(), readChar(), readInt(), readLong(), readFloat(), readDouble(), readLine(), readUTF()等
寫(xiě)操作(實(shí)現(xiàn)了DataOutput接口)
writeBoolean(), writeChar(), writeUTF(), writeInt(), writeLong(), writeFloat(), writeDouble()等
實(shí)例
public class RandomAccessTest {
public static void main(String[] args) throws IOException {
long filePoint = 0;
String s;
RandomAccessFile file = new RandomAccessFile(
"RandomAccessTest.java", "r");
long fileLength = file.length(); // 獲取文件長(zhǎng)度
while (filePoint < fileLength) {
s = file.readLine(); // 讀一行字符,并移動(dòng)文件指針
System.out.println(s); // 輸出顯示讀入的一行字符
file.skipBytes(5);
filePoint = file.getFilePointer(); // 獲取當(dāng)前文件指針
}
file.close();
}
}
對(duì)象的串行化
將對(duì)象保存到外存,稱為對(duì)象的永久化。對(duì)象永久化的關(guān)鍵是將對(duì)象的狀態(tài)以一種串行格式表示出來(lái),以便以后讀取能夠?qū)⒃搶?duì)象重構(gòu)出來(lái)。對(duì)Java對(duì)象的這一讀寫(xiě)過(guò)程稱為對(duì)象的串行化。
常在下列情況下使用
1.Java遠(yuǎn)程方法調(diào)用(Remote Method Invocation)
2.Java Bean / EJB
3.對(duì)象永久化
實(shí)現(xiàn)串行化
? 用ObjectOutputStream/ObjectInputStream實(shí)現(xiàn)對(duì)象的串行化
◇ 通過(guò)ObjectOutputStream的writeObject方法將一個(gè)對(duì)象寫(xiě)入到流中
? public final void writeObject(Object obj) throws IOException
◇ 通過(guò)ObjectInputStream的readObject方法將一個(gè)對(duì)象從對(duì)象流中讀出
? public final Object readObject() throws IOException, ClassNotFoundException
◇ ObjectOutputStream實(shí)現(xiàn)了java.io.DataOutput接口
◇ ectInputStream實(shí)現(xiàn)了java.io.DataInput接口
實(shí)例
/*輸出對(duì)象*/
public class SerializeDate {
SerializeDate( ){
Date d = new Date( );
try {
ObjectOutputStream s= new ObjectOutputStream(
new FileOutputStream(“date.ser”));
s.writeObject(d);
s.close( );
}catch( IOException e){
e.printStackTrace( );
}
}
public static void main(String args[]){
SerializeDate b = new SerializeDate();
}
}
/*輸入對(duì)象*/
public class UnSerializeDate {
Date d = null;
UnSerializeDate() {
try {
ObjectInputStream s = new ObjectInputStream(
new FileInputStream("date.ser"));
Object o=s.readObject();
if(o instanceof Date)
d = (Date) o;
s.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
UnSerializeDate us = new UnSerializeDate();
System.out.println(us.d.toString());
}
}
注意:
一個(gè)類只有實(shí)現(xiàn)了Serializable接口,其對(duì)象才是可串行化的
(未完待續(xù).....)
總結(jié)
以上是生活随笔為你收集整理的java io流 教程_Java基础教程:IO流与文件基础的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java 接口的静态方法_Java8新特
- 下一篇: YY浏览器如何清理浏览器缓存?