黑馬程序員 java基礎--IO流(3)

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


                                              知識點六  File類

一、概述:

1、File類:文件和目錄路徑的抽象表現形式

2、特點:

1)用來將文件或文件夾封裝成對象

2)方便於對文件與文件夾的屬性信息進行操作

3)File對象可以作爲多數傳遞給流的構造函數

二、創建File對象:

方式一:File f1 = new File("a.txt");

      --->   將a.txt封裝成對象,可將已有的和未出現的文件或文件夾封裝成對象

方式二:File f2 = new File("c:\\abc","b.txt");

      --->   分別指定文件夾和文件。好處:降低了兩者的關聯程度,

方式三:File d = new File("c:\\abc");     File f3 = new File(d,"c.txt");

      --->   可以傳入父目錄和文件名。

目錄分隔符:調用File.separator,相當於是反斜槓 \

三、File類的常見方法
1.創建
  boolean createNewFile();在指定位置創建文件,如果該文件已經存在,則不創建,返回false。
  
  和輸出流不一樣,輸出流對象一創建就創建文件。而且文件已經存在,則覆蓋。
  
  boolean mkdir():創建文件夾,只能創建一級目錄
  
  boolean mkdirs():創建多級文件夾,可以創建多級目錄
  
2.刪除
  
  boolean delete();刪除失敗,返回false;
  
  void deleteOnExit();在程序退出時刪除指定文件。
3.判斷。
  boolean exists():文件是否存在
  booleanisFile():是否是文件
  boolean isDirectory():是否是文件目錄
  boolean  isHidden():文件是否隱藏
  boolean  isAbsolute():是否是絕對路徑
 
4.獲取信息。
  String getName(); 獲取文件名
  String getPath();  獲取文件的相對路徑(即創建的對象傳入的參數是什麼就獲取到什麼)
 String getParent();獲取父目錄,該方法返回絕對路徑中的父目錄,獲取相對路徑,返回null, 如果相對路徑中有上一級目錄,則返回的即爲該目     錄
  String getAbsolutePath();獲取絕對路徑
  long lastModified();最後一次修改的時候
  long length():文件的大小
  static File[] listRoots() ;獲取文件的系統根,即各個盤符

  String[] list() ;列出當前目錄所有文件,包含隱藏文件。注:調用了list方法的file對象,必須是封裝了一個目錄,且該目錄必須存在。

  boolean renameTo(File dest);對文件重命名爲dest

5.換名字: renameTo();方法用於更換文件的名字
6.  
列出及過濾文件:

    String[] list(); 列出當前目錄所有文件,包含隱藏文件,調用list方法的file對象,必須是封裝了一個目錄,且該目錄必須存在。

    File[] list(FilenameFilter filter); FilenameFilter:文件名過濾器,是一個接口,其中包含一個方法,accept(File dir,String name),返回    的是boolean型,對不符合條件的文件過濾掉。

    File[] listFiles(); 獲取當前文件夾下的文件和文件夾,返回類型爲File數組

     ListFiles(FilenameFilter filter);同list,是對獲取的 當前文件夾下的文件和文件夾的 文件名過濾器。


***關於覆蓋:覆蓋的原理是先刪除,然後再創建 ***

示例:

import java.io.*;

class FileDemo
{
   public static void main(String[] args) throws IOException
   {
    //  consMethod();
	method_5();
   }
   //創建File對象
   public static void consMethod()  
   {
     //將a.txt封裝成file對象。可以將已有的和未出現的文件或則文件夾封裝成對象。
      File f1=new File("a.txt");
	  
	  //abc指的是父目錄,b.txt指的是目錄中的文件名
	   File f2=new File("C:/abc","b.txt");
	  
	   //將目錄封裝成對象
	   File d=new File("C:/abc");
	   File f3=new File(d,"c.txt");
	   
	   sop("f1:"+f1);
	   sop("f2:"+f2);
	   sop("f3:"+f3);
	   
	   //separator是與系統有關的默認的名稱分割符,這樣就可以實現跨平臺
	   File f4=new File("c:"+File.separator+"abc"+File.separator+"ggg"+File.separator+"a.txt");
   }
  
   public static void sop(Object obj)
   {
      System.out.println(obj);
   }
   //方法一
   public static void method_1() throws IOException
   {
      File f=new File("file.txt");
	  f.deleteOnExit();
//	  sop("create:"+f.createNewFile());

      sop("delete:"+f.delete());
   }
    //方法二
    public static void method_2() throws IOException
    {
	     File f=new File("file.txt");
		 
		 //文件是否能被執行
		// sop("execute:"+f.canExecute());
		//判斷文件是否存在
		//sop("exists:"+f.exists());
		//創建文件夾
	    //mkdir()方法用於創建目錄,只能創建一級目錄,不能創建多級目錄
		//File dir=new File("abc\\aaa");
		//mkdir()方法用於創建一級目錄
		//sop("mkdir:"+dir.mkdir());
		
		//mkdirs()方法用於創建多級目錄
		File dir=new File("abc\\aaa\\ccc\\nnggg");
		//mkdir()方法用於創建多級目錄
		sop("mkdir:"+dir.mkdirs());
	}
	//方法三
	public static void method_3() throws IOException
    {
	   File f=new File ("file.txt");
	   //記住在判斷文件對象是否是文件對象或者目錄時,必須要先判斷該文件對象封裝的內容是否存在
	   //通過exists判斷。
	   
	   //f.createNewFile();
	   
	   f.mkdir();
	   
	   //isDirectory()判斷是否是目錄,isFile判斷是否是文件
	   sop("dir:"+f.isDirectory());
	   sop("dir:"+f.isFile());
	   
	   //判斷文件是否是絕對路徑
	   sop(f.isAbsolute());
	}
	//方法四
	public static void method_4() throws IOException
    {
	    File f=new File("file.txt");
		
		sop("path:"+f.getPath());
		
     	sop("abspath:"+f.getAbsolutePath()); 
		//該方法返回的是絕對路徑中的父目錄
		//如果獲取的是相對路徑,返回null空
		//如果相對路徑中有上一層目錄,那麼該目錄就是返回結果
		sop("parent:"+f.getParent()); 
		
	}
	
	//方法五
	public static void method_5() throws IOException
    {
	    //這樣相當於移動(剪貼)和重命名
	    File f1=new File("C:/Test.java");
		
		File f2=new File("d:/Sword.java");
		
		//renameTo()方法用於更換文件的名字
		sop(f1.renameTo(f2));
		
	} 
	
}

/*
list用於打印指定目錄下文件或則文件夾的名稱的

listRoots()列出機器中有效的盤符
*/

import java.io.*;

class FileDemo2
{
   public static void main(String[] args) throws IOException
   { 
       File dir=new File("C:\\");
	   
	   File[] files=dir.listFiles();
	   
	   for(File f: files)
	   {
	      System.out.println(f.getName()+"::"+f.length());
	   }
	   
	   
   }
    public static void  listDemo_2()
   {
         // listRootsDemo();
	 
	 //listDemo();
	 File dir=new File("C:\\Users\\Administrator\\Desktop\\衝刺黑馬之路\\代碼");
	 
	 //FilenameFilter()爲匿名內部類
	  String[] arr=dir.list(new  FilenameFilter()
	  {
	     public boolean accept(File dir,String name)
		 {
		    // System.out.println("dir:"+dir+"...name"+name);
			 /*
			 if(name.endsWith(".java"))
			 {
			     return true;
			 }
			 */
		     return name.endsWith(".java");
		 }
	  });
	 
	  System.out.println("len:"+arr.length);
	 
	  for(String name:arr)
	  { 
	     System.out.println(name);
	  }
   }
   
   public static void  listDemo()
   {
      File f=new File("C:\\");
	  //list()用於打印指定目錄下文件或則文件夾的名稱的
	  //調用list方法的file對象必須是封裝了一個目錄,該目錄還必須存在。
	  String[] names=f.list();
	  for(String name:names)
	  { 
	     System.out.println(name);
	  }
   }
   
   public static void listRootsDemo()
   { 
      //列出機器中有效的盤符
       File[] files=File.listRoots();
       
	   //高級for循環,也就是for增強
       for(File f:files)
      {
	    System.out.println(f);
	  }	   
   }
}

四、遞歸:

對於每次循環都是用同一個功能的函數,即函數自身調用自身,這種表現形式或手法,稱爲遞歸。

注意:

1、限定條件,是作爲結束循環用的,否則是死循環

2、注意遞歸的次數,儘量避免內存溢出。因爲每次調用自身的時候都會先執行下一次調用自己的發那個發,所以會不斷在棧內存中開闢新空間,次數過多,會導致內存溢出。

例一:

列出指定目錄下文件或者文件夾,包含子目錄中的內容,也就是列出指定目錄下所有內容。用遞歸的方式層級顯示

分析,因爲目錄中還有目錄,只有使用同一個列出目錄功能的函數完成即可,在列出過程中出現的還是目錄的話,還可以再調用本功能,這就是利用遞歸原理。

import java.io.*;

class FileDemo3 
{
	public static void main(String[] args) 
	{
		File dir = new File("d:\\testdir");
		//showDir(dir,0);

		//toBin(6);
		//int n = getSum(8000);
		//System.out.println("n="+n);

		System.out.println(dir.delete());
	}
	//對目錄進行分級
	public static String getLevel(int level)
	{
		StringBuilder sb = new StringBuilder();
		sb.append("|--");
		for(int x=0; x<level; x++)
		{
			//sb.append("|--");
			sb.insert(0,"|  ");

		}
		return sb.toString();
	}
	public static void showDir(File dir,int level)
	{
		
		System.out.println(getLevel(level)+dir.getName());

		level++;
		File[] files = dir.listFiles();
		for(int x=0; x<files.length; x++)
		{
			if(files[x].isDirectory())
				showDir(files[x],level);
			else
				System.out.println(getLevel(level)+files[x]);
		}
	}

    public static int getSum(int n)
	{
		if(n==1)
			return 1;
		return n+getSum(n-1);
	}

	public static void toBin(int num)
	{
		if(num>0)
		{
			toBin(num/2);
			System.out.println(num%2);
		}
	}
        public static void method()
	{
		method();
	}
}
例二:

刪除一個帶內容的目錄:

刪除原理:在window中,刪除目錄是從裏往外刪除的,同樣使用遞歸

import java.io.*;

class  RemoveDir
{
	public static void main(String[] args) 
	{
		
		File dir = new File("d:\\testdir");
		removeDir(dir);
	}

	public static void removeDir(File dir)
	{
		File[] files = dir.listFiles();
		
		for(int x=0; x<files.length; x++)
		{
		     //if(!files[x].isHidden()&&files[x].isDirectory())判斷文件是否隱藏
		
			if(files[x].isDirectory())
				removeDir(files[x]);
			else
				System.out.println(files[x].toString()+":-file-:"+files[x].delete());
		}

		System.out.println(dir+"::dir::"+dir.delete());
	}

}
例三:
將一個指定目錄下的java文件的絕對路徑,存儲到一個文本文件中。
建立一個java文件列表文件。
思路:
1,對指定的目錄進行遞歸。
2,獲取遞歸過程所有的java文件的路徑。
3,將這些路徑存儲到集合中。
4,將集合中的數據寫入到一個文件中。
補充一點:

數據的持久化:把數據存硬盤裏就是持久化存儲

import java.io.*;
import java.util.*;
class  JavaFileList
{
	public static void main(String[] args) throws IOException
	{
		
		File dir = new File("d:\\java1223");

		List<File> list = new ArrayList<File>();

		fileToList(dir,list);

	   // System.out.println(list.size());
  
       //dir是父目錄,"javalist.txt"是文件名
	    File file = new File(dir,"javalist.txt");
		
		//file.toString()將路徑強轉成字符串
	    writeToFile(list,file.toString());

		


	}
	public static void fileToList(File dir,List<File> list)
	{
		File[] files = dir.listFiles();

		for(File file : files)
		{
			if(file.isDirectory())
				fileToList(file,list);
			else
			{
				if(file.getName().endsWith(".java"))
					list.add(file);
			}
		}
	}

	public static void writeToFile(List<File> list,String javaListFile)throws IOException
	{
		BufferedWriter bufw =  null;
		try
		{
			bufw = new BufferedWriter(new FileWriter(javaListFile));
			
			for(File f : list)
			{
			
			  //獲取每個文件的絕對路徑
				String path = f.getAbsolutePath();
				bufw.write(path);
				bufw.newLine();
				bufw.flush();
			}

		}
		catch (IOException e)
		{
			throw e;
		}
		finally
		{
			try
			{
				if(bufw!=null)
					bufw.close();
			}
			catch (IOException e)
			{
				throw e;
			}
		}
	}
}

                                             知識點七  Properties

一、概述:

1、Properties是hashtable的子類。也就是說它具備map集合的特點。而且它裏面存儲的鍵值對都是字符串,不需要泛型定義。
Properties是不僅可以操作鍵值對信息,而且可以硬盤上的鍵值對信息。是集合中和IO技術相結合的集合容器。

2、特點:

1)可用於鍵值對形式的配置文件

2)在加載時,需要數據有固定的格式,常用的是:鍵=值

二、常用方法:

1、設置和獲取元素:

Object setProperty(String key,String value);調用Hashtable的方法put

String getProperty(String key);  指定key搜索value

Set<String> stringPropertyName();返回屬性列表的鍵集,存入Set集合

void load(InputStream ism) ;從輸入字符流中讀取屬性列表

void load(Reader reader); 從輸入字符流中讀取屬性列表

示例:

import java.io.*;
import java.util.*;

class PropertiesDemo 
{
	public static void main(String[] args) throws IOException
	{
		//method_1();
		loadDemo();
	}

	public static void loadDemo()throws IOException
	{
		Properties prop = new Properties();
		FileInputStream fis = new FileInputStream("info.txt");

		//將流中的數據加載進集合。
		prop.load(fis);
         
		//setProperty改變的是內存的結果
		prop.setProperty("wangwu","39");

		FileOutputStream fos = new FileOutputStream("info.txt");
        
    //haha是注入信息,註釋,#代表註釋信息,不會被Properties所加載,Properties所加載的信息必須是鍵值對
        //那麼在加載數據時,需要數據有固定的格式,鍵=值
		prop.store(fos,"haha");

	//	System.out.println(prop);
		prop.list(System.out);

		fos.close();
		fis.close();

	}

	//演示,如何將流中的數據存儲到集合中。
	//想要將info.txt中鍵值數據存到集合中進行操作。
	/*
		1,用一個流和info.txt文件關聯。
		2,讀取一行數據,將該行數據用"="進行切割。
		3,等號左邊作爲鍵,右邊作爲值。存入到Properties集合中即可。

	*/
	public static void method_1()throws IOException
	{
		BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));

		String line = null;
		Properties prop = new Properties();


		while((line=bufr.readLine())!=null)
		{
		   //split是切割
			String[] arr = line.split("=");
			///System.out.println(arr[0]+"...."+arr[1]);
			prop.setProperty(arr[0],arr[1]);
		}

		bufr.close();

		System.out.println(prop);
	}
        //設置和獲取元素。set和get方法
	public static void setAndGet()
	{
		Properties prop = new Properties();
        
		//setProperty設置鍵值對
		prop.setProperty("zhangsan","30");
		prop.setProperty("lisi","39");
 
//		System.out.println(prop);
		String value = prop.getProperty("lisi");
		//System.out.println(value);
		
		//89+""轉化成字符型		
		prop.setProperty("lisi",89+"");

		Set<String> names = prop.stringPropertyNames();
		for(String s : names)
		{
			System.out.println(s+":"+prop.getProperty(s));
		}
	}

	
}
練習:限制程序運行次數。當運行次數到達5次時,給出,請您註冊的提示。並不再讓該程序執行。
1)很容易想到的是:計數器。
可是該計數器定義在程序中,隨着程序的運行而在內存中存在,並進行自增。
可是隨着該應用程序的退出,該計數器也在內存中消失了。
2)下一次在啓動該程序,又重新開始從0計數。
這樣不是我們想要的。
3)程序即使結束,該計數器的值也存在。
下次程序啓動在會先加載該計數器的值並加1後在重新存儲起來。
4)所以要建立一個配置文件。用於記錄該軟件的使用次數。
5)該配置文件使用鍵值對的形式。這樣便於閱讀數據,並操作數據。
6)鍵值對數據是map集合。數據是以文件形式存儲,使用io技術。那麼map+io -->properties.
補充知識點:

配置文件可以實現應用程序數據的共享。
現在要用的配置文件有兩種:鍵值對的和xml文件

dom4j: dom for java解析xml文件

示例:

import java.io.*;
import java.util.*;
class  RunCount
{
	public static void main(String[] args) throws IOException
	{
		Properties prop = new Properties();

		File file = new File("count.ini");
		if(!file.exists())
			file.createNewFile();
		
		FileInputStream fis = new FileInputStream(file);

		//將流中的數據加載到集合當中
		prop.load(fis);
		

		int count = 0;
		String value = prop.getProperty("time");
		
		if(value!=null)
		{
			count = Integer.parseInt(value);
			if(count>=5)
			{
				System.out.println("您好,使用次數已到,拿錢!");
				return ;
			}

		}

		count++;

		prop.setProperty("time",count+"");

		FileOutputStream fos = new FileOutputStream(file);
        
		
		//注入信息沒寫
		prop.store(fos,"");

		fos.close();
		fis.close();
		
	}
}

/*
name=zhangsan
age=20


<persons>
	<person id="001">
		<name>zhagnsan</name>
		<age>30</age>
		<address>bj</address>
	</person>
	<person>
		<name>...
	</person>
</persons>
*/
               
                                            知識點八  打印流

一、概述:

1、打印流包括:PrintStream和PrintWriter

2、該流提供了打印方法,可以將各種數據類型的數據都原樣打印。

二、字節打印流:PrintStream

構造方法中可接收的參數類型:

1、file對象。File

2、字符串路徑:String

3、字符輸出流:OutputStream

三、字符串打印流:PrintWriter

構造方法中可接受的參數類型

1、file對象:File

2、字符串路徑:String

3、字節輸出流:OutputStream

4、字符輸出流:Writer

補充知識點:在dos命令控制檯下,輸入cls可以清空dos控制檯,按下ctrl+c關閉輸入

示例:

import java.io.*;

class  PrintStreamDemo
{
	public static void main(String[] args) throws IOException
	{ 
        //讀取鍵盤錄入,這句話非常的重要,一定要背下來
		BufferedReader bufr = 
			new BufferedReader(new InputStreamReader(System.in));
        
		//把文件封裝到流裏面,可以實現字符刷新
		PrintWriter out = new PrintWriter(new FileWriter("a.txt"),true);

		String line = null;

		while((line=bufr.readLine())!=null)
		{
			if("over".equals(line))
				break;
			out.println(line.toUpperCase());
			//out.flush();
		}

		out.close();
		bufr.close();

	}	
}

                                                    知識點九  序列流


一、概述:

1.序列流SequenceInputStream沒有直接對應OutputStream,表示其它輸入流的邏輯串聯

2、SequenceInputStream可以將多個流連接成一個源

3、構造函數:

    SequenceInputStream(Enumeration<? extends FileInputStream> e)

二、如何合併多個文件:

1、創建集合,並將流對象添加進集合

2、創建Enumeration對象,將集合元素加入。

3、創建SequenceInputStream對象,合併流對象

4、創建寫入流對象,FileOutputStream,將數據寫入流資源

5、定義數組,將讀取流數據存入數組,並將數組中元素寫入文件中。

示例:

class SequenceDemo 
{
	public static void main(String[] args) throws IOException
	{

		Vector<FileInputStream> v = new Vector<FileInputStream>();

		
		v.add(new FileInputStream("c:\\1.txt"));
		v.add(new FileInputStream("c:\\2.txt"));
		v.add(new FileInputStream("c:\\3.txt"));
        
		
	 //Enumeration是個接口不是類(列舉)爲了實現遍歷枚舉也用於將輸入流指定到 SequenceInputStream 中。 
                          
     //注:此接口的功能與 Iterator 接口的功能是重複的。此外,Iterator 接口添加了一個可選的移除操作,並使用較短的方法名。
                       
     //新的實現應該優先考慮使用 Iterator 接口而不是 Enumeration 接口。
		Enumeration<FileInputStream> en = v.elements();

		SequenceInputStream sis = new SequenceInputStream(en);

		FileOutputStream fos = new FileOutputStream("c:\\4.txt");
         
		//創建緩衝區
		byte[] buf = new byte[1024];

		int len =0;
		while((len=sis.read(buf))!=-1)
		{
			fos.write(buf,0,len);
		}

		fos.close();
		sis.close();
	}
}
三、切割流資源:

1、先關聯文件FileInputStream

2、定義寫入流變量:FileOutputStream

3、創建數組,並定義切割所需的大小|

4、循環讀寫數據,並每次創建一個新寫入流,創建完後並寫入文件中

5、關閉流資源

示例:

import java.io.*;
import java.util.*;

class SplitFile 
{
	public static void main(String[] args) throws IOException
	{
		//splitFile();
		merge();
	}


	public static void merge()throws IOException
	{
		ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();

		for(int x=1; x<=3; x++)
		{
			al.add(new FileInputStream("c:\\splitfiles\\"+x+".part"));
		}

		final Iterator<FileInputStream> it = al.iterator();

		Enumeration<FileInputStream> en = new Enumeration<FileInputStream>()
		{
			public boolean hasMoreElements()
			{
				return it.hasNext();
			}
			public FileInputStream nextElement()
			{
				return it.next();
			}
		};

		SequenceInputStream sis = new SequenceInputStream(en);


		FileOutputStream fos = new FileOutputStream("c:\\splitfiles\\0.bmp");

		byte[] buf = new byte[1024];

		int len = 0;

		while((len=sis.read(buf))!=-1)
		{
			fos.write(buf,0,len);
		}

		fos.close();
		sis.close();
	}

	public static void splitFile()throws IOException
	{
		FileInputStream fis =  new FileInputStream("c:\\1.bmp");

		FileOutputStream fos = null;


		byte[] buf = new byte[1024*1024];

		int len = 0;
		int count = 1;
		while((len=fis.read(buf))!=-1)
		{
			fos = new FileOutputStream("c:\\splitfiles\\"+(count++)+".part");
			fos.write(buf,0,len);
			fos.close();
		}
		
		fis.close();
		
	}
}

 最新最全的的java學習視頻教程:http://pro.net.itcast.cn/View-22-1458.aspx

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

詳細請查看:http://edu.csdn.net/heima




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章