天天看點

IO流(三)

 Properties類:

 Properties類概述:

  • Properties是hashtable的子類。也就是說它具備map集合的特點。而且它裡面存儲的鍵值對都是字元串,不需要泛型定義。
  • Properties是不僅可以操作鍵值對資訊,而且可以操作硬碟上的鍵值對資訊。是集合中和IO技術相結合的集合容器。
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));  
        }  
    }  
  
      
}  
           

配置檔案:

用于記錄應用程式的運作次數,當運作次數已到, 給出 注冊的提示。并不再讓該程式執行。

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對象。File2、字元串路徑:String   3、字元輸出流:OutputStream

字元串列印流:PrintWriter

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

1、file對象:File2、字元串路徑:String3、位元組輸出流:OutputStream4、字元輸出流:Writer

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)

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();  
          
    }  
}  
           

 對象序列化

将堆記憶體中的對象存入硬碟,保留對象中的資料,稱之為對象的持久化(或序列化)

特有方法:

1、write(int val)   --->  寫入一個位元組(最低八位)

2、writeInt(int vale)  --->   吸入一個32為int值

/* 
對象的序列化 
*/  
  
import java.io.*;  
//對象序列化測試   
class ObjectStreamDemo   
{  
    public static void main(String[] args) throws Exception  
    {      
        //對象寫入流  
        writeObj();  
        //對象讀取流    
        readObj();  
    }  
    //定義對象讀取流   
    public static void readObj()throws Exception  
    {  
        //ObjectInputStream對細節對象進行操作   
        //建立對象讀取流    
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));  
        //通過讀取檔案資料,傳回對象    
        Person p = (Person)ois.readObject();  
  
        System.out.println(p);  
        //最終關閉流對象    
        ois.close();  
    }  
    //定義對象寫入流    
    public static void writeObj()throws IOException  
    {  
        //建立對象寫入流    
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt"));  
         //寫入對象資料    
        oos.writeObject(new Person("lisi0",399,"kr"));  
        //關閉流資源    
        oos.close();  
    }  
}  
           
/* 
沒有方法的接口通常稱為标記 
*/  
  
import java.io.*;  
//建立Person類,實作序列化  
class Person implements Serializable  
{  
    //定義自身的序列化方式    
    public static final long serialVersionUID = 42L;  
/*serialVersion
給類一個可被編譯器識别的的序列号,在編譯類時,會配置設定一個long型UID,通過序列号,
将類存入硬碟中,并序列化,即持久化。序列号根據成員算出的。
靜态不能被序列化。如果非靜态成員也無需序列化,可以用transien修飾。*/
    //定義私有屬性    
    private String name;  
    //age被transient修飾後就不能被序列化了,保證其值隻在堆記憶體中存在,而不再文本檔案中存在  
    transient int age;  
    //靜态成員變量不能被序列化  
    static String country = "cn";  
    //構造Person類    
    Person(String name,int age,String country)  
    {  
        this.name = name;  
        this.age = age;  
        this.country = country;  
    }  
    //覆寫toString方法    
    public String toString()  
    {  
        return name+":"+age+":"+country;  
    }  
}  
           

管道流:

PipedInputStream和PipedOutputStream是涉及到多線程技術的IO流對象。

步驟:

1、要先建立一個讀和寫的兩個類,實作Runnable接口,因為是兩個不同的線程,覆寫run方法,注意,需要在内部抛異常

2、建立兩個管道流,并用connect()方法将兩個流連接配接

3、建立讀寫對象,并傳入兩個線程内,并start執行

/* 
管道流技術,涉及多線程技術 
*/  
  
import java.io.*;  
//建立Read類,實作run方法    
class Read implements Runnable  
{  
    private PipedInputStream in;  
      
    Read(PipedInputStream in)  
    {  
        this.in = in;  
    }  
    //實作run方法    
    public void run()  
    {  
        try  
        {  
            byte[] buf = new byte[1024];  
             //讀取寫入的資料    
            System.out.println("讀取前。。沒有資料阻塞");  
            int len = in.read(buf);  
            System.out.println("讀到資料。。阻塞結束");  
  
  
  
            String s= new String(buf,0,len);  
  
            System.out.println(s);  
  
            in.close();  
  
        }  
        catch (IOException e)  
        {  
            throw new RuntimeException("管道讀取流失敗");  
        }  
    }  
}  
//建立Write類    
class Write implements Runnable  
{  
    private PipedOutputStream out;  
    //Write構造函數  
    Write(PipedOutputStream out)  
    {  
        this.out = out;  
    }  
    //實作run方法   
    public void run()  
    {  
        try  
        {  
            //寫入資料    
            System.out.println("開始寫入資料,等待6秒後。");  
            Thread.sleep(6000);  
            out.write("piped lai la".getBytes());  
            out.close();  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException("管道輸出流失敗");  
        }  
    }  
}  
  
class  PipedStreamDemo  
{  
    public static void main(String[] args) throws IOException  
    {  
        //建立管道流對象    
        PipedInputStream in = new PipedInputStream();  
        PipedOutputStream out = new PipedOutputStream();  
        //将讀取流(輸入流)和寫入流(輸出流)關聯起來    
        in.connect(out);  
  
        Read r = new Read(in);  
        Write w = new Write(out);  
        //建立讀寫對象,并建立線程對象    
        new Thread(r).start();  
        new Thread(w).start();  
  
  
    }  
}  
           

RandomAccessFile 類

RandomAccessFile 類概述:

1、RandomAccessFile稱之為随機通路檔案的類,自身具備讀寫方法。

2、該類不算是IO體系中的子類,而是直接繼承Object,但是它是IO包成員,因為它具備讀寫功能,内部封裝了一個數組,且通過指針對數組的元素進行操作,同時可通過seek改變指針的位置。

3、可以完成讀寫的原理:内部封裝了位元組輸入流

4、構造函數:RandomAccessFile(File file,String mode),可已從它的構造函數中看出,該類隻能操作檔案(也有字元串),而且操作檔案還有模式。

模式傳入值:”r“:以隻讀方式打開;”rw“:打開以便讀寫

如果模式為隻讀,則不會建立檔案,會去讀一個已存在的檔案,若檔案不存在,則會出現異常,如果模式為rw,且該對象的構造函數要操作的檔案不存在,會自動建立,如果存在,則不會覆寫,也可通過seek方法修改。

5.RandomAccessFile的最大的作用是實作多線程的下載下傳

特有方法:

1、seek(int n):設定指針,可以将指針設定到前面或後面

2、skipBytes(int n):跳過指定位元組數,不可往前跳

class RandomAccessFileDemo   
{  
    public static void main(String[] args) throws IOException  
    {  
        //writeFile_2();  
        //readFile();  
  
        //System.out.println(Integer.toBinaryString(258));  
  
    }  
  
    public static void readFile()throws IOException  
    {  
        //"r"代表模式,隻讀  
        RandomAccessFile raf = new RandomAccessFile("ran.txt","r");  
          
        //seek和skipBytes的差別是:skipBytes不能往回跳,seek可以前後的跳,可以随意改變指針。  
          
        //調整對象中指針。  
        //raf.seek(8*1);  
  
        //跳過指定的位元組數  
        raf.skipBytes(8);  
  
        byte[] buf = new byte[4];  
  
        raf.read(buf);  
  
        String name = new String(buf);  
  
        int age = raf.readInt();  
  
  
        System.out.println("name="+name);  
        System.out.println("age="+age);  
  
        raf.close();  
  
  
    }  
  
    public static void writeFile_2()throws IOException  
    {  
        RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");  
        raf.seek(8*0);  
        raf.write("周期".getBytes());  
        raf.writeInt(103);  
  
        raf.close();  
    }  
  
    public static void writeFile()throws IOException  
    {  
        RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");  
  
        raf.write("李四".getBytes());  
        raf.writeInt(97);  
        raf.write("王五".getBytes());  
        raf.writeInt(99);  
  
        raf.close();  
    }  
}  
           

操作基本資料類型的流對象

操作基本資料類型的流對象:DataInputStream和DataOutputStream

這兩個讀寫對象,可用于操作基本資料類型的流對象,包含讀寫各種基本資料類型的方法

import java.io.*;  
class DataStreamDemo   
{  
    public static void main(String[] args) throws IOException  
    {  
        //writeData();  
        //readData();  
  
        //writeUTFDemo();  
  
//      OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk");  
//  
//      osw.write("你好");  
//      osw.close();  
  
//      readUTFDemo();  
  
    }  
    public static void readUTFDemo()throws IOException  
    {  
        DataInputStream dis = new DataInputStream(new FileInputStream("utf.txt"));  
  
        String s = dis.readUTF();  
  
        System.out.println(s);  
        dis.close();  
    }  
  
  
  
    public static void writeUTFDemo()throws IOException  
    {  
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("utfdate.txt"));  
  
        dos.writeUTF("你好");  
  
        dos.close();  
    }  
  
    public static void readData()throws IOException  
    {  
        DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));  
  
        int num = dis.readInt();  
        boolean b = dis.readBoolean();  
        double d = dis.readDouble();  
  
        System.out.println("num="+num);  
        System.out.println("b="+b);  
        System.out.println("d="+d);  
  
        dis.close();  
    }  
    public static void writeData()throws IOException  
    {  
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));  
  
        dos.writeInt(234);  
        dos.writeBoolean(true);  
        dos.writeDouble(9887.543);  
  
        dos.close();  
  
        ObjectOutputStream oos = null;  
        oos.writeObject(new O());  
  
          
    }  
}