IO流(其三)
-------- android培训、java培训、期待与您交流!--------
① 创建一个Properties集合
Properties prop = new Properties() ;
② 利用setProperties()方法存储元素
prop.setProperties("权权",30) ;
③ 取出元素
// 利用Set集合接收Properties对象的键
Set
for(String name : names){
//利用getProperty()方法取出键对应的值
String value = prop.getProperty(name) ;
}
④ 修改(如果键相同,则值将会被覆盖)
prop.setProperties("权权",20) ;
⑤ 通过list()方法将Properties集合中的信息进行输出,该方法对于调试很有用
//Properties集合具有与对象相结合的功能
prop.list(System.out) ;
⑥ 存储(使数据持久化)
prop.store("所要关联的流对象","属性列表的描述信息") ;
⑦ 读取配置文件信息
prop.load("所要关联的流对象") ;
通过以下一个范例,进一步了解Properties集合方法的使用以及其存储和读取功能:(注意:注释中包含注意点以及知识点)
package cn.itzixue.properties;
import java.io.*;
import java.util.Properties;
public class PropertiesDemo {
/*
* 范例:获取一个应用程序运行的次数,如果超过五次,停止运行程序,并提示试用次数已到
*
* 思路:
* 1.涉及到次数,需要一个计数器。每次程序启动都需要进行计数,而该计数器必须能在每次获取的时候自增一次,
* 并且要能将改变之后的值进行保存,便于下一次应用程序运行时能读取到已使用的次数
* 2.要让应用程序每次运行时都能够读到计数器信息,且能对计数信息进行修改,就应该让计数器的生命周期变长,
* 即从内存存取到硬盘文件
* 3.要想实现文件中的信息存储并体现,应该使用键值对的方式让其名字与之相对应,这就需要运用到MAP集合,
* 再加上需要读取硬盘上的数据,所以应该使用与MAP集合相关的io流,即是Properties
*/
public static void main(String[] args) throws IOException {
getAppCount() ;
}
public static void getAppCount() throws IOException {
//将配置文件封装成对象
File confile = new File("count.properties") ;
//如果文件不存在,则创建一个新文件。避免因文件不存在而是读取产生异常
if(!confile.exists()){
confile.createNewFile() ;
}
FileInputStream fis = new FileInputStream(confile) ;
//初始化Properties对象
Properties prop = new Properties() ;
//使用Properties对象的load()方法读取配置文件中的信息
prop.load(fis) ;
//利用Properties对象的getProperties()方法获取对应键的值
String value = prop.getProperty("time") ;
//定义一个计数器count来获取配置文件中的信息
int count = 0 ;
if(value!=null){
//因为字符串无法进行算术运算,所以应该用Integer.parseInt(value)方法来将获取到的字符串信息转换为整形数据
count = Integer.parseInt(value) ;
if(count>5){
//超过无五次进行提示,并结束程序
/*System.out.println("使用次数已到,请购买正版!!!!!!!!") ;
return ;*/
//使用RuntimeException更为合理
throw new RuntimeException("使用次数已到,请购买正版!!!!!!!!") ;
}
}
count++ ;
//将修改后的数据信息重新设置到Properties对象之中
prop.setProperty("time", count+"") ;
System.out.println("已使用 : "+count+" 次,剩下使用次数为 : "+(5-count)+" 次 !");
FileOutputStream fos = new FileOutputStream("count.properties") ;
//通过Properties对象的store()方法将修改后的数据写入到配置文件中
//注意:此处所传参数第一个是目的文件,第二个是对该配置文件的描述信息
prop.store(fos, "");
fos.close() ;
fis.close() ;
}
}
1.PrintStream
我们最常用到的输出语句:System.out对应的类型就是PrintStream。PrintStream具有以下几个特点:1.提供了打印方法可以对多种数据类型值进行打印,并保持数据的表示形式
2.不抛出IOException
3.构造函数可以接受三种类型的值(包括:① 字符串路径;② File对象;③ 字节输出流)
2.PrintWriter
构造函数可以接收四种类型的值(包括:① 字符串路径;② File对象;③OutputStream;④ Writer)。对于①,②类型的数据,还可以指定编码表。也就是字符集。对于③,④类型的数据,可以指定自动刷新。
注意:该自动刷新值为true时,只有三个方法可以用:println(),printf(),format()。
PrintWriter pw = new PrintWriter(new BufferedWriter(
new OutputSteamWriter(new FileOutputStream("a.txt"),"utf-8")),true);
3.打印流的三种输出方法
① void print(数据类型 变量)
② println(数据类型 变量) 提供换行,自动刷新
③ printf(String format, Object... args) 可以自定数据格式
JDK1.5之后Java对PrintStream进行了扩展,增加了格式化输出方式,可以使用printf()重载方法直接格式化输出。但是在格式化输出的时候需要指定输出的数据类型格式。
package cn.itzixue.sequenceinputstream; import java.io.File; import java.io.FilenameFilter; public class SuffixFilter implements FilenameFilter { private String suffix = null ; public SuffixFilter(String suffix) { this.suffix = suffix ; } public boolean accept(File dir, String name) { return name.endsWith(suffix); } }
package cn.itzixue.sequenceinputstream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
public class SplitFileDemo {
private static int SIZE = 1024*1024 ;
public static void main(String[] args) throws IOException {
File file = new File("F:"+File.separator+"1.mp3") ;
splitFile(file) ;
}
public static void splitFile(File file) throws IOException {
//用文件读取流关联源文件
FileInputStream fis = new FileInputStream(file) ;
//定义一个缓冲区
byte[] buf = new byte[SIZE ] ;
//定义目的位置
FileOutputStream fos = null ;
int len = 0 ;
//定义文件名序号,在创建文件时通过自增来使得文件切割之后分别存储与不同的文件中并且每一段文件通过序号排列
int count = 1 ;
//将切割所得文件存放的目录进行封装
File dir = new File("F:\\mp3part") ;
//健壮性判断
if(!dir.exists()){
//如果目录不存在则创建
dir.mkdirs() ;
}
//进行读写操作
while((len=fis.read(buf))!=-1){
//通过File类的构造方法将拼接好的目的位置传入FileOutputStream对象中
fos = new FileOutputStream(new File(dir,(count++)+".part")) ;
fos.write(buf, 0, len);
//关闭流操作
fos.close() ;
}
Properties prop = new Properties() ;
//将所切割文件的文件名和切割出来的碎片文件个数用键值对方式存储进Properties对象中
prop.setProperty("partcount", count+"") ;
prop.setProperty("filename", file.getName()) ;
//创建一个输出流对象关联被切割文件的配置文件,用于存储被切割文件的文件名以及碎片个数,便于以后进行合并
fos = new FileOutputStream(new File(dir,file.getName()+".properties")) ;
//将Properties对象中的信息存储到文件中进行持久化
prop.store(fos, "save file info") ;
fos.close() ;
fis.close() ;
}
}
对指定目录下的文件碎片根据配置文件信息进行合并:
package cn.itzixue.sequenceinputstream;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Set;
public class MergeFile {
public static void main(String[] args) throws IOException {
File dir = new File("F:"+File.separator+"mp3part") ;
mergeFile(dir) ;
}
public static void mergeFile(File dir) throws IOException {
//定义一个文件名过滤器,将配置文件过滤出来并存储于File对象数组中
File[] file = dir.listFiles(new SuffixFilter(".properties")) ;
//判断配置文件个数是否为一个,如果不是,则抛出异常停止运行程序
if(file.length!=1){
throw new RuntimeException(dir+"目录下缺少配置文件或者配置文件不唯一") ;
}
//将遍历到的配置文件封装成File类对象(由于配置文件只能有一个,所以只需要获取file[0]即可)
File confile = file[0] ;
FileInputStream fis = new FileInputStream(confile) ;
Properties prop = new Properties() ;
//将配置文件与Properties对象关联
prop.load(fis) ;
//将配置文件中的数据通过Properties对象的getProperty()方法通过取到相应的值
String filename = prop.getProperty("filename") ;
int num = Integer.parseInt(prop.getProperty("partcount")) ;
//通过自定义的文件名过滤器过滤出碎片文件,并存储于File对象数组中
File[] partFiles = dir.listFiles(new SuffixFilter(".part")) ;
//判断碎片文件个数是否正确,如果不是,则抛出异常停止运行程序
if(partFiles.length!=(--num)){
throw new RuntimeException("碎片文件数量不符合要求,应该为"+num+"个,请重新下载!!") ;
}
//创建一个ArrayList类对象,用于接受存放碎片文件
ArrayList a = new ArrayList() ;
//将指定目录下的碎片文件添加到集合中
for(int x=1;x en = Collections.enumeration(a) ;
//将所获得的集合枚举值传递给序列流对象
SequenceInputStream sis = new SequenceInputStream(en) ;
//创建文件合并的目的地
FileOutputStream fos = new FileOutputStream(new File(dir,"1-1.mp3")) ;
int len = 0 ;
byte[] buf = new byte[1024] ;
while((len=sis.read(buf))!=-1){
fos.write(buf, 0, len) ;
}
fos.close() ;
sis.close() ;
}
}
// 如果文件不存在,则创建,如果文件存在,不创建,所传入的"rw"是代表可使用的权限(r指可读;w指可写)
RandomAccessFile raf = new RandomAccessFile("A.txt" ,"rw" );
raf.write( " 张三 ".getBytes());
// 使用 write()方法之写入最后一个字节(即最低字节)
// 使用 writeInt()方法写入四个字节( int 类型)
raf.writeInt(97);
随机代码演示:
// 该方法可以返回当前指针位置
raf.getFilePointer() ;
// 可以通过seek()方法设置指针的位置(0*8只是一个演示,因为在此环境中两个中文四个字节,所传入的整数也是四个字节,所以一组数据总共有8个字节,该语句表示从0处插入)
raf.seek(0*8) ;
如果从0位置指针开始写入8个字节,会将原来8个字节数据覆盖,其他数据保持不变。