天天看點

黑馬程式員-課堂筆記-Properties類及檔案切割及檔案合并練習

  ------- <a href="http://www.itheima.com" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="blank">android教育訓練</a>、<a href="http://www.itheima.com" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="blank">java教育訓練</a>、期待與您交流! ----------

    其實重點主要是Properties,隻是檔案的切割和合并是對所學知識的一個綜合練習,設計的内容比較多,包括容器,異常,泛型,列印流等是以标題就成這樣的,又是Properties,又是切割又是合并的,可能Properties遠不止這些功能,以下内容為個人課堂筆記,将按自己的了解方式經行記錄,如有閱讀者另有高見,請不吝賜教,批評指正,我本菜鳥。無畏批評,教導。請多關照。

Properties:類表示了一個持久的屬性集。

Properties

可儲存在流中或從流中加載。屬性清單中每個鍵及其對應值都是一個字元串。——這句話是JavaAPI上面的說明,我怎麼都不能了解,聽畢老師的視訊後,個人的了解是:Properties是一種對io流和圖(鍵值對)相結合的一種對軟體配置資訊的持久化存儲的優化。以下是課程中講解Properties的主要方法:

String getProperty(String key):傳回值為字元串類型,而Properties是hashtable的子類,它具備map集合的特點,并且該集合中存儲的是鍵值對組合成的一個一個的字元串,集合中的元素就像hashmap中執行個體調用entrySet()傳回的Entry一樣,把鍵和值合并成了一個元素,而這個元素包含了鍵和值的資訊,并可以同個Properties方法重新将他們分開。getProperty的參數是map集合的鍵,傳回的是對應的值。

例如:

Properties propt=new Properties();                      
                     propt.setProperty("wangwu", 23+"");
                     propt.setProperty("zhangsan", 20+"");                     
                    System.out.println(propt.getProperty("wangwu");//列印結果會是23.
           

    既然上述内容中已經涉及到了setProperty()方法,那先闡述我對這個方法的了解,其實本來就因為放一塊兒将的,學javabean,不就是講的get和set嗎?聽課後練習寫代碼時該方法,基本上有兩個作用,第一,相當于集合中的add或是append,能夠往properties中加入資料,第二,能夠針對修改已經存在的鍵值對中的值。增加元素的功能是因為當時我修改容器中的wangwu的值時,少打了一個g。但列印結果卻多了一個wanwu的結果。  “  propt.setProperty("wanwu", 40+"");”就這句話的作用。

    能夠發表的筆記,是不是不光自己要能夠便于了解、記憶和學習,還要别人能起到同樣的作用哈?剛想到這,我就想起是不是做筆記也得講個科學性,比如下邊的内容, 就像類的抽象化,重點是抽取共性,那下邊我分三個部分分别講述(或者說是記錄我的課堂筆記),因為菜鳥講出來的東西,都是需要經過大神們考驗才是準确的東西,更何況軟體是一門很注重細節的專業。不表達一下我的不專業,怕會贻笑大方之家哦……  嘿嘿,言歸正傳:

        第一部分:void list(PrintStream out)和void list(PrintWriter out)重載了。一個接收位元組流參數,一個接收字元流參數。将屬性清單輸出到指定的輸出流propt.list(System.out);//列出集合目錄。并列印在控制台上。學到的就這麼點内容,其他沒什麼可講的,我一直在想的是:将屬性清單輸出到指定的輸出流。,如果參數傳遞的不是System.out,而是檔案,是不是這存儲的格式就它prpt.list();方法說了算?“-- listing properties --”這玩意兒去掉咋整呢?再有?不是輸出到指定的流裡邊去了嗎?要是我把指定的流再封裝一下。接下來又該咋整了?要是我的接收檔案有固定格式不需要這個“-- listing properties --”那得咋整啊?是不是這個list()方法就隻局限于列印輸出?

        第二部分:void load(Reader reader)和void load(InputStream inStream)和list()方法差不多,也是傳回空,也是接收位元組流,接收字元流參數,其實說到這裡,共性就出來了,下面将的第三部分,也存在着同樣的共性,也是傳回空,接收位元組流字元流重載。講完第三部分,把他們整一塊吧。印象更加深刻。void load(InputStream inStream)——從輸入流中讀取屬性清單(鍵和元素對)。void load(Reader reader)按簡單的面向行的格式從輸入字元流中讀取屬性清單(鍵和元素對)。其實兩者都是按面向行的格式讀取屬性清單,在API對load(InputStream inStream)沒有細細贅述了,執行個體如下:

Properties propt=new Properties();//建立Properties對象

FileInputStream fis=new FileInputStream("src\\com\\itheima\\info.txt");//建立位元組輸入流,并關聯源。

 propt.load(fis);//調用load方法,并把位元組輸入流傳遞給load方法。然後load方法按簡單的面向行的格式從輸入位元組流中讀取屬性清單。

        第三部分:void store(OutputStream out, String comments)和void store (Writer writer ,String comments)其實功能和load正好相反!load是從持久化存儲的檔案中擷取配置資訊傳遞給Properties集合,store則是從記憶體中的Properties集合中通過調用方法,并通過輸出流,把需持久化存儲的配置資訊存儲到配置檔案中存儲起來。執行個體如下:

                             Properties propt=new Properties();

                             FileOutputStream fos=new FileOutputStream("src\\com\\itheima\\info.txt");

                             propt.store(fos, "PropertiestoFile");

                             propt.list(System.out);//此行用于擷取記憶體中Properties集合中的資料,然後和已經傳到的配置檔案中的配置資訊進行對比(假如是修改配置資訊,而不是建立的配置檔案)!

                      傳遞位元組流參數                          傳遞字元流參數
void list(PrintStream out) void list(PrintWriter out)
void load(InputStream inStream) void load(Reader reader)
void store(OutputStream out, String comments) void store(Writer writer,String comments)

切割檔案:

1.需求:把一個檔案按固定檔案大小,把一個檔案切割成幾個獨立的檔案片段,并以.properties為擴充名的檔案格式儲存檔案片段。

2.思路:檔案時以大小進行切割,思路是:定義位元組數組緩沖區,假設檔案是以1M的容量進行切割,然後通過讀取流關聯需要被切割的檔案。同時建立位元組輸出流。接收位元組數組緩存區的資料。因為是切割成為多個片段檔案,如果不知道被切割檔案的大小,可以通過在循環體中建立輸出流對應每個需接收資料的片段檔案。

3步驟(代碼):

public static void splitFile()throws Exception
	{
		File f=new File("i.txt");
		System.out.println(f.getAbsolutePath());
		FileInputStream fis = new FileInputStream("splitfiles\\helloworld.mp3");
		FileOutputStream fos=null;
		byte [] buf=new byte[1024*1024];
		int len=0;
		int count=1;
		while((len=fis.read(buf))!=-1)
		{
			fos=new FileOutputStream("splitfiles\\"+(count++)+".part");
			fos.write(buf, 0, len);
			fos.close();
		}
		fis.close();
	}
           

合成檔案:

1.需求:把上例中的片段檔案重新組合成一個可執行的.mp3檔案。

2.思路:根據逆向思維,将多個檔案組合成一個檔案,那麼需建立多個輸入流,對應一個輸出流。問題是多個流如何與一個流建立有序傳輸資料的連接配接呢?本例中引入了SequenceInputStream。它的作用是将多個流合并成一個流。并以最後一個流的終止符,作為改合并了的流終止符。先分别建立對應多個片段檔案的位元組輸入流(因為引入的SequenceInputStream是位元組流),并且與檔案關聯。下一步試将多個流檔案按順序合并到SequenceInputStream流中。但是這裡涉及到一個問題是:SequenceInputStream有兩種重載形式的構造函數,一種是接收一個Enumeration的參數,而另外一個隻接收兩個位元組輸入流!是以就隻能選擇第一種SequenceInputStream(Enumeration<? extends InputStream> e)。問題有出來了,怎麼将多個輸入流變成一個Enumeration然後傳遞給SequenceInputStream呢?同時Enumeration是一個接口!?擺在眼前的一堆選擇(1、Vector容易可以實作就多個元素傳回成一個Enumeration,但是執行效率不高;2、可以考慮用執行效率高的容器,然後通過實作Enumeration接口來建立枚舉執行個體達到同樣的效果)。接下來就是建立緩沖區,建立輸出流,按同樣的思路執行即可。

3.步驟(代碼):

public static void merge()throws Exception
	{
		ArrayList<FileInputStream> arrlist=new ArrayList<FileInputStream>();
		for(int i=1;i<5;i++)
		{
			//FileInputStream fis=new FileInputStream("splitfiles\\"+i+".part");
			arrlist.add(new FileInputStream("splitfiles\\"+i+".part"));
			//fis.close();
		}
		final Iterator<FileInputStream> it=arrlist.iterator();
		Enumeration<FileInputStream> en=new Enumeration<FileInputStream>()
		{
			public boolean hasMoreElements()
			{
				return it.hasNext();
			}
			public FileInputStream nextElement()
			{
				return it.next();
			}
		};
		SequenceInputStream sis=new SequenceInputStream(en);
		byte [] buf = new byte[1024];
		FileOutputStream fos=new FileOutputStream("splitfiles\\shanming.mp3");
		int len=0;
		while((len=sis.read(buf))!=-1)
		{
			fos.write(buf, 0, len);
		}
		
		fos.close();
		sis.close();
		
		//fos.write(en);
	}
           

  FileInputStream fis = new FileInputStream("splitfiles\\helloworld.mp3");