Properties概述:
Properties 是hashtable的子类,具备map集合的特点里面存储的键值对都是字符串,是集合中和IO相结合的集合容器
该类对象的特点:可以用键值对形式的配置文件
在加载数据时要有固定格式,通常是:键=值
1,常用方法列表
steProperty();、getProperty();、设置和获取元素
stringPropertyNames(); JDK1.6返回属性列表中键集,Map>>Set
load(InputStream inStream) ;JDK1.6 从输入流中读取属性列表(键和元素对)
list(PrintStream out) 将属性列表输出到指定的输出流
stor(OutputStream out, String comments);将此 Properties 表中的属性列表(键和元素对)写入输出流
2,需求:将info.txt中键值数据存储到集合中操作,将流中的数据存到集合中
步骤:
1,将流和info.txt文件关联
2,读取一行数据,将该行数据用"="切割
3,等号左边为键,右边为值,存入Properties集合
操作演示:
import java.io.*; import java.util.*; class PropertiesDemo { public static void main(String[] args) throws IOException { // setAndGet(); // method_1(); loadDemo(); } public static void loadDemo() throws IOException//三,load,将流加载进集合,操作,存储 { Properties prop = new Properties(); FileInputStream fis = new FileInputStream("info.txt"); //字节输入流 prop.load(fis); //将流中数据加载进集合 prop.setProperty("xiaoqiang","99");//改变的只是内存中的数据,所以打印出99,但文件中还是22 FileOutputStream fos = new FileOutputStream("info.txt");//字节输出流 prop.store(fos,"haha"); //将prop表中键值对写入到fos输出流 prop.list(System.out);//属性列表,输出到控制台 fos.close(); fis.close(); } public static void method_1() throws IOException//二,将流中的数据存到集合中 { BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));//1,文件关联,读取字符流 String line = null; Properties prop = new Properties(); while ((line=bufr.readLine()) !=null) { String[] arr = line.split("="); //2,将每一行劈切割成数组(两个元素) prop.setProperty(arr[0],arr[1]);//3,等号左键右值,存入集合 } bufr.close(); sop(prop); //打印集合 } public static void setAndGet() //一,设置和获取元素 { Properties prop = new Properties();//隶属于Map集合HashTable prop.setProperty("xiaoqiang","22");//setProperty在底层调用了Map的put方法 prop.setProperty("zhangsan","33"); // sop(prop);//打印出键值对 String value = prop.getProperty("xiaoqiang");//获取键对应的值,类似于Map中的get() // sop(value);//打印出22 Set<String> names = prop.stringPropertyNames();//返回属性列表中键集,Map>Set for(String s : names){ sop(s+" : "+prop.getProperty(s)); } } public static void sop(Object obj){ System.out.println(obj); } }运行结果:
Properties应用
需求:记录应用程序运行次数,如果次数已到,给出注册提示
解决思路:很容易联想到计数器,但是计数器定义在程序中,随着程序的运行在内存中存在,并进行自增;可是随着该应用程序的退出,计数器也在内存中消失了,下次启动该程序时,又重新从0开始计数
使程序即使结束,计数器的值也存在,下次程序启动会先加载该计数器并+1后重新存储起来
所以建立一个配置文件,记录该软件运行次数;该配置文件使用键值对的形式,便于阅读和操作
键值对数据时map集合,数据以文件形式存储,使用io技术
即:map+io-->Properties.
实现过程:
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);//将流中数据加载进集合 String value = prop.getProperty("time");//获取time键的值 int count = 0;//此步骤为了处理value=null的情况,第一次运行将time的value设置为1 if(value !=null){ count = Integer.parseInt(value);//value有值,将字符串解析为十进制数, if(count>=5){ //限制使用次数 System.out.println("试用次数已到,请注册后使用!"); return; } } count++; prop.setProperty("time",count+"");//设置time键的值 FileOutputStream fos = new FileOutputStream(file);//定义输出流,目的 prop.store(fos,"haha"); fis.close();//关闭资源 fos.close(); } }
运行结果
扩展:其它获取数据较为便捷的方式
dom4j开发包 获取数据的,作为了解
打印流
PrintWriter与PrintStream可以直接操作输入流和文件。(重点)
该流提供了打印方法,可以将各种数据类型的数据原样打印。
PrintWriter
有多个构造函数,可以接受的参数类型:
1,File对象 File
2,字符串路径,String
3,字节输出流,OutputStream
4,字符输出流,Writer
import java.io.*; class PrintDemo { 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(); } }
序列流
SequenceInputStream
对多个流进行合并。
SequenceInputStream(Enumeration<? extends InputStream> e)
通过记住参数来初始化新创建的 SequenceInputStream,
该参数必须是生成运行时类型为 InputStream及其子类 对象的 Enumeration接口类 型参数。Vector类的方法element()返回值为枚举类型,但是效率不高
示例:将多个文件(输入流)合并为一个(输入流)输出到一个文件上
Vector实现文件合并
import java.io.*; import java.util.*; class SequenceDemo { public static void main(String[] args) throws IOException { Vector<FileInputStream> v = new Vector<FileInputStream>();//Enumeration枚举 v.add(new FileInputStream("g:\1.txt")); v.add(new FileInputStream("g:\2.txt")); v.add(new FileInputStream("g:\3.txt")); Enumeration<FileInputStream> en = v.elements();//返回此向量组件的枚举 SequenceInputStream sis = new SequenceInputStream(en);//应对多个序列流的参数列表使用枚举 FileOutputStream fos = new FileOutputStream("g:\0.txt");//目的 byte[] buf = new byte[1024]; int len = 0; while ((len=sis.read(buf)) !=-1)//字节输入流的方法read,返回字符串有效长度 { fos.write(buf,0,len); //输出 } fos.close(); sis.close();//序列流是由多个输入流合并成的一个输入流 } }
文件的分割与合并
主要知识点:序列流,字节流,字节流缓冲区,list集合,迭代器,枚举
由于Vector不够高效,在JDK1.2版本以后被ArrayList替代,枚举对应的迭代器,结构类似,都是取出对象的方法。
而序列流的参数只能是枚举类型,ArrayList又没有实现Enumeration接口,没有返回枚举类型的方法。但是有迭代器,就用匿名内部类的形式,将迭代器获取的ArrayList对象包装成枚举类型,传入序列流。
实现代码:
import java.io.*; import java.util.*; class SplitFile { public static void main(String[] args) throws IOException { splitFile(); merge(); } public static void merge() throws IOException //2,合并 { ArrayList<FileInputStream> al = new ArrayList<FileInputStream>(); for (int x=1; x<=6 ;x++ ){ al.add(new FileInputStream("g:\1\" +x+".part")); } final Iterator<FileInputStream> it = al.iterator();//内部类的局部变量要用final修饰 Enumeration<FileInputStream> en = new Enumeration<FileInputStream>() { //匿名内部类,通过迭代获取对象,转成枚举类型,传递给Sequence public boolean hasMoreElements(){ //实现枚举接口方法 return it.hasNext(); } public FileInputStream nextElement(){ //实现方法 return it.next(); } };//注意分号,匿名内部类 SequenceInputStream sis = new SequenceInputStream(en);//必须传入枚举类型 FileOutputStream fos = new FileOutputStream("g:\1\0.mp3"); byte[] buf = new byte[1024*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 //1,切割 { FileInputStream fis = new FileInputStream("g:\酒红色的心-玉置浩二.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("G:\1\"+(count++)+".part");//定义要输出的碎片 fos.write(buf,0,len); //写入字节数据 fos.close(); //每切割一次就关闭一次,因为每次循环都开启了一个新的流 } fis.close(); } }