字符流的緩衝區
對應類:
BufferedWriter
BufferedReader
緩衝區的出現是爲了提高流的操作效率,所以在創建緩衝區之前必須要先有流對象。將需要被提高效率的流對象作爲參數傳遞給緩衝區的構造函數。
關閉緩衝區,就是在關才緩衝區中的流對象。
newline():換行
FileWriter fw = FileWriter(“D:\\aa.txt”);
BufferedWriter bw = BufferedWriter(fw);
bw.write(“adfdsafdsa”);
bw.newline();
bw.write(“fdsafsda”);
bw.close();
BufferedReader
readLine():讀一行
FileReader fr = new FileReader(“d:\\txt.txt”);
BufferedReader br = new BufferedReader(fr);
String str=null;
while((str=br.readLine())!=null){
out.print(str);
}
br.close();
緩衝區的複製文件
BufferedWriter bw = null;
BufferedReader br = null;
try{
bw = newBufferedWriter(new FileWriter(“D:\\aaa_copy.txt”));
br = newBufferedReader(new FileReader(“D:\\aaa.txt”));
String line = null;
while((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
}
自定義緩衝區類
class myBufferedReader{
privater FileReaderr;
myBufferedReader(FileReaderr){
this.r = r;
}
public String myReadLine(){
StringBuildersb = new StringBuilder();
intch=0;
while((ch=r.read())!=-1){
if(ch==’\r’)
contine;
if(ch==’\n’)
returnsb.toString();
else
sb.append((char)ch);
}
if(sb.length()!=0)
returnsb.toString();
return null;
}
public void myclose(){
r.close();
}
}
裝飾設計模式:
當要對已有的對象進行功能增強時,可以定義類,將已有對象傳入,基於已有對象的功能,並提供加強功能。那麼自定義的該類就稱爲裝飾類。
裝飾類通常會通過構造方法接收被裝飾的對象,並基於被裝飾的對象的功能,提供更強的功能。
裝飾和繼承的區別:
例:
MyReader
|--MyTextReader
|--MyTextReader
變爲:
MyReader
|--MyTextReader
|--MyTextReader
|--MyBuffereReader
裝飾模式比繼承要靈活,避免了繼承體系臃腫,而且降低了類與類之間的關係。裝飾類因爲增強已有對象,具備的功能和已有的是相同的,只不過提供了更強的功能。所有裝飾類和被裝飾類通常是都屬於一個體系中的。
import java.io.*;
class MyLineNumberReader{
private FileReader fr;
private int LineNumber=11;
MyLineNumberReader(FileReader fr ){
this.fr = fr;
}
public String myReadLine()throws Exception{
StringBuffer sb = new StringBuffer();
int ch;
while((ch=fr.read())!=-1){
if(ch=='\r'){
continue;
}
if(ch=='\n'){
LineNumber++;
return sb.toString();
}
else{
sb.append((char)ch);
}
}
if(sb.length()!=0){
System.out.println("++++++++++++++++++++++++++++++++");
return sb.toString();
}
return null;
}
public void setLineNumber(int LineNumber){
this.LineNumber=LineNumber;
}
public int getLineNumber(){
return LineNumber;
}
public void close()throws Exception{
fr.close();
}
}
class MyLineNumberDemo{
public static void main(String[] args)throws Exception{
FileReader fr = new FileReader("D:\\tmp\\aa_copy.txt");
MyLineNumberReader lnr = new MyLineNumberReader(fr);
lnr.setLineNumber(11);
String str;
while((str=lnr.myReadLine())!=null){
System.out.println(lnr.getLineNumber()+":"+str);
}
lnr.close();
}
}
LineNumberReader帶行號的裝飾類
getLineNumber();
setLineNumber();
自定義LineNumberReader類
FileReader fr = new FileReader("D:\\tmp\\aa_copy.txt");
LineNumberReader lnr = new LineNumberReader(fr);
lnr.setLineNumber(0);
String str;
while((str=lnr.readLine())!=null){
System.out.println(lnr.getLineNumber()+":"+str);
}
lnr.close();
字節流:
InputStream
OutputStream
FileInputStream
FileOutputStream
write(“abcd”.getBytes());//以單個字符存入
不需要用flush()方法刷新
FileInputStream fis = new FileInputStream(“aa.txt”);
byte[] buf = new byte[fis.available()];
fis.read(buf);
System.out.println(new String(buf));
fis.close();
不建議使用此方式,因爲考慮到文件比較大時,會發生內存溢出。
所以一般使用下面方式
FileInputStream fis = new FileInputStream(“aa.txt”);
byte[] buf = new byte[1024];
int num=0;
while((num=fis.read(buf))!=-1){
System.out.println(newString(buf,0,num));
}
複製一張圖片
用字節讀取流對象和圖片關聯。
用字節寫入流對象創建一個圖片文件。用於存儲獲取到的圖片數據。
通過循環讀寫,完成數據的存儲。
關才資源。
字節流的緩衝區
BufferedOutputStream
BufferedInputStream
BufferedInputStream bufis = new BufferedInputStream(newFileInputStream(“c:\\1.mp3”));
BufferedOntputStream bufos = new BufferedOntputStream(new FileOntputStream(“c:\\1_copy.mp3”));
int by=0;
while((by=bufis.read())!=-1){
bufos.write(by);
}
七. 自定義字節流緩衝區
import java.io.*;
classMyBufferedInputStream{
privateInputStream in;
privatebyte[] buf = new byte[1024];
private intpos=0,count=0;
MyBufferedInputStream(InputStreamin){
this.in=in;
}
//一次讀一個字節,從緩衝區(字節數組)獲取。
publicint myRead(){
//通過in對象讀取硬盤上數據,並存儲buf中。
if(count==0){
count = in.read(buf);
if(count<0)
return -1;
pos=0;
byte b = buf[pos];
count--;
pos++;
return b&255;
}elseif(count>0){
byte b = buf[pos];
count--;
pos++;
return b&255;
}
return-1;
}
publicvoid myClose(){
in.close();
}
}
讀取鍵盤錄入
System.out:對應的是標準輸出設備,控制檯
System.in:對應的是鍵盤
InputStreamin = System.in;
int by =in.read();
System.out.println(by);
InputStreamin = System.in;
int ch=0;
while((ch=in.read())!=-1){
System.out.println(by);
}
InputStreamin = System.in;
StringBuildersb = new StringBuilder();
while(true){
int ch=in.read();
if(ch==’\r’)
contine;
if(ch==’\n’){
String s = sb.String();
if(“over”.equals(s))
break;
System.out.println(s.toUpperCase());
sb.delete(0,sb.length());
}else{
sb.appen((char)ch);
}
}
十一. 通過剛纔的鍵盤錄入一行數據並打印其大寫,發現其實就是讀一行數據的原理,也就是readLine方法。
能不能直接使用readLine方法來完成鍵盤錄入的一行數據的讀取呢?
readLine方法是BufferedReader類中的方法。
而鍵盤錄入的read方法是字節流InputStream的方法。
那麼將字節流轉換成字符流再使用字符流緩衝區的readLine的方法。
InputStreamReader:將字節流轉換成字符流,在構造方法中傳入字節流。
OutputStreamWriter
code:
//獲取鍵盤錄入對象。
//InputStream in = System.in;
//將字節流對象轉成字符流對象,使用轉換流:InputStreamReader;
//InputStreamReader isr = newInputStreamReader(in);
//爲了提高效率,將字符串進行緩衝區的高效操作,使用裝飾類:BufferedReader;
//BufferedReader byfr = newBufferedReader(isr);
BufferedReader byfr = newBufferedReader(new InputStreamReader(System.in));
//OutputStream out = System.out;
//OutputStreamWriter osw = newOutputStreamWriter(out);
//BufferedWriter bufw = newBufferedWriter(osw);
BufferedWriter bufw = newBufferedWriter(new OutputStreamWriter(System.out));
String line=null;
while((line=bufr.read())!=null){
if(“over”.equals(line))
break;
osw.write (line.toUpperCase());
bufw.newLine();
osw.flush();
}
byfr.close();
十二.
1. 將鍵盤輸入的數據寫入到一個文件中,只需改上述代碼中的目的由控制檯改爲文件。
BufferedWriter bufw= new BufferedWriter(new OutputStreamWriter(new FileOutputStream(“out.txt”)));
2. 將一個文件的數據打印在控制檯上。
BufferedReader bufr= new BufferedReader(new InputStreamReader(new FileInputStream(“copyPic.java”)));
流操作的基本規律:
流對象有很多,不知識該用哪一個。
通過兩個明確來完成。
明確源和目的。
源:輸入流:InputStream Reader
目的:輸出流:OutputStream Writer
操作的數據是否是純文本。
是:字符流:Reader Writer
不是:字節流:InputStream OutputStream
當體系明確後,在明確要使用哪個具體的對象。通過設備來進行區分:
源設備:內存,硬盤,鍵盤
目的設備:內存,硬盤,控制檯
需求:
將一個文本文件中的數據存儲到另一個文件中,複製文件。
源:InputStreamReader //因爲是源,所以使用讀取流,判斷是不是操作文本文件,是!則選擇Reader。這樣體系就明確了。
接下來明確要使用該體系中的哪個對象。明確設備:硬盤上的一個文件。
Reader體系中可以操作文件的對象是:FileReader
是否需要提高效率,是!則加入Reader體系中的緩衝區:BufferedReader;
目的:OutputStreamWriter //目的是否是純文本,是!則Writer。設備:硬盤上的一個文件。Writer體系中可以操作文件的對象是:FileWriter
是否需要提高效率,是!則加入Writer體系中的緩衝區:BufferedWriter;
將鍵盤錄入的數據保存到一個文件中。
源:InputStream Reader //判斷是不是純文件?是!則用Reader。
設備:鍵盤,對應的對象是System.in ??? 不是選擇Reader嗎?System.in對應的不是字節流嗎?爲了操作鍵盤 的文本數據方便。轉成字符流按照字符串操作是最方便的。所以既然明確了Reader,那麼就將System.in轉換成Reader。
用到了Reader體系中的轉換流,InputStreamReader
code:
InputStreamReader isr = new InputStreamReader(System.in);
//需要提高效率嗎?需要!BufferedReader
BufferedReader bufr = new BufferedReader(isr);
目的:OutputStream Writer //是否是純文本,是!則用Writer、
設備:硬盤,一個文件,使用FileWriter
code:
FileWriter fw = new FileWriter(“a.txt”);
//提高效率?
BufferedWriter bufw = new BufferedWriter(fw);
擴展,想要把錄入的數據按照指定的編碼表存入,將數據存到文件中。
目的:OutputStream Writer //是否是純文本,是!則用Writer、
設備:硬盤,一個文件,使用FileWriter
但是FileWriter是使用的默認編碼表:GBK
但是存儲時,需要加入指定編碼表,而指定的編碼表只有轉換流可以指定。所以要使用的對象是OutputStreamWriter.而該轉換對象要接收一個字節輸出流,而且還可操作的文件的字節輸出流。FileOutputStream
code:
OutputStreamWriterosw = new OutputStreamWriter(new FileOutputStream(“d.txt”),”UTF-8”);
需要高效嗎?需要!
BufferedWriterbufw = new BuffereWriter(osw);
所以,記住!轉換流什麼使用,字符和字節之間的橋樑,通常,涉及到字符編碼轉換時,需要用到轉換流。
讀取指定編碼表的文件
InputStreamReader
十三. 改變標準輸入輸出設備. -不常用
System.setIn(new FileInputStream(“a.txt”);
System.setOut(newFileOutputStream(“b.txt”));
十四. 系統日誌文件
catch(Exception e){
Date d = newDate();
SimpleDateFormatsdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
String s =sdf.format(d);
PrintStreamps = new PrintStream(“exeception.log”)
ps.println(s);
System.setOut(ps);
e.printStackTreace(System.out);
}
十四. 打印系統信息
Properties p =System.getProperties();
//p.list(System.out);
p.liset(newPrintStream(“systeminfo.txt”));