02_IO操作的基本规律(InputStream,OutputStream,Reader,Writer,FileReader,FileWriter,BufferedReader,BufferedWri
模擬BufferedInputStream,編寫(xiě)一個(gè)類(lèi)
package toto.IO;
?
import java.io.IOException;
import java.io.InputStream;
?
class MyBufferedInputStream{
??? private InputStream in;
??? private byte[] buf = new byte[1024*4];
??? private int pos = 0,count = 0;
??? MyBufferedInputStream(InputStream in){
?????? this.in = in;
??? }
??? //從緩沖區(qū)中讀取一個(gè)字節(jié)
??? /**
??? *緩沖區(qū)的原理:
??? *其實(shí)就是定義了一個(gè)臨時(shí)容器
??? *然后將獲取到的數(shù)據(jù)都存入到臨時(shí)容器中,通過(guò)臨時(shí)容器的方法獲取數(shù)據(jù),當(dāng)臨時(shí)容器
??? *中的數(shù)據(jù)取完后,再獲取一批數(shù)據(jù)進(jìn)容器、
???
發(fā)現(xiàn)自定義的緩沖區(qū)出現(xiàn)了秒殺效果
為什么秒殺呢?
因?yàn)?/span>MP3這樣的媒體數(shù)據(jù),對(duì)應(yīng)的二進(jìn)制數(shù)據(jù),很有可能出現(xiàn)連續(xù)多個(gè)1的情況。而連續(xù)的過(guò)程中,出現(xiàn)-1,程序就認(rèn)為讀到了末尾,程序停止讀取。
???
為了避免這種情況,將獲取的一個(gè)字節(jié)數(shù)據(jù),進(jìn)行提升,變成int ,并在保留原有八位的基礎(chǔ)上補(bǔ)零。補(bǔ)完后,就變成了正數(shù),就避免了-1的這種情況。
??? ?*/
??? public int myRead() throws IOException{
?????? if(count == 0){
?????????? count = in.read(buf);//通過(guò)流對(duì)象從硬盤(pán)獲取一批數(shù)據(jù)裝入緩沖去
??????????
?????????? pos = 0;//從0開(kāi)始取
?????????? byte b = buf[pos];//將數(shù)據(jù)存入數(shù)組
?????????? pos++;//取完之后pos++
?????????? count--;//取走一個(gè)減少一個(gè)
?????????? return b&oxff;?? //這里與上的是255。這里進(jìn)行了自動(dòng)提升效果。
?????? }else if(count>0){
?????????? //第二次取時(shí)count>0
?????????? byte b = buf[pos];
?????????? pos++;
?????????? count--;
?????????? return b;
?????? }else {
?????????? return -1;
?????? }
??? }
??? public void myClose()throws IOException{
?????? in.close();
??? }
}
?
public class Demo1 {
?
???
}
?
/*package toto.IO;
?
import java.io.IOException;
import java.io.Reader;
?
*//**
?* 按照裝飾設(shè)計(jì)模式的思想
?* 自定義MyBufferedReader類(lèi)
?* 一樣提供一個(gè)和BufferedReader功能相同的readLine方法。
?*//*
class MyBufferedReader{//extends Reader{
??? 由于它里面中提供Reader中的所有方法,故它要繼承Reader類(lèi)。這里繼承的原因是里面的方法太多這里不寫(xiě)了
???
??? private FileReader r;這種方式只能包裝FileReader類(lèi),
??? 要想包裝所有的Reader的子類(lèi),我們寫(xiě)成以下方式:
???
??? private Reader r;
???
??? MyBufferedReader(Reader r) {//這里是被包對(duì)象
?????? this.r = r;
??? }
??? 提供一個(gè)一次讀一行的方法。
??? ?* 1、使用的還是Reader中read()方法,一次讀一個(gè)。
??? ?* 2、將讀到一個(gè)字符進(jìn)行臨時(shí)存儲(chǔ)。數(shù)組和StringBuilder都可以。
??? ?* 這里選用StringBuilder,因?yàn)榭梢允÷詳?shù)組延長(zhǎng)部分代碼的編寫(xiě)。該Builder中使用就是數(shù)組
??? ?* 而且可變長(zhǎng)度,并且最終變成字符串。
??? ?* 3、因?yàn)樽载?fù)有很多需要循環(huán)讀取。
??? ?* 4,讀取到的字符進(jìn)行判斷,如果是回車(chē)符,那么就將StringBuilder中的存儲(chǔ)數(shù)據(jù)作為字符串返回
???
??? public String myReadLine() throws IOException {
?????? StringBuilder sb = new StringBuilder();
??????
?????? int ch = 0;
?????? while((ch==r.read())!=-1) {//使用初進(jìn)來(lái)的read方法,并且要判斷不等于-1
?????????? if(ch=='\r')//遇到這個(gè)轉(zhuǎn)義字符時(shí),不能將這個(gè)數(shù)據(jù)讀進(jìn)去,并且將這個(gè)數(shù)據(jù)向下讀一個(gè)
????????????? continue;
?????????? if(ch=='\n')
????????????? return sb.toString();
?????????? sb.append((char)ch);//如果兩個(gè)都滿(mǎn)足,就將數(shù)據(jù)向里面轉(zhuǎn)了。
?????? }
?????? return null;
??? }
???
??? public void myClose() throws IOException{
?????? r.close();
??? }
}
public class MyBufferedReader{
?
???
??? public static void main(String[] args) {
?????? // TODO Auto-generated method stub
?
??? }
?
}
*/
?
?
?
轉(zhuǎn)換流
/*
?* 轉(zhuǎn)換流,涉及的對(duì)象都在字符流體系中。
?* InputStreamReader字節(jié)轉(zhuǎn)到字符的橋梁。 把看不懂得轉(zhuǎn)換成為看的懂的。
?* OutputStreamWriter:字符轉(zhuǎn)到字節(jié)的橋梁。把看得懂的轉(zhuǎn)換成為看不懂的。
?* 該類(lèi)本身是一個(gè)字符流,因?yàn)樗菢蛄?#xff0c;需要把一個(gè)指定的字節(jié)流傳給構(gòu)造函數(shù)。
?* 將制定的字節(jié)流轉(zhuǎn)成字符流。*/
?
package toto.IO;
?
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
?
public class Demo2 {
?
??? public static void main(String[] args)throws IOException {
?????? //readIn();
//???? System.out.println('-'+0);
//???? System.out.println('1'+0);
?????? readLineByKey();
??? }
??? /*
??? ?* 讀取鍵盤(pán)錄入,并打入的錄入的數(shù)據(jù)
??? ?* 當(dāng)錄入了一行數(shù)據(jù)后,打印錄入的一行數(shù)據(jù)內(nèi)容。而其可以不斷的進(jìn)行錄入
??? ?* 一次打印一行。
??? ?*
??? ?*1,讀取鍵盤(pán)通過(guò)System.in完成
??? ?*2,需要一次打印一行。那么就需要定義一個(gè)臨時(shí)容器,將讀取到自己額進(jìn)行臨時(shí)存儲(chǔ)。
??? ?*當(dāng)讀到回車(chē)符的時(shí)候就降臨時(shí)容器中存儲(chǔ)的數(shù)據(jù)一次性打印、*/
???
??? public static void printLineByKey() throws Exception{
?????? InputStream in = System.in;
?????? int by = 0;
?????? StringBuilder sb = new StringBuilder();
?
?????? while((by==in.read())!=-1){//這里有警告,不知道為什么
?????????? if(by=='\r')
????????????? continue;
?????????? if(by=='\n')
????????????? System.out.println(sb.toString());
?????????? else
????????????? sb.append((char)by);
?????? }
??? }
???
??? public static void readIn() throws IOException {
?????? //獲取標(biāo)準(zhǔn)的輸入流,對(duì)應(yīng)的默認(rèn)設(shè)備就是鍵盤(pán)。
?????? //從鍵盤(pán)獲取到的數(shù)據(jù)都是字節(jié)數(shù)據(jù)。
?????? InputStream in = System.in;
?????? //讀取鍵盤(pán)錄入的一個(gè)字節(jié)
??????
?????? //通過(guò)循環(huán)形式,讀取一個(gè)字節(jié),打印一個(gè)字節(jié)
?????? int by = 0;
?????? while((by=in.read())!=-1){
?????????? System.out.println(by);
?????? }
??????
??? }
??? public static void readLineByKey() throws IOException {
?????? //字節(jié)讀取流
??? ??? InputStream in =System.in;
??? ???
?????? //要想使用readLine方法讀取一樣,就要建立BufferReader對(duì)象
?????? //但是該字符流的緩沖區(qū),在對(duì)象在初始化時(shí),
?????? //要將一個(gè)字符對(duì)象作為參數(shù)傳遞給BufferReader的構(gòu)造函數(shù)
??? ??? //讀取鍵盤(pán)是字節(jié)流,如何讓字符流的緩沖區(qū)所使用呢?,這時(shí)就需要將字節(jié)流轉(zhuǎn)成字節(jié)流
??? ??? //想要進(jìn)行字節(jié)和字符流的轉(zhuǎn)換,就需要IO包中的轉(zhuǎn)換流
??? ??? //由于早期只有字節(jié)流,只有涉及到字符流之后才涉及到轉(zhuǎn)換,故這個(gè)轉(zhuǎn)換體系在字符流中。
??? ??? //InputStreamReader的前面是字節(jié)流,后面是字符流。故通過(guò)它轉(zhuǎn)換。
?????? InputStreamReader isr = new InputStreamReader(in);
??? ??? //因?yàn)?/span>BufferedReader只能包裝字符流。故只需將isr傳遞進(jìn)去就行了。
??? ??? BufferedReader bufr = newBufferedReader(isr);
??????
??? ??? String line = null;
??? ???
??? ??? while((line=bufr.readLine())!=null){
??? ??? if(line.equals("over")){
??? ??? ??? break;
??? ??? }
??? ??? //System.out.println(line.toUpperCase());
??? ??? }
??? ??? bufr.close();
??? }
???
}
?
?
package toto.IO;
/*流操作的基本規(guī)律
?* 流操作要明確數(shù)據(jù)源和數(shù)據(jù)目的(數(shù)據(jù)匯)
?*
?* 在現(xiàn)有程序中,
?* 源:鍵盤(pán)
?* 目的控制臺(tái)。
?* 1、需求:將一個(gè)硬盤(pán)上的文件打印在控制臺(tái)上
?* 2、需求:將鍵盤(pán)錄入的數(shù)據(jù)存儲(chǔ)到一個(gè)文件中。
?*
?* */
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
?
public class TransStreamDemo2 {
?
??? public static void main(String[] args) throws IOException {
?????? /*InputStream in = System.in;
?????? InputStreamReader isr = new InputStreamReader(in);
?????? BufferedReader bufr = new BufferedReader(isr);*/
?????? //上面三行可以轉(zhuǎn)換成一行,讀取鍵盤(pán)最方便方式,因?yàn)殒I盤(pán)錄入的都是文本數(shù)據(jù)。所以一次讀一行最方便,先將字節(jié)流包裝成字符流,再將字符流寫(xiě)入緩沖區(qū),提高效率。
?????? /*BufferedReader bufr = new
?????????? BufferedReader(new InputStreamReader(System.in));*/
??????
??????
?????? //硬盤(pán)上的文件是字節(jié)流,要將它轉(zhuǎn)換成字符流,讀取硬盤(pán)上的一個(gè)文件的方式:
?????? BufferedReader bufr = new
?????? BufferedReader(new InputStreamReader(new FileInputStream("文件地址")));
??????
??????
?????? /*向控制臺(tái)上輸出,使用System.out
OutputStream out = System.out;
?????? OutputStreamWriter osw = new OutputStreamWriter(out);
?????? BufferedWriter bufw = new BufferedWriter(osw);*/
??????
//???? BufferedWriter bufw = new BufferedWriter(newOutputStreamWriter(System.out));
??????
?????? //寫(xiě)需求1時(shí),上面包裝流中式文件路徑,下面是System.out,當(dāng)寫(xiě)需求2時(shí),上面是System.in,下面是要寫(xiě)到的文件的路徑。當(dāng)上下都是文件名稱(chēng)時(shí),相當(dāng)于文件的復(fù)制。
?????? BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("要寫(xiě)到的文件的地址")));
?????? String line = null;
?????? while((line==bufr.readLine())!=null){
?????????? if("over".equals(line)){
????????????? break;
?????????? }
?????????? bufw.write(line.toUpperCase());
?????????? bufw.newLine();
?????????? bufw.flush();
?????? }
?????? bufw.close();
?????? bufr.close();
??? }
?
}
?
IO包中對(duì)象其實(shí)都是以圍繞讀寫(xiě)為主,用于操作數(shù)據(jù)。
IO技術(shù)的難點(diǎn):因?yàn)?/span>io包中的對(duì)象太多,在實(shí)際開(kāi)發(fā),不太容易明確使用哪個(gè)對(duì)象
?
IO操作的基本規(guī)律:
1、?作用的數(shù)據(jù)源和數(shù)據(jù)目的。
如果是操作數(shù)據(jù)源:輸入流。(InputStream ,Reader),讀入的是字節(jié)流用InputStream,讀入的是字符流用Reader.
如果是操作數(shù)據(jù)匯:就是輸入流。(OutputStream,Writer),輸出成字節(jié)流用OutputStream,輸出成字符用writer
?
2、?要操作的數(shù)據(jù)是不是純文本數(shù)據(jù)。
如果是:使用字符流
如果不是:使用字節(jié)流。
3,根據(jù)源和目的的設(shè)備來(lái)確定要操作的對(duì)象。
?
?
無(wú)論數(shù)據(jù)源或者數(shù)據(jù)匯都有存在設(shè)備。
源設(shè)備:硬盤(pán)(File)。鍵盤(pán)(鍵盤(pán)對(duì)應(yīng)的是System.in)。內(nèi)存(內(nèi)存對(duì)應(yīng)的都是數(shù)組)。
目的設(shè)備:硬盤(pán)(File),控制臺(tái)(控制臺(tái)對(duì)應(yīng)的是:System.out),內(nèi)存(內(nèi)存對(duì)應(yīng)的是數(shù)組)。
?
?
這兩個(gè)明確可以確定到底要使用上面四個(gè)體系中的那個(gè)體系。
?
需求一:對(duì)文本文件進(jìn)行復(fù)制
1,?這個(gè)需求既有源又有目的
源:硬盤(pán)上的文件。InputStream Reader
目的:硬盤(pán)上的文件。OutputStream or Writer
?
是不是純文本數(shù)據(jù)呢?是。
源:要使用字符讀取流Reader
目的:要使用字符輸出流Writer
?
那么體系確定后,要使用該體系中那個(gè)對(duì)象呢?
源:是一個(gè)文件。所以要使用字符讀取流中可以操作文件的對(duì)象:FileReader
目的:也是一個(gè)文件,所以要使用字符寫(xiě)入流中的可以操作文件的對(duì)象:FileWriter
?
FileReader fr = new FileReader(“a.txt”);
FileWriter fw = new FileWriter(“b.txt”);
?
該操作過(guò)程中是否需要提高俠侶呢?是。
如果是:加入緩沖技術(shù)。
代碼就變成:
BufferedReader bufr = newBufferedReader(new FileReader(“a.txt”));
BufferedWriter bufw = newBufferedWriter(new FileWriter(“b.txt”));
?
?
需求二,將一個(gè)硬盤(pán)上的文件打印在控制臺(tái)上。
1,?明確源和目的
源:硬盤(pán)的文件。讀取文件,體系是InputStream or Reader
目的:控制臺(tái)。OutputStream or Writer
???? 對(duì)于控制臺(tái)較為特殊,其默認(rèn)的目的是System.out
2,?是不是純文本數(shù)據(jù)
是
源:Reader
目的Writer
3,明確體系中的對(duì)象
源:因?yàn)槭且粋€(gè)文件,FileReader
目的:因?yàn)槭强刂婆_(tái)對(duì)應(yīng)的對(duì)象是System.out,為了便于字符操作,所以將System.out轉(zhuǎn)換成字符流。
FileReader fr =new FileReader(“a.txt”);? 讀取字符流
OutputStreamWriterout =new OutputStreamWriter(System.out;); //輸出字節(jié)流
??????
FileReader fr =new FileReader(“a.txt”);? 讀取字符流
OutputStreamWriterosw = new OutputStreamWriter(System.out);這里也變成了字符流了。
?
??char[] buf = new char[1024];
int len = 0;
while((len=fr.read(buf))!=-1){
???osw.writer(buf,o.len);?? //將數(shù)據(jù)寫(xiě)到目的了(buf),即控制體。
}
?
為了提高效率,加入緩沖技術(shù)。
BufferedReader buf = new BufferReader(newFileReader(“a.txt”));
BufferedWriter bufw = newBufferedWriter(new OutputStreamWriter(“b.txt”));
?
String line = null;
While((lien=bufr.readLine())!=null){
?????? bufw.write(line);
?????? bufw.newLine();
?????? bufw.flush();
}
?
?
需求三,將錄入的文件寫(xiě)入硬盤(pán)上的文件。
1,明確體系;
源:InputStream。????System.in
目的:硬盤(pán)文件? OutputStream,Writer。
2,?明確純文本。
因?yàn)殒I盤(pán)錄入的都是字節(jié)數(shù)據(jù)。但是該數(shù)據(jù)最終得轉(zhuǎn)化成為純文本。
所以可以使用字符流。
源:Reader
目的:Writer。
3,?明確體系對(duì)象
源:因?yàn)殒I盤(pán)錄入,對(duì)應(yīng)的對(duì)象是System.in,是一個(gè)字節(jié)讀取流。
為了可以使用字符讀取留來(lái)操作這些數(shù)據(jù),可以將其轉(zhuǎn)換成字符讀取流
?
目的:因?yàn)槭且粋€(gè)文本文件,所以可以使用FileWriter。
InputStreamReaderisr = new InputStreamReader(System.in);
?
FileWriter fw =new FileWriter(“a.txt”);
?
?? 為了提高效率,加入了緩沖技術(shù)
?
Bufferreader bufr = new BufferedReader(newInputStreamReader(System,in));
BufferedWriter bufw = newBufferedWriter(new FileWriter(“a.txt”));
?
需求四:讀取鍵盤(pán)錄入,將錄入的信息打印在控制臺(tái)上,
1體系:
源:InputStream? Reader
目的:OutputStream,Writer
2純文本:是
源:Reader
目的:Writer
4,?對(duì)象:
源:System.in
目的:System.out
因?yàn)殒I盤(pán)錄入都是純文本,所以用字符流操作很方便。
那么就將源和目的都轉(zhuǎn)換成字符流
InputStreamReader isr = newInputStreamReader(System.in);
?
OutputStreamWriter osw = newOutputStreamWriter(System.out);
?
需要高效
BufferedReader bufr = newBufferedReader(new InputStreamReaderl(System,in));
BufferedWriter bufw = newBufferedWriter(new OutputStreamWriter(System.out));
?
注意:在使用寫(xiě)入緩沖區(qū)時(shí),記得要進(jìn)行刷新。flush().
?
?
?
需求五:將一個(gè)文本文件中的數(shù)據(jù)存儲(chǔ)到另一個(gè)文本文件中,要求按照UTF-8的編碼形式存儲(chǔ)
1,?體系
源InputStream or Reader
目的:OutputStream or Writer
2,純文本?yes
源:Reader
目的:Writer
3,對(duì)象:
因?yàn)椴僮魇俏谋?#xff0c;而且沒(méi)有指定編碼。所以可以按照默認(rèn)編碼形式
。那么就可以使用FileReader
目的:
按照一般思想,會(huì)去找FileWriter。但是FileWriter使用的默認(rèn)編碼。
而需求中要求按照指定編碼UTF-8形式存儲(chǔ)
那么這時(shí)就要用到轉(zhuǎn)換流,因?yàn)橹挥修D(zhuǎn)換流可以在初始化是指定編碼。
?
目的也是一個(gè)文件。那么就明確要使用的對(duì)象是FileOutStream。
?
FileReader fr =new FileReader(“a.txt”);
OutlputStreamWriterosw = new OutputStream(new FileOutputStream(“b.txt”),”UTF-8”);
需要提高效率
BufferedReaderbufr = new BufferedReader(new FileReader(a.txt));
???
???BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(newFileOutputStream(“b.txt”),”UTF-8”));
?
package toto.IO;
?
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
?
public class TransStreamDemo {
?
?????? /**
?????? ?* @param args
?????? ?*/
?????? publicstatic void main(String[] args)throws IOException {
????????????? //writeText();
????????????? readText();
?????? }
?????? publicstatic void readAndWrite()throws IOException{
????????????? FileReaderfr = new FileReader("test.txt");//字符流
????????????? //FileWriterfw = new FileWriter("test1.txt");//默認(rèn)的字符集。
????????????? OutputStreamWriterosw = new OutputStreamWriter(new
??????????????????????????? FileOutputStream("text1.txt"),"utf-8");//字符流
?????????????
????????????? char[] buf = new char[1024];
????????????? intlen = 0;
????????????? while((len=fr.read(buf))!=-1){
???????????????????? osw.write(buf,0,len);
????????????? }
????????????? osw.close();
????????????? fr.close();
?????? }
?????? publicstatic void readText() throws IOException{
????????????? FileReaderfr = new FileReader("test.txt");//這種編碼默認(rèn)是gbk
????????????? intch = fr.read();
????????????? System.out.println((char)ch);
?????????????
????????????? intch1 = fr.read();
????????????? System.out.println((char)ch1);
????????????? fr.close();
?????? }
?????? publicstatic void writeText() throws IOException{
????????????? FileWriterfw = new FileWriter("test.txt");
????????????? fw.write("你好");
????????????? fw.close();
?????? }
?
}
?
讀取一個(gè)UTF-8編碼的文件。
BufferedReader bufr =
New BufferedReader(new FileInputStream(“text.txt”,”utf-8”) )
?
或通過(guò):
InputStreamReaderisr = new InputStreamReader(new FileInputStream(“text.txt”,”utf-8”));
?
char[] buf = new char[1024];
總結(jié)
以上是生活随笔為你收集整理的02_IO操作的基本规律(InputStream,OutputStream,Reader,Writer,FileReader,FileWriter,BufferedReader,BufferedWri的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 01_Eclipse的使用方法
- 下一篇: 联创股份是什么公司