Java-IO流-Properties

引出Properties

  • 将一个媒体文件切割成多个碎片

        1,切割文件的原理:一个源对应多个目的;切割文件的两种方式。
        2,碎片文件的命名和编号。
        3,程序代码体现。
        4,如何记录源文件的类型以及碎片的个数(建立配置信息文件)(其实也可以将这些信息记录碎片文件中)
        5,通过Properties属性集建立配置文件。
            常见方法:load(InputStream) load(Reader)  
            store(OutputStream,conmments),store(Writer,conmments)
        6,Properties的作为配置在应用程序很常见,主要用于将配置信息持久化。
            建立的配置文件扩展名规范: .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 {
//  将一个媒体文件切割成多个碎片。
        /*
         * 思路:
         * 1,读取源文件,将源文件的数据分别复制到多个文件中。
         * 2,切割方式有两种:按照碎片个数切,要么按照指定大小切。
         * 3,一个输入流对应多个输出流。
         * 4,每一个碎片都需要编号,顺序不要错。
         * 
         */
        
        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,使用字节流读取流和源文件关联。
        FileInputStream fis = new FileInputStream(srcFile);
        
        //2,明确目的。目的输出流有多个,只创建引用。
        FileOutputStream fos = null;
        
        //3,定义缓冲区。1M.
        byte[] buf = new byte[BUFFER_SIZE];//1M
        
        //4,频繁读写操作。
        int len = 0;
        int count = 1;//碎片文件的编号。
        while((len=fis.read(buf))!=-1){
            //创建输出流对象。只要满足了缓冲区大小,碎片数据确定,直接往碎片文件中写数据 。
            //碎片文件存储到partsDir中,名称为编号+part扩展名。
            fos = new FileOutputStream(new File(partsDir,(count++)+".part")); 
            //将缓冲区中的数据写入到碎片文件中。
            fos.write(buf,0,len);
            //直接关闭输出流。
            fos.close();
        }
        
        /*
         * 将源文件以及切割的一些信息也保存起来随着碎片文件一起发送。
         * 信息;
         * 1,源文件的名称(文件类型)
         * 2,切割的碎片的个数。
         * 将这些信息单独封装到一个文件中。
         * 还要一个输出流完成此动作。
         */
        String filename = srcFile.getName();
        int partCount = count;
        
        //创建一个输出流。
        fos = new FileOutputStream(new File(partsDir,count+".properties"));
        //创建一个属性集。
        Properties prop = new Properties();
        //将配置信息存储到属性集中。
        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,它里面存储的键值都是字符串,通常这个集合就用于配置文件的操作

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 {
        
        /*
         * 配置文件规律,只要读取一行文本,按照 = 对文本进行切割即可。
         */
        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]);
        }
        /*
         *  发现配置文件信息很多,需要进行存储。
         *  用哪个容器呢?个数不确定,就使用集合。
         *  发现信息中存在对应关系,使用Map集合。
         *  发现一点配置文件中的信息都是字符串,这些信息不在内存中而是在硬盘上。
         *  map中和io技术集合的集合对象: Properties,它里面存储的键值都是字符串,通常这个集合就用于配置文件的操作。
         *  
         */
        
        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();

        // 添加数据。
        prop.setProperty("zhangsan", "39");
        prop.setProperty("lisi", "29");
        
        //想要把数据保存到文件中,需要输出流。
        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方法,就可以将流中的数据加载集合中。原理;ReaderPartConfigDemo.java
        // 中的readPathConfig();
        prop.load(fr);

        System.out.println(prop);

        fr.close();
    }

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

        // 创建一个Properites集合。
        Properties prop = new Properties();

        // 添加数据。
        prop.setProperty("zhangsan", "39");
        prop.setProperty("lisi", "29");

        // 获取数据。一个。
        // 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);  //调试用
    }

}

合并文件-序列流SequenceInputStream

        1,文件合并的原理:多个源对应一个目的。
        2,每一个碎片对应一个输入流,多个输入流对象先要进行集合存储。
        3,SequenceInputStream可以解决这个问题。将多个源合并成一个源。
        4,读取配置文件信息,并加入健壮性的判断。
        5,独立解决碎片文件缺少的判断。
  • 为什么需要序列流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,碎片文件有很多,每一个碎片都需要和读取流关联。 2,每一个读取流读取到的数据都需要通过一个输出流写入到一个文件中。
         * 3,原理:多个源--->一个目的地。
         * 
         * 
         * 如下代码的问题: 碎片过多,会产生很多的输入流对象,这是正常的,不正常在于,面对每一个输入流对象去操作。
         * 当流对象过多时,必须先存储起来。面的流对象的容器操作更容易。 1,需要容器。 2,将流对象和碎片文件关联后存储到容器中。
         * 3,遍历容器获取其中的流对象,在进行频繁的读写操作。 4,即使关流也是遍历容器对每一个流对象进行close的调用。
         */

        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];
        // 遍历集合,获取流对象。
        for (FileInputStream fis : list) {

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

        fos.close();
        // 关闭所有流对象。
        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 {
        
        /*
         * 虽然合并成功,问题如下:
         * 1,如何明确碎片的个数,来确定循环的次数,以明确要有多少个输入流对象。
         * 2,如何知道合并的文件的类型。
         * 解决方案:应该先读取配置文件。
         */
        //1,获取配置文件。
        File configFile = getConfigFile(partsDir);
        
        //2,获取配置文件信息容器。获取配置信息的属性集。
        Properties prop = getProperties(configFile);
        
        //3,将属性集对象传递合并方法中。
        merge(partsDir,prop);
    }


    //根据配置文件获取配置信息属性集。
    private static Properties getProperties(File configFile) throws IOException {
        FileInputStream fis = null;
        Properties prop = new Properties();
        try{
            //读取流和配置文件相关联。
            fis = new FileInputStream(configFile);
            //将流中的数据加载的集合中。
            prop.load(fis);
        }finally{
            if(fis!=null){
                try{
                fis.close();
                }catch(IOException e){
                    //写日志,记录异常信息。便于维护。
                }
            }
        }
        return prop;
    }


    //根据碎片目录获取配置文件对象。
    private static File getConfigFile(File partsDir) {
        
        if(!(partsDir.exists() &&partsDir.isDirectory())){
            throw new RuntimeException(partsDir.toString()+",不是有效目录");
        }
    
        //1,判断碎片文件目录中是否存在properties文件。使用过滤器完成。
        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扩展名的文件不存在,或不唯一");
        }
        
        
        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,对碎片文件进行合并,将多个读取流合并成一个读取流。
        List<FileInputStream> list = new ArrayList<FileInputStream>();
        
        for (int i = 1; i < partCount; i++) {
            list.add(new FileInputStream(new File(partsDir, i + ".part")));
        }
        
        //怎么获取枚举对象呢?List自身是无法获取枚举Enumeration对象的,考虑到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();
    }
}

应用练习

定义功能记录程序运行次数,满足试用次数后,给出提示:试用次数已到,请注册

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 {
        /*
         * 定义功能记录程序运行次数,满足试用次数后,给出提示:试用次数已到,请注册。
         * 
         * 思路:
         * 1,需要计数器。这个软件使用一次计数一次。每使用一次,就进行计数累计。
         * 2,计数器是程序中的一个变量,程序启动计数器计数,可是程序结束这个计数器就消失了。
         * 下次启动会重新进行计数,原来计数的值没有保留下来。咋办?
         * 3,让这个计数器持久化。存储到文件中,为了标识数据可读性,数据起个名字。出现键值对。
         * 而且还是一个持久化的键值对,Properties集合正好符合这个要求。
         * 
         */
        
        if(isStop()){
            System.out.println("试用次数已到,请注册");
            return;
        }
        runcode();
        

    }

    private static boolean isStop() throws IOException {
        
        //1,配置文件。
        File configFile = new File("tempfile/app.properties");
        if(!configFile.exists()){//如果配置文件不存在,就创建。
            configFile.createNewFile();
        }
        
        //2,创建属性集。
        Properties prop = new Properties();
        
        //3,定义读取流和配置文件关联。
        FileInputStream fis = new FileInputStream(configFile);
        
        //4,将流关联的数据读取到属性集中。
        prop.load(fis);
        
        //5,通过属性集的指定键count,获取具体的次数。
        String value = prop.getProperty("count");
        int count = 0;
        //6, 对value进行判断,如果存在就对其自增。
        if(value!=null){
            count = Integer.parseInt(value);
            if(count>=5){
                return true;
            }
            
        }
        count++;//对其值进行自增。
        //7,将自增后的值和指定的键重新存储到属性集中,键相同,值覆盖。
        prop.setProperty("count", Integer.toString(count));
        
        //8,将属性集存储到配置文件中。对配置文件中的信息进行更新。
        FileOutputStream fos = new FileOutputStream(configFile);
        prop.store(fos, "app run count");
        
        //9,关闭资源。
        fos.close();
        fis.close();
        
        
        
        return false;
    }

    //程序主体。
    public static void runcode(){
        System.out.println("程序运行....play");
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容