黑馬程序員--IO流

--------------android培訓java培訓、學習型技術博客、期待與您交流! --------------

IO流的四個基類

   A:字節流
   輸入流
InputStream
|--FileInputStream
  輸出流
OutputStream
|--FileOutputStream
   B:字符流
  輸入流
 Reader
|--FileReader

  輸出流
  Writer
|--FileWriter
爲了提高讀寫效率,加入了緩衝技術
字符流:(BufferedReader和BufferedWriter)
字節流:(BufferedInputStream和BufferedOutputStream)

 複製文本代碼

package Demo;

/*需求:複製文本文件

 分析:源:用Reader或者InputStream    
          操作的是硬盤上的純文本數據用Reader           
          加入緩衝技術用BufferedReader   

     目的:用Writer或者OutputStream  
          操作的是硬盤上的純文本數據用Writer             
          加入緩衝技術用BufferedWriter

 */

import java.io.*;

public class CopyTxt {
	public static void main(String[] args) {
		BufferedReader bur = null;
		BufferedWriter buw = null;
		try {
			bur = new BufferedReader(new FileReader("D:\\work.txt")); // 提高效率,定義讀取流緩衝區
			buw = new BufferedWriter(new FileWriter("C:\\123.txt")); // 提高效率,定義寫入流緩衝區
			String line = null;
			while ((line = bur.readLine()) != null) { // 讀取一行數據
				buw.write(line);
				buw.newLine(); // 換行
				buw.flush(); // 刷新,將緩衝區的數據保存到文件裏。使用緩衝區一定記着刷新
			}
			System.out.println("複製成功");
		} catch (Exception e) {
			throw new RuntimeException("複製失敗");

		} finally {
			try {
				if (bur != null)
					bur.close(); // 關閉讀取流
			} catch (Exception e) {
				throw new RuntimeException("讀取流關閉失敗");
			}
			try {
				if (buw != null)
					buw.close(); // 關閉寫入流
			} catch (Exception e) {
				throw new RuntimeException("寫入流關閉失敗");
			}
		}
	}
}


 

需求:複製一張圖片

分析:

源:用Reader或者InputStream    

       操作的是硬盤上的非純文本數據用InputStream         

        加入緩衝技術用BufferedInputStream   

目的:用Writer或者OutputStream 

      操作的是硬盤上的純文本數據用OutputStream            

      加入緩衝技術用BufferedOutputStream

package Demo;

import java.io.*;

public class CopyPic {
	public static void main(String[] args) {
		BufferedInputStream br = null;
		BufferedOutputStream bw = null;
		try {
			bw = new BufferedOutputStream(new FileOutputStream("D:\\123.jpg"));
			br = new BufferedInputStream(new FileInputStream("C:\\abc.jpg"));
			int len = 0;
			while ((len = br.read()) != -1) { // 從輸入流中讀取下一個字節
				bw.write(len);
				bw.flush();
			}
		} catch (Exception e) {
			throw new RuntimeException("複製失敗");
		} finally {
			try {
				if (br != null) {
					br.close();
				}
			} catch (Exception e) {
				throw new RuntimeException("讀取流關閉失敗");
			}
			try {
				if (bw != null) {
					bw.close();
				}
			} catch (Exception e) {
				throw new RuntimeException("寫入流關閉失敗");
			}
		}
		System.out.println("複製成功");
	}
}


裝飾模式

               裝飾模式比繼承要靈活,而且降低了類於類之間的關係。避免了繼承體系臃腫。裝飾類因爲增強已有對象,具備的功能和已有的是相同的,只不過提供了更強功能,所以裝飾類和被裝飾類通常是都屬於一個體系中的。
          給已有的對象提供增強額外的功能。還不用對原有對象進行修改

             裝飾模式在IO中的應用,寫入文件用的FileWriter,發現這個類的功能不夠強大裝飾類出現了BufferedWriter,增強原有FileWriter的功能,在原有FileWriter的基礎上,增加了一個新的方法newLine(),但是BufferedWriter寫一行的方法,底層用的還是FileWriter的方法BufferedWriter構造方法  BufferedWriter(Writer out)

Writer
       |--TestWriter
       |--MediaWriter

現有一個體系用於各種數據的寫入。

但是,防線寫入效率有點低。想要對其進行效率的提高。
可以使用緩衝技術來完成的。


以後對象的寫入方法,不夠高效,可以通過派生子類的形式對齊進行復寫,定義高效的寫入動作。
Writer
        |--TestWriter
        |--BufferTextWriter
        |--MediaWriter
         |--BufferMediaWriter
通過繼承的方式提高了效率。
但是對於擴展性是一個問題。而且所需的功能越多,子類就越多。
一旦加入新類,就需要爲它提供高效。麻煩!


如何解決這個問題呢?優化!
既然都需要緩衝,對數據寫入的效率進行提高。
可以轉變一下思想,這樣來做,將緩衝技術單獨進行封裝。
哪個對象需要緩衝,就把哪個對象傳遞給緩衝對象即可。

class Buffer {

	Buffer(TestWriter w) {
	}

	Buffer(MediaWriter w) {
	}
}


爲了便於擴展,可以對一組對象進行緩衝。

class BufferWriter extends Writer{
	Buffer(Writer w){
	}
	Public void write(){
	}
}

 

體系就變成了這樣:
Writer
         |--TextWriter
         |--MediaWriter
         |--BufferWriter
BufferWriter的出現,增強了Writer體系中的功能。
這種設計方式比原來更爲靈活,避免了繼承的臃腫。
將這樣解決方式就定義了一個名稱方便於後人使用:裝飾設計模式。

裝飾設計代碼

/*
 模擬一下BufferedReader
 */
import java.io.*;

class MyBufferedReader extends Reader {

	private Reader r;

	MyBufferedReader(Reader r) {
		this.r = r;
	}

	// 可以一次讀一行數據的方法。
	public String myReadLine() throws IOException {
		// 定義一個臨時容器。原BufferReader封裝的是字符數組。
		// 爲了演示方便。定義一個StringBuilder容器。因爲最終還是要將數據變成字符串。
		StringBuilder sb = new StringBuilder();
		int ch = 0;
		while ((ch = r.read()) != -1) {
			if (ch == '\r')
				continue;
			if (ch == '\n')
				return sb.toString();
			else
				sb.append((char) ch);
		}

		if (sb.length() != 0)
			return sb.toString();
		return null;
	}

	/*
	 * 覆蓋Reader類中的抽象方法。
	 */
	public int read(char[] cbuf, int off, int len) throws IOException {
		return r.read(cbuf, off, len);
	}

	public void close() throws IOException {
		r.close();
	}

	public void myClose() throws IOException {
		r.close();
	}
}

class MyBufferedReaderDemo {
	public static void main(String[] args) throws IOException {
		FileReader fr = new FileReader("buf.txt");
		MyBufferedReader myBuf = new MyBufferedReader(fr);
		String line = null;
		while ((line = myBuf.myReadLine()) != null) {
			System.out.println(line);
		}
		myBuf.myClose();
	}
}

需求:讀取鍵盤錄入,將鍵盤錄入轉換成大寫存放在文件中

分析:

        源:用InputStream或Reader   

               操作的數據是純文本用Reader  加入緩衝技術BufferedReader  

       設備:鍵盤,對應的對象是System.in   所以要用轉換流 InputStreamReader
 
    目的:用Writer或OutputStream 

          操作的數據是文本數據用Writer  

          加入緩衝技術BufferedWriter 

    設備:硬盤   硬盤上的一個文本文件


 

package Demo;

import java.io.*;

public class ReadSystemIn {
	public static void main(String[] args) throws Exception {

		BufferedReader bur = null;
		BufferedWriter buw = null;
		try {
			bur = new BufferedReader(new InputStreamReader(System.in));
			buw = new BufferedWriter(new FileWriter("D:\\abc.java"));
			String line = null;
			while ((line = bur.readLine()) != null) { // 一次讀一行的數據
				if (line.equals("over"))
					break;
				buw.write(line.toUpperCase()); // 把讀取的字符串轉換成大寫並寫入
				buw.newLine(); // 換行
				buw.flush();
			}
		} catch (Exception e) {
			throw new RuntimeException("失敗");
		} finally {
			try {
				if (bur != null)
					bur.close(); // 關閉讀取流
			} catch (Exception e) {
				throw new RuntimeException("讀取流關閉失敗");
			}
			try {
				if (buw != null)
					buw.close(); // 關閉寫入流
			} catch (Exception e) {
				throw new RuntimeException("寫入流關閉失敗");
			}
		}
	}
}

File類

         

1)創建功能:

A:創建文件

public boolean createNewFile():如果文件不存在,就會創建一個文件。

B:創建文件夾(目錄)

public boolean mkdir():創建單級文件夾,要求父文件夾先存在

public boolean mkdirs():直接創建多級文件夾

2)刪除功能:

public boolean delete()     不管的是刪除文件還是文件夾,都是採用同一種功能。

注意事項:如果是刪除文件夾,請保證文件夾內沒有內容。 如果有內容,必須把內容刪除完畢才能刪除文件夾。

3)判斷功能:

           boolean exists() :文件是否存在.
         boolean  isFile(): 判斷是否是文件

           boolean isDirectory();是否是文件夾
         boolean  isHidden(); 是否隱藏
         boolean   isAbsolute(); 是否是絕對路徑,文件不存在的情況也能判斷。

4)獲取信息:

         String   getAbsolutePath():  獲取抽象路徑

需求: 將一個指定目錄下的class文件的絕對路徑,存儲到一個文本文件中。

分析:列出指定目錄下文件的絕對路徑,就是包含子目錄中的內容,也就是列出指定目錄下所有class文件的絕對路徑。 在列出過程中因爲是目錄中還有目錄,所以還可以調用本功能,也就是遞歸。
在使用遞歸的時候要注意:(1)遞歸一定要有出口,否則就是死遞歸。

                        (2)遞歸的次數不能過多,否則內存溢出。

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class ListDir {
	public static void main(String[] args) {
		File dir = new File("C:\\work2");
		List<File> list = new ArrayList<File>();
		getPath(dir, list);
		// System.out.println(list);
		writeToFile(list, "D:\\abc.txt");

	}

	// 定義一個獲取文件絕對路徑,把絕對路徑對象存入到集合中的方法
	public static void getPath(File dir, List<File> list) {
		File[] file = dir.listFiles();
		for (File f : file) {
			if (f.isDirectory()) { // 遍歷到的f,如果是目錄就進行遞歸
				getPath(f, list);
			} else {
				if (f.getName().endsWith(".class"))
					list.add(f);
			}
		}
	}

	// 定義一個得到集合裏面的絕對路徑,把絕對路徑存儲到指定的文本文件的方法
	public static void writeToFile(List<File> list, String javaListFile) {
		BufferedWriter buw = null;
		try {
			buw = new BufferedWriter(new FileWriter(javaListFile));
			for (File file : list) {
				buw.write(file.getAbsolutePath()); // 得到絕對路徑,並且寫入到流中
				buw.newLine();
				buw.flush();
			}
		} catch (IOException e) {
			throw new RuntimeException();
		} finally {
			try {
				if (buw != null)
					buw.close();
			} catch (IOException e) {
				throw new RuntimeException("寫入流關閉失敗");
			}
		}
	}
}


 


 

 

發佈了23 篇原創文章 · 獲贊 2 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章