1? ? ? IO(三)No20
【
Properties屬性集董栽,主要用于操作配置屬性椅野,
是以鍵值對(duì)的方式來(lái)保存屬性鸣峭,并且都是String類型
繼承自Hashtable類盆犁,所以是一個(gè)Map集合,具有Map接口中的所有方法,但是在保存和讀取數(shù)據(jù)的時(shí)候不建議使用put和get方法乙各,因?yàn)橛锌赡軙?huì)出現(xiàn)異常墨礁,建議使用Properties中特有的方法進(jìn)行數(shù)據(jù)的存儲(chǔ)
常用方法:
1、添加耳峦、獲取
setProperty(String key,String value):添加鍵值對(duì)
getProperty(String key):通過(guò)鍵獲取值《getProperty(Stringkey)
getProperty(Stringkey,StringdefaultValue)》如果鍵不存在返回默認(rèn)值
2恩静、保存、加載(配合IO流使用)
store():將數(shù)據(jù)通過(guò)輸出流寫(xiě)到指定文件中
《store(OutputStreamout,Stringcomments)
store(Writerwriter,Stringcomments)參數(shù)二:代表注釋》
load():通過(guò)輸入流讀取指定文件中的數(shù)據(jù)
《load(InputStreaminStream)load(Readerreader)》
3蹲坷、遍歷數(shù)據(jù)
list():將集合中的所有數(shù)據(jù)輸出到指定的流中(一般用于調(diào)試)
《list(PrintStreamout)list(PrintWriterout)》
stringPropertyNames():獲取集合中鍵的集合(鍵的類型是String類型)
】
【
publicclass Demo {
public static void main(String[] args)throws IOException {
Properties prop = newProperties();
/*
* Properties類繼承于Hashtable類驶乾,所以可以使用put方法添加鍵值對(duì),
* 但是Properties類中的數(shù)據(jù)要求應(yīng)該都是String類型循签,使用put方法返回可能會(huì)出問(wèn)題
* 官方建議使用setProperty()方法添加鍵值對(duì)
*/
//?????????????? prop.put("textsize",18);
//?????????????? prop.get("textsize");
//保存值
prop.setProperty("textsize","18");
prop.setProperty("textcolor","red");
//獲取值
String size =prop.getProperty("textsize");
String color=prop.getProperty("textcolor");
System.out.println(size);
System.out.println(color);
//將屬性保存到磁盤(pán)上
//Properties的作用是將數(shù)據(jù)持久化保存级乐,實(shí)際上就是將數(shù)據(jù)保存在磁盤(pán)上
//?????????????? prop.save(out, comments);
FileOutputStream fos = new FileOutputStream("prop.properties");
prop.store(fos, "注釋");
//從磁盤(pán)上讀取屬性數(shù)據(jù)
Properties prop2 = newProperties();
FileInputStream fis = newFileInputStream("prop.properties");
prop2.load(fis);
System.out.println(prop2);
//遍歷Properties集合(是Map集合)
//list方法一般是用于調(diào)試用的
prop2.list(System.out);
//傳統(tǒng)的遍歷Map集合的方式,通過(guò)keyset方法獲取鍵的集合县匠,但是元素都是Object類型
//?????????????? prop2.keySet();
Set???? keyset = prop2.stringPropertyNames();
for (String key : keyset) {
String value =prop2.getProperty(key);
System.out.println(key+"..........."+value);
}
}
}
實(shí)例:寫(xiě)一個(gè)程序风科,要求用戶只能打開(kāi)5次,在第6次打開(kāi)的時(shí)候就拋出異常提示“打開(kāi)失敗”
publicclass Ex {
public static void main(String[] args){
System.out.println("程序開(kāi)啟.......");
//檢測(cè)使用的次數(shù)
check();
System.out.println("程序正常運(yùn)行.......");
System.out.println("程序結(jié)束.......");
}
private static void check() {
/*
* 思路:記錄用戶打開(kāi)程序的次數(shù)聚唐,每次打開(kāi)的時(shí)候都記一次丐重,將次數(shù)保存在配置文件中,
* 每次打開(kāi)的時(shí)候讀取上一次記錄的次數(shù)杆查,如果超出上限,就提示用戶
*/
//
FileInputStream fis =null;
FileOutputStream fos = null;
try {
Properties prop =new Properties();
File file = newFile("prop_ex.properties");
//要保證文件存在
if(!file.exists()){
file.createNewFile();
}
fis = new FileInputStream(file);
//從文件中加載數(shù)據(jù)到Properties集合中
prop.load(fis);
//通過(guò)鍵獲取值臀蛛,如果鍵值對(duì)不存在亲桦,就返回指定的默認(rèn)值
int count=Integer.parseInt(prop.getProperty("count","0"));
count ++;
//判斷打開(kāi)的次數(shù)是否已經(jīng)超過(guò)了上限
if(count>5){
throw newRuntimeException("適用用次數(shù)已經(jīng)超過(guò)5次上限,請(qǐng)續(xù)費(fèi)浊仆!.......");
}else{
//如果沒(méi)有超過(guò)
fos = newFileOutputStream(file);
prop.setProperty("count",String.valueOf(count));
prop.store(fos,"open count");
}
} catch (IOException e) {
// TODO: handleexception
}finally{
if(fos != null){
try {
fos.close();
fos= null;
} catch(IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fis != null){
try {
fis.close();
fis= null;
} catch(IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
】
【
數(shù)組流
】
【
byte[] bytes ={97,98,99,100,101};//源字節(jié)數(shù)組
ByteArrayInputStream bais =//在源數(shù)組上創(chuàng)建一個(gè)內(nèi)存輸入流
newByteArrayInputStream(bytes);
int n=0;
byte[] buf = new byte[4];
//讀4個(gè)字節(jié)放到緩沖buf中客峭,返回有效讀取數(shù)
while((n=bais.read(buf))!=-1){
for(int i=0;i
System.out.println(buf[i]);? //打印
}
}
}
//不需要關(guān)閉
//創(chuàng)建一個(gè)內(nèi)存輸出流,可以通過(guò)它向內(nèi)置的字節(jié)數(shù)組中寫(xiě)字節(jié)
ByteArrayOutputStream baos=new ByteArrayOutputStream();
baos.write(65);//往內(nèi)置字節(jié)數(shù)組中寫(xiě)一個(gè)字節(jié)
baos.write(66);
baos.write(67);
//從中拿出之前寫(xiě)的字節(jié)生成的數(shù)組
byte[] array =baos.toByteArray();
for(byte b : array){//遍歷打印抡柿,用于驗(yàn)證
System.out.println(b);
}
//源文件流
FileInputStream fis = newFileInputStream("g:/output.txt");
//目標(biāo)內(nèi)存輸出流
ByteArrayOutputStream baos=new? ByteArrayOutputStream();
int n=0;
byte[] buf = new byte[4];//緩沖數(shù)組創(chuàng)建
//每次從文件讀4個(gè)字節(jié)方法緩沖中舔琅,有效字節(jié)數(shù)賦給n,和-1比較判斷是否讀完
while((n=fis.read(buf))!=-1){
baos.write(buf,0,n);?? //沒(méi)有讀完就將有效字節(jié)寫(xiě)到內(nèi)存輸出流
}
fis.close();//需要關(guān)閉
//?????????????? baos.close();//不需要關(guān)閉
byte[]array=baos.toByteArray();?? //獲取字節(jié)數(shù)組
for (byte b : array) {//遍歷,驗(yàn)證
System.out.println((char)b);
}
FileInputStream fis =new FileInputStream(
"g:/MySQL-connector-Java-5.1.7-bin.jar");
ByteArrayOutputStream baos =new ByteArrayOutputStream();
int n = 0;
byte[] buf = newbyte[1024];//緩沖
while ((n = fis.read(buf)) !=-1) {//從文件讀1024字節(jié)洲劣,有效字節(jié)數(shù)賦值給n,和-1比較判斷是否結(jié)束
baos.write(buf, 0,n);//把有效字節(jié)寫(xiě)到內(nèi)存輸出流
}
fis.close();
byte[] array =baos.toByteArray(); //用寫(xiě)進(jìn)的字節(jié)生成數(shù)組
//準(zhǔn)備從這個(gè)字節(jié)數(shù)組中讀字節(jié)
ByteArrayInputStream bais =new ByteArrayInputStream(array);
FileOutputStream fos = newFileOutputStream("g:/copy.jar");
while ((n = bais.read(buf))!= -1) {//從數(shù)組讀1024字節(jié)备蚓,有效字節(jié)數(shù)賦給n,和-1比較
fos.write(buf, 0,n); //把有效字節(jié)寫(xiě)到copy.jar
}
fos.close();
FileInputStream fis = newFileInputStream("g:/mysql-connector-java-5.1.7-bin.jar");
ByteArrayOutputStream baos=new ByteArrayOutputStream();
int n= 0;
byte[] buf = new byte[1024];
while((n=fis.read(buf))!=-1){//讀源文件只進(jìn)行一次
baos.write(buf,0,n);
}
fis.close();
byte[] array =baos.toByteArray();
//把文件放到內(nèi)存中,這些動(dòng)作不重復(fù)進(jìn)行囱稽,這些動(dòng)作包含了對(duì)磁盤(pán)的操作
//把內(nèi)存中的內(nèi)容拷貝到文件郊尝,重復(fù)進(jìn)行
for(int i=1;i<=100;i++){
ByteArrayInputStreambais = new ByteArrayInputStream(array);
FileOutputStream fos= new FileOutputStream("g:/100/"+i+".jar");
//這里也要讀100次,但是每次都是讀內(nèi)存數(shù)組战惊,所以效率大大提高
while((n=bais.read(buf))!=-1){
fos.write(buf,0,n);
}
fos.close();
}
】
內(nèi)存流(字節(jié)數(shù)組)節(jié)點(diǎn)流流昏、字節(jié)流
ByteArrayInputStream
ByteArrayOutputStream
構(gòu)造方法:
ByteArrayInputStream(byte[]bytes)創(chuàng)建一個(gè)內(nèi)存流,可以從參數(shù)字節(jié)數(shù)組中讀取字節(jié)
常用方法:
int read()
int read(byte[] buf)
不需要調(diào)用close()方法
構(gòu)造方法:
ByteArrayOutputStream()創(chuàng)建一個(gè)內(nèi)存輸出流,無(wú)參數(shù)况凉,可以往內(nèi)置的字節(jié)數(shù)組中寫(xiě)字節(jié)
常用方法:
write(int b)
write(byte[] buf,intoff,int len)
不需要調(diào)用close()方法
toByteArray()獲得字節(jié)數(shù)組(之前寫(xiě)到其中的字節(jié)組成的字節(jié)數(shù)組)
在文件小且不經(jīng)常變更的情況下谚鄙,可以用內(nèi)存流先進(jìn)行緩存,避免反復(fù)磁盤(pán)操作
實(shí)例:
【
public static void main(String[] args)throws IOException {
//字節(jié)數(shù)組輸出流
//是以數(shù)組作為數(shù)據(jù)源刁绒,將數(shù)據(jù)寫(xiě)到數(shù)組中
//當(dāng)數(shù)組輸出流被創(chuàng)建的時(shí)候內(nèi)部會(huì)自動(dòng)創(chuàng)建一個(gè)數(shù)組
ByteArrayOutputStream baso =new ByteArrayOutputStream();
//將數(shù)據(jù)寫(xiě)出到數(shù)組流內(nèi)部的數(shù)組(內(nèi)存)中
baso.write("強(qiáng)風(fēng)125".getBytes());
//取出流中的字節(jié)數(shù)組
byte[]buf? =baso.toByteArray();
System.out.println(newString(buf));
//在這里因?yàn)椴僮鞯氖莾?nèi)存闷营,所以不需要釋放存放
//?????????????? baso.close();
//使用場(chǎng)景:從網(wǎng)上下載圖片并顯示在界面上
//從內(nèi)存數(shù)組中去數(shù)據(jù)
ByteArrayInputStream bais =new ByteArrayInputStream(buf);
byte[] cubf? = new byte[1024];
bais.read(cubf);
System.out.println(newString(cubf));
//如果一個(gè)數(shù)組中的數(shù)據(jù)比較多,需要分批讀取膛锭,那么使用數(shù)組流能簡(jiǎn)化我們的代碼
//比如:現(xiàn)在有一個(gè)字節(jié)數(shù)組大小為1000粮坞,每次讀取300個(gè)字節(jié),自到將數(shù)據(jù)讀完
}
】
對(duì)象流是一種處理流初狰、字節(jié)流
【
對(duì)象流
ObjectInputStream
readObject()
ObjectOutputStream
writeObject()
注意事項(xiàng):
1莫杈、被對(duì)象流操作的對(duì)象必須先進(jìn)行序列化(實(shí)現(xiàn)Serializable接口)
1)需要在類中定義一個(gè)靜態(tài)常量(序列值,static final longserialVersionUID)
2)在數(shù)據(jù)序列化的時(shí)候不會(huì)對(duì)靜態(tài)字段(static )和瞬態(tài)字段(transient)進(jìn)行序列化
2奢入、一個(gè)文件只能存儲(chǔ)一個(gè)對(duì)象
】
實(shí)例:
【
publicclass Demo {
public static void main(String[] args)throws IOException, ClassNotFoundException {
//?????????????? test1();
//?????????????? writeObj();
readObj();
}
private static void readObj() throwsIOException, ClassNotFoundException {
FileInputStream fis = newFileInputStream("objdemo.object");
ObjectInputStream ois = new ObjectInputStream(fis);
//內(nèi)部自動(dòng)進(jìn)行了反序列化
Student stu =(Student)ois.readObject();
System.out.println(stu);
}
private static void writeObj() throwsIOException {
Student stu = new Student("小強(qiáng)", "男", 18);
//對(duì)象流筝闹,用于直接操作對(duì)象
FileOutputStream fos = newFileOutputStream("objdemo.object");
ObjectOutputStream oos = newObjectOutputStream(fos);
//將對(duì)象寫(xiě)出到指定設(shè)備
//注意:對(duì)象流操作的對(duì)象必須進(jìn)行序列化
//序列化:只需要實(shí)現(xiàn)Serializable
oos.writeObject(stu);
oos.close();
}
private static void test1() throwsIOException, FileNotFoundException {
Student stu = newStudent("小強(qiáng)","男", 18);
FileWriter fw?=? newFileWriter("object.txt");
fw.write(stu.name+"|");
fw.write(stu.gender+"|");
fw.write(stu.age +"");
fw.close();
//從磁盤(pán)上讀取對(duì)象的數(shù)據(jù)并生成對(duì)象
BufferedReader br = new BufferedReader(newFileReader("object.txt"));
String line = br.readLine();
String[] strs = line.split("\\|");
String name = strs[0];
String gender = strs[1];
int age = Integer.parseInt(strs[2]);
Student stu2 = new Student(name, gender, age);
System.out.println(stu2);
}
}
classStudent implements Serializable/*標(biāo)記接口*/{
/**
* 序列值,用于標(biāo)記類的唯一性
* 如果沒(méi)有指定序列值腥光,那么編譯器會(huì)自動(dòng)根據(jù)類中的成員來(lái)自動(dòng)生成一個(gè)序列值
* 建議:在序列化的時(shí)候最好要寫(xiě)上序列值
*/
private static final long serialVersionUID= 10000L;
/**
* static 修飾的類成員不會(huì)被序列化
*/
String name;
String gender;
transient int age;???? //瞬態(tài)的(不會(huì)進(jìn)行序列化)
public Student(String name, Stringgender, int age) {
this.name = name;
this.gender = gender;
this.age = age;
}
@Override
public String toString() {
return "Student[name=" + name + ", gender=" + gender + ", age=" + age
+"]";
}
}
】
【
//文件的文件輸出流
FileOutputStream fos = newFileOutputStream("g:/obj");
//用對(duì)象輸出流去處理关顷、裝飾fos文件輸出流
ObjectOutputStream oos = newObjectOutputStream(fos);
oos.writeObject("1000phone");//寫(xiě)一個(gè)字符串對(duì)象到流中
oos.close();
//對(duì)象流裝飾文件流
ObjectOutputStream oos = newObjectOutputStream(
newFileOutputStream("g:/elephant"));
//初始化對(duì)象
Elephant mike = newElephant("Mike", 1000);
oos.writeObject(mike);??? //把大象塞進(jìn)去
oos.close();
】
構(gòu)造方法:ObjectOutputStream(OutputStream os)參數(shù)是它要處理、裝飾的流武福,增加了寫(xiě)對(duì)象的功能
writeObject(Objectobj)
【
ObjectInputStream ois= //用對(duì)象流裝飾文件流
newObjectInputStream(new FileInputStream("g:/obj"));
String str =(String)ois.readObject();?? //讀一個(gè)對(duì)象
System.out.println("從obj文件中拿出來(lái)了:"+str);
ois.close();
ObjectInputStream ois= new ObjectInputStream(
newFileInputStream("g:/elephant"));
//把大象從流中拖出來(lái)议双,拿到的是Object類型,強(qiáng)轉(zhuǎn)為大象類型
Elephant e =(Elephant)ois.readObject();
System.out.println(e.getName()+"?? "+e.getWeight());
ois.close();
】
構(gòu)造方法:ObjectInputStream(InputStream is)參數(shù)是它要處理捉片、裝飾的流平痰,增加了讀對(duì)象的功能
Object readObject()
對(duì)象流讀寫(xiě),寫(xiě)的和讀的類型一定要一致伍纫。
對(duì)象流讀寫(xiě)的對(duì)象必須要可序列化宗雇,必須實(shí)現(xiàn)Serializable接口,這個(gè)接口無(wú)抽象方法莹规。
用途:信息的存儲(chǔ)赔蒲、信息在網(wǎng)絡(luò)上的傳遞、信息在組件間傳遞
【
PrintWriterpw = new PrintWriter(
newFileOutputStream("g:/answer.txt",true));
//由于構(gòu)造方法第二個(gè)參數(shù)為true ,println會(huì)自動(dòng)刷緩存
pw.println("1000phone");//打印1000phone到文件中并換行
pw.println("Android");//打印android到文件中并換行
pw.println("java");//打印java到文件中并換行
pw.close();
】
PrintWriter輸出流良漱、字符流舞虱、處理流
構(gòu)造方法:
PrintWriter(OutputStreamos,boolean autoFlush)第一個(gè)參數(shù)是所要裝飾的字節(jié)輸出流,第二個(gè)參數(shù)是表示是否自動(dòng)刷緩存
PrintWriter(Writerwriter,boolean autoFlush)裝飾字符流
PrintWriter(Stringpath债热,String csn)在以第一個(gè)參數(shù)為路徑的文件上建立打印流砾嫉,字符集由第二個(gè)參數(shù)指定
println()打印并且換行,在autoFlush為true時(shí)窒篱,會(huì)自動(dòng)刷緩存
PrintStream用法和PrintWriter差不多焕刮,構(gòu)造方法少一點(diǎn)
實(shí)例
【
publicstatic void main(String[] args) throws IOException {
// 打印流(只有輸出流)PrintStream(字節(jié)打印流)? PrintWriter (字符打印流)
//?????????????? PrintStream ps = new PrintStream(newFileOutputStream("print.txt"));
PrintStream ps = newPrintStream("print.txt");
/*ps.print(true);
ps.print("中");
ps.print("f");*/
ps.print(18);??? //編碼
ps.write(97);??? //字面值
ps.close();
}
】
【
DataOutputStream dos= //用數(shù)據(jù)流裝飾文件流
newDataOutputStream(new FileOutputStream("g:/answer.txt"));
dos.writeInt(101);//向數(shù)據(jù)流中寫(xiě)100
dos.writeInt(100);
dos.writeInt(70);
dos.writeInt(66);
dos.close();//關(guān)閉處理會(huì)自動(dòng)關(guān)閉所裝飾的流
DataInputStream dis =new DataInputStream(
new FileInputStream("g:/answer.txt"));
int a=dis.readInt();//用數(shù)據(jù)流裝飾文件流
System.out.println(a);
System.out.println(dis.readInt());//打印讀出的int數(shù)據(jù)
System.out.println(dis.readInt());
System.out.println(dis.readInt());
dis.close();
】
DataOutputStream數(shù)據(jù)輸出流舶沿,字節(jié)流、處理流
DataOutputStream(OutputStreamos)構(gòu)造方法參數(shù)為它所裝飾的字節(jié)輸出流配并,添加了寫(xiě)基本類型數(shù)據(jù)的功能
writeInt(int i)
writeXXX(xxx i)
DataInputStream數(shù)據(jù)輸入流
DataInputStream(InputStreamis)構(gòu)造方法參數(shù)為它所裝飾的字節(jié)輸入流括荡,添加了讀基本數(shù)據(jù)類型的功能
int readInt()
xxx readXXX()
實(shí)例:
【
publicstatic void main(String[] args) throws IOException {
//數(shù)據(jù)流(過(guò)濾流)
FileOutputStream fos = newFileOutputStream("data.txt");
DataOutputStream oos = newDataOutputStream(fos);
oos.writeByte(100);
oos.writeChar('中');
oos.writeShort(1000);
oos.writeInt(1022);
oos.writeLong(12025);
oos.writeFloat(12.2f);
oos.writeDouble(15.4524);
oos.writeBoolean(true);
oos.close();
//讀取數(shù)據(jù)
FileInputStream fis = new FileInputStream("data.txt");
DataInputStream dis = new DataInputStream(fis);
System.out.println(dis.readByte());
System.out.println(dis.readChar());
System.out.println(dis.readShort());
System.out.println(dis.readInt());
System.out.println(dis.readLong());
System.out.println(dis.readFloat());
System.out.println(dis.readDouble());
dis.close();
}
】
裝飾模式:
1、把被裝飾者通過(guò)構(gòu)造方法傳入裝飾者
2溉旋、被裝飾者和裝飾者具有相同的方法(方法名畸冲、返回、參數(shù))观腊、具有相同的接口或父類
3邑闲、被裝飾者以屬性的形式存在于裝飾者中
【
RandomAccessFile raf= new RandomAccessFile("g:/answer.txt", "rw");
raf.write(65);//A|
raf.write(66);//AB|
raf.seek(0);//將游標(biāo)一下子跳到第一個(gè)位置|AB
raf.write(67);
raf.write(68);
raf.close();
RandomAccessFile raf=new RandomAccessFile("g:/answer.txt", "r");
System.out.println(raf.read());
System.out.println(raf.read());
raf.seek(0);? //游標(biāo)放到最前
System.out.println(raf.read());
System.out.println(raf.read());
raf.close();
】
RandomAccessFile隨機(jī)訪問(wèn)文件,不是InputStream梧油、OutputStream苫耸、Reader、Writer中的任一個(gè)子類
RandomAcceessFile(Stringpath,String mode)
構(gòu)造方法第一個(gè)參數(shù)表示文件路徑儡陨,第二個(gè)參數(shù)打開(kāi)模式,如果是"rw"表示可讀可寫(xiě)蒜哀,如果是"r"表示只讀
seek(int pos)定位班挖,游標(biāo)可以隨便向前向后跳,只要不超出范圍(Stream或辖、Reader牡直、Writer只能往后不能往前)