Java-IO流-Properties

引出Properties

  • 將一個(gè)媒體文件切割成多個(gè)碎片

        1,切割文件的原理:一個(gè)源對(duì)應(yīng)多個(gè)目的;切割文件的兩種方式。
        2,碎片文件的命名和編號(hào)。
        3,程序代碼體現(xiàn)。
        4,如何記錄源文件的類型以及碎片的個(gè)數(shù)(建立配置信息文件)(其實(shí)也可以將這些信息記錄碎片文件中)
        5,通過(guò)Properties屬性集建立配置文件。
            常見方法:load(InputStream) load(Reader)  
            store(OutputStream,conmments),store(Writer,conmments)
        6,Properties的作為配置在應(yīng)用程序很常見,主要用于將配置信息持久化。
            建立的配置文件擴(kuò)展名規(guī)范: .properties。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public class SplitFileTest {

    private static final int BUFFER_SIZE = 1048576;//1024*1024
    private static final String LINE_SEPARATOR = System.getProperty("line.separator");

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
//  將一個(gè)媒體文件切割成多個(gè)碎片。
        /*
         * 思路:
         * 1,讀取源文件,將源文件的數(shù)據(jù)分別復(fù)制到多個(gè)文件中。
         * 2,切割方式有兩種:按照碎片個(gè)數(shù)切,要么按照指定大小切。
         * 3,一個(gè)輸入流對(duì)應(yīng)多個(gè)輸出流。
         * 4,每一個(gè)碎片都需要編號(hào),順序不要錯(cuò)。
         * 
         */
        
        File srcFile = new File("1.mp3");
        File partsDir = new File("PartFiles");
        splitFile(srcFile,partsDir);

    }

    /**
     * 切割文件。
     * @param srcFile
     * @param partsDir
     * @throws IOException 
     */
    public static void splitFile(File srcFile, File partsDir) throws IOException {
    
        //健壯性的判斷。
        if(!(srcFile.exists() && srcFile.isFile())){
            throw new RuntimeException("源文件不是正確的文件或者不存在");
        }
        
        if(!partsDir.exists()){
            partsDir.mkdirs();
        }
        
        //1,使用字節(jié)流讀取流和源文件關(guān)聯(lián)。
        FileInputStream fis = new FileInputStream(srcFile);
        
        //2,明確目的。目的輸出流有多個(gè),只創(chuàng)建引用。
        FileOutputStream fos = null;
        
        //3,定義緩沖區(qū)。1M.
        byte[] buf = new byte[BUFFER_SIZE];//1M
        
        //4,頻繁讀寫操作。
        int len = 0;
        int count = 1;//碎片文件的編號(hào)。
        while((len=fis.read(buf))!=-1){
            //創(chuàng)建輸出流對(duì)象。只要滿足了緩沖區(qū)大小,碎片數(shù)據(jù)確定,直接往碎片文件中寫數(shù)據(jù) 。
            //碎片文件存儲(chǔ)到partsDir中,名稱為編號(hào)+part擴(kuò)展名。
            fos = new FileOutputStream(new File(partsDir,(count++)+".part")); 
            //將緩沖區(qū)中的數(shù)據(jù)寫入到碎片文件中。
            fos.write(buf,0,len);
            //直接關(guān)閉輸出流。
            fos.close();
        }
        
        /*
         * 將源文件以及切割的一些信息也保存起來(lái)隨著碎片文件一起發(fā)送。
         * 信息;
         * 1,源文件的名稱(文件類型)
         * 2,切割的碎片的個(gè)數(shù)。
         * 將這些信息單獨(dú)封裝到一個(gè)文件中。
         * 還要一個(gè)輸出流完成此動(dòng)作。
         */
        String filename = srcFile.getName();
        int partCount = count;
        
        //創(chuàng)建一個(gè)輸出流。
        fos = new FileOutputStream(new File(partsDir,count+".properties"));
        //創(chuàng)建一個(gè)屬性集。
        Properties prop = new Properties();
        //將配置信息存儲(chǔ)到屬性集中。
        prop.setProperty("filename", srcFile.getName());
        prop.setProperty("partcount", Integer.toString(partCount));
        
        //將屬性集中的信息持久化。
        prop.store(fos, "part file info");
        
//      fos.write(("filename="+filename+LINE_SEPARATOR).getBytes());
//      fos.write(("partcount="+Integer.toString(partCount)).getBytes());
        fos.close();
        fis.close();
    }
}
  • 配置文件的建立和讀取

Properties,它里面存儲(chǔ)的鍵值都是字符串,通常這個(gè)集合就用于配置文件的操作

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class ReaderPartConfigDemo {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        //解析partConfig文件中的信息。
        
        File configFile = new File("PartFiles/7.partconfig");
        readPathConfig(configFile);

    }

    public static void readPathConfig(File configFile) throws IOException {
        
        /*
         * 配置文件規(guī)律,只要讀取一行文本,按照 = 對(duì)文本進(jìn)行切割即可。
         */
        BufferedReader bufr = new BufferedReader(new FileReader(configFile));
        
        String line = null;
        while((line=bufr.readLine())!=null){
            String[] arr = line.split("=");
            System.out.println(arr[0]+":::::"+arr[1]);
            //map.put(arr[0],arr[1]);
        }
        /*
         *  發(fā)現(xiàn)配置文件信息很多,需要進(jìn)行存儲(chǔ)。
         *  用哪個(gè)容器呢?個(gè)數(shù)不確定,就使用集合。
         *  發(fā)現(xiàn)信息中存在對(duì)應(yīng)關(guān)系,使用Map集合。
         *  發(fā)現(xiàn)一點(diǎn)配置文件中的信息都是字符串,這些信息不在內(nèi)存中而是在硬盤上。
         *  map中和io技術(shù)集合的集合對(duì)象: Properties,它里面存儲(chǔ)的鍵值都是字符串,通常這個(gè)集合就用于配置文件的操作。
         *  
         */
        
        bufr.close();
    }
}

Properties詳解

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;

public class PropertiesDemo {

    /**
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        // Properties集合的使用。

        // methodDemo_1();
//      methodDemo_2();
        methodDemo_3();

    }

    /*
     * 保存到流中的方法(持久化)
     */
    public static void methodDemo_3() throws IOException {

        Properties prop = new Properties();

        // 添加數(shù)據(jù)。
        prop.setProperty("zhangsan", "39");
        prop.setProperty("lisi", "29");
        
        //想要把數(shù)據(jù)保存到文件中,需要輸出流。
        FileWriter fw = new FileWriter("info.properties");
        
        //使用store方法。
        prop.store(fw, "info");
        
        fw.close();
        

    }

    /*
     * 演示從流中加載,。
     */
    public static void methodDemo_2() throws IOException {

        File configFile = new File("PartFiles/7.partconfig");
        FileReader fr = new FileReader(configFile);

        Properties prop = new Properties();
        // 使用Properties集合的load方法,就可以將流中的數(shù)據(jù)加載集合中。原理;ReaderPartConfigDemo.java
        // 中的readPathConfig();
        prop.load(fr);

        System.out.println(prop);

        fr.close();
    }

    // 1,基本使用,存和取。
    public static void methodDemo_1() {

        // 創(chuàng)建一個(gè)Properites集合。
        Properties prop = new Properties();

        // 添加數(shù)據(jù)。
        prop.setProperty("zhangsan", "39");
        prop.setProperty("lisi", "29");

        // 獲取數(shù)據(jù)。一個(gè)。
        // String value = prop.getProperty("lisi");
        // System.out.println("value="+value);

        // 全部取出。map--set--iterator
        Set<String> set = prop.stringPropertyNames();
        // System.out.println("-- listing properties --");
        for (String name : set) {
            String value = prop.getProperty(name);
            System.out.println(name + ":" + value);
        }
                 
        // prop.list(System.out);  //調(diào)試用
    }

}

合并文件-序列流SequenceInputStream

        1,文件合并的原理:多個(gè)源對(duì)應(yīng)一個(gè)目的。
        2,每一個(gè)碎片對(duì)應(yīng)一個(gè)輸入流,多個(gè)輸入流對(duì)象先要進(jìn)行集合存儲(chǔ)。
        3,SequenceInputStream可以解決這個(gè)問(wèn)題。將多個(gè)源合并成一個(gè)源。
        4,讀取配置文件信息,并加入健壯性的判斷。
        5,獨(dú)立解決碎片文件缺少的判斷。
  • 為什么需要序列流SequenceInputStream

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class MergeFileTest2 {

    /**
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        // 合并碎片文件。
        /*
         * 思路: 1,碎片文件有很多,每一個(gè)碎片都需要和讀取流關(guān)聯(lián)。 2,每一個(gè)讀取流讀取到的數(shù)據(jù)都需要通過(guò)一個(gè)輸出流寫入到一個(gè)文件中。
         * 3,原理:多個(gè)源--->一個(gè)目的地。
         * 
         * 
         * 如下代碼的問(wèn)題: 碎片過(guò)多,會(huì)產(chǎn)生很多的輸入流對(duì)象,這是正常的,不正常在于,面對(duì)每一個(gè)輸入流對(duì)象去操作。
         * 當(dāng)流對(duì)象過(guò)多時(shí),必須先存儲(chǔ)起來(lái)。面的流對(duì)象的容器操作更容易。 1,需要容器。 2,將流對(duì)象和碎片文件關(guān)聯(lián)后存儲(chǔ)到容器中。
         * 3,遍歷容器獲取其中的流對(duì)象,在進(jìn)行頻繁的讀寫操作。 4,即使關(guān)流也是遍歷容器對(duì)每一個(gè)流對(duì)象進(jìn)行close的調(diào)用。
         */

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

        for (int i = 1; i < 7; i++) {
            list.add(new FileInputStream("PartFiles/" + i + ".part"));
        }

        FileOutputStream fos = new FileOutputStream("PartFiles/00.mp3");

        byte[] buf = new byte[1024 * 1024];
        // 遍歷集合,獲取流對(duì)象。
        for (FileInputStream fis : list) {

            int len = fis.read(buf);
            fos.write(buf, 0, len);
        }

        fos.close();
        // 關(guān)閉所有流對(duì)象。
        for (FileInputStream fis : list) {

            fis.close();
        }
    }

}
  • 使用序列流SequenceInputStream合并文件

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

public class MergerFileTest3 {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        
        File partsDir = new File("E:\\PartFiles");
        
        mergerFile(partsDir);
    }

    public static void mergerFile(File partsDir) throws IOException {
        
        /*
         * 雖然合并成功,問(wèn)題如下:
         * 1,如何明確碎片的個(gè)數(shù),來(lái)確定循環(huán)的次數(shù),以明確要有多少個(gè)輸入流對(duì)象。
         * 2,如何知道合并的文件的類型。
         * 解決方案:應(yīng)該先讀取配置文件。
         */
        //1,獲取配置文件。
        File configFile = getConfigFile(partsDir);
        
        //2,獲取配置文件信息容器。獲取配置信息的屬性集。
        Properties prop = getProperties(configFile);
        
        //3,將屬性集對(duì)象傳遞合并方法中。
        merge(partsDir,prop);
    }


    //根據(jù)配置文件獲取配置信息屬性集。
    private static Properties getProperties(File configFile) throws IOException {
        FileInputStream fis = null;
        Properties prop = new Properties();
        try{
            //讀取流和配置文件相關(guān)聯(lián)。
            fis = new FileInputStream(configFile);
            //將流中的數(shù)據(jù)加載的集合中。
            prop.load(fis);
        }finally{
            if(fis!=null){
                try{
                fis.close();
                }catch(IOException e){
                    //寫日志,記錄異常信息。便于維護(hù)。
                }
            }
        }
        return prop;
    }


    //根據(jù)碎片目錄獲取配置文件對(duì)象。
    private static File getConfigFile(File partsDir) {
        
        if(!(partsDir.exists() &&partsDir.isDirectory())){
            throw new RuntimeException(partsDir.toString()+",不是有效目錄");
        }
    
        //1,判斷碎片文件目錄中是否存在properties文件。使用過(guò)濾器完成。
        File[] files = partsDir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                
                return pathname.getName().endsWith(".properties");
            }
        });
        
        if(files.length!=1){
            throw new RuntimeException("properties擴(kuò)展名的文件不存在,或不唯一");
        }
        
        
        File configFile = files[0];
        return configFile;
    }



    private static void merge(File partsDir,Properties prop) throws FileNotFoundException,
            IOException {
        
        //獲取屬性集中的信息。
         String filename = prop.getProperty("filename");
         int partCount = Integer.parseInt(prop.getProperty("partcount"));
        
        
        
        //使用io包中的SequenceInputStream,對(duì)碎片文件進(jìn)行合并,將多個(gè)讀取流合并成一個(gè)讀取流。
        List<FileInputStream> list = new ArrayList<FileInputStream>();
        
        for (int i = 1; i < partCount; i++) {
            list.add(new FileInputStream(new File(partsDir, i + ".part")));
        }
        
        //怎么獲取枚舉對(duì)象呢?List自身是無(wú)法獲取枚舉Enumeration對(duì)象的,考慮到Collections中去找。
        Enumeration<FileInputStream> en = Collections.enumeration(list);
        
        //源。
        SequenceInputStream sis = new SequenceInputStream(en);
        
        //目的。
        FileOutputStream fos = new FileOutputStream(new File(partsDir,filename));
        
        //不斷的讀寫。
        byte[] buf = new byte[4096];
        int len = 0;
        while((len=sis.read(buf))!=-1){
            fos.write(buf,0,len);
        }
        
        fos.close();
        sis.close();
    }
}

應(yīng)用練習(xí)

定義功能記錄程序運(yùn)行次數(shù),滿足試用次數(shù)后,給出提示:試用次數(shù)已到,請(qǐng)注冊(cè)

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public class AppCountTest {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        /*
         * 定義功能記錄程序運(yùn)行次數(shù),滿足試用次數(shù)后,給出提示:試用次數(shù)已到,請(qǐng)注冊(cè)。
         * 
         * 思路:
         * 1,需要計(jì)數(shù)器。這個(gè)軟件使用一次計(jì)數(shù)一次。每使用一次,就進(jìn)行計(jì)數(shù)累計(jì)。
         * 2,計(jì)數(shù)器是程序中的一個(gè)變量,程序啟動(dòng)計(jì)數(shù)器計(jì)數(shù),可是程序結(jié)束這個(gè)計(jì)數(shù)器就消失了。
         * 下次啟動(dòng)會(huì)重新進(jìn)行計(jì)數(shù),原來(lái)計(jì)數(shù)的值沒(méi)有保留下來(lái)。咋辦?
         * 3,讓這個(gè)計(jì)數(shù)器持久化。存儲(chǔ)到文件中,為了標(biāo)識(shí)數(shù)據(jù)可讀性,數(shù)據(jù)起個(gè)名字。出現(xiàn)鍵值對(duì)。
         * 而且還是一個(gè)持久化的鍵值對(duì),Properties集合正好符合這個(gè)要求。
         * 
         */
        
        if(isStop()){
            System.out.println("試用次數(shù)已到,請(qǐng)注冊(cè)");
            return;
        }
        runcode();
        

    }

    private static boolean isStop() throws IOException {
        
        //1,配置文件。
        File configFile = new File("tempfile/app.properties");
        if(!configFile.exists()){//如果配置文件不存在,就創(chuàng)建。
            configFile.createNewFile();
        }
        
        //2,創(chuàng)建屬性集。
        Properties prop = new Properties();
        
        //3,定義讀取流和配置文件關(guān)聯(lián)。
        FileInputStream fis = new FileInputStream(configFile);
        
        //4,將流關(guān)聯(lián)的數(shù)據(jù)讀取到屬性集中。
        prop.load(fis);
        
        //5,通過(guò)屬性集的指定鍵count,獲取具體的次數(shù)。
        String value = prop.getProperty("count");
        int count = 0;
        //6, 對(duì)value進(jìn)行判斷,如果存在就對(duì)其自增。
        if(value!=null){
            count = Integer.parseInt(value);
            if(count>=5){
                return true;
            }
            
        }
        count++;//對(duì)其值進(jìn)行自增。
        //7,將自增后的值和指定的鍵重新存儲(chǔ)到屬性集中,鍵相同,值覆蓋。
        prop.setProperty("count", Integer.toString(count));
        
        //8,將屬性集存儲(chǔ)到配置文件中。對(duì)配置文件中的信息進(jìn)行更新。
        FileOutputStream fos = new FileOutputStream(configFile);
        prop.store(fos, "app run count");
        
        //9,關(guān)閉資源。
        fos.close();
        fis.close();
        
        
        
        return false;
    }

    //程序主體。
    public static void runcode(){
        System.out.println("程序運(yùn)行....play");
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容