Java中的IO框架流三

1? ? ? IO(三)No20

1.1????Properties 屬性集

Properties屬性集,主要用于操作配置屬性,

是以鍵值對的方式來保存屬性,并且都是String類型

繼承自Hashtable類,所以是一個Map集合,具有Map接口中的所有方法,但是在保存和讀取數(shù)據(jù)的時候不建議使用put和get方法,因為有可能會出現(xiàn)異常,建議使用Properties中特有的方法進行數(shù)據(jù)的存儲

常用方法:

1、添加、獲取

setProperty(String key,String value):添加鍵值對

getProperty(String key):通過鍵獲取值《getProperty(Stringkey)

getProperty(Stringkey,StringdefaultValue)》如果鍵不存在返回默認值

2、保存、加載(配合IO流使用)

store():將數(shù)據(jù)通過輸出流寫到指定文件中

store(OutputStreamout,Stringcomments)

store(Writerwriter,Stringcomments)參數(shù)二:代表注釋

load():通過輸入流讀取指定文件中的數(shù)據(jù)

load(InputStreaminStream)load(Readerreader)

3、遍歷數(shù)據(jù)

list():將集合中的所有數(shù)據(jù)輸出到指定的流中(一般用于調(diào)試)

list(PrintStreamout)list(PrintWriterout)

stringPropertyNames():獲取集合中鍵的集合(鍵的類型是String類型)

1.1.1? 示例程序

publicclass Demo {

public static void main(String[] args)throws IOException {

Properties prop = newProperties();

/*

* Properties類繼承于Hashtable類,所以可以使用put方法添加鍵值對,

* 但是Properties類中的數(shù)據(jù)要求應該都是String類型,使用put方法返回可能會出問題

* 官方建議使用setProperty()方法添加鍵值對

*/

//?????????????? 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);

//將屬性保存到磁盤上

//Properties的作用是將數(shù)據(jù)持久化保存,實際上就是將數(shù)據(jù)保存在磁盤上

//?????????????? prop.save(out, comments);

FileOutputStream fos = new FileOutputStream("prop.properties");

prop.store(fos, "注釋");

//從磁盤上讀取屬性數(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集合的方式,通過keyset方法獲取鍵的集合,但是元素都是Object類型

//?????????????? prop2.keySet();

Set???? keyset = prop2.stringPropertyNames();

for (String key : keyset) {

String value =prop2.getProperty(key);

System.out.println(key+"..........."+value);

}

}

}

實例:寫一個程序,要求用戶只能打開5次,在第6次打開的時候就拋出異常提示“打開失敗”

publicclass Ex {

public static void main(String[] args){

System.out.println("程序開啟.......");

//檢測使用的次數(shù)

check();

System.out.println("程序正常運行.......");

System.out.println("程序結(jié)束.......");

}

private static void check() {

/*

* 思路:記錄用戶打開程序的次數(shù),每次打開的時候都記一次,將次數(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);

//通過鍵獲取值,如果鍵值對不存在,就返回指定的默認值

int count=Integer.parseInt(prop.getProperty("count","0"));

count ++;

//判斷打開的次數(shù)是否已經(jīng)超過了上限

if(count>5){

throw newRuntimeException("適用用次數(shù)已經(jīng)超過5次上限,請續(xù)費!.......");

}else{

//如果沒有超過

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();

}

}

}

}

}

1.2????內(nèi)存流

數(shù)組流

byte[] bytes ={97,98,99,100,101};//源字節(jié)數(shù)組

ByteArrayInputStream bais =//在源數(shù)組上創(chuàng)建一個內(nèi)存輸入流

newByteArrayInputStream(bytes);

int n=0;

byte[] buf = new byte[4];

//讀4個字節(jié)放到緩沖buf中,返回有效讀取數(shù)

while((n=bais.read(buf))!=-1){

for(int i=0;i

System.out.println(buf[i]);? //打印

}

}

}

//不需要關(guān)閉

//創(chuàng)建一個內(nèi)存輸出流,可以通過它向內(nèi)置的字節(jié)數(shù)組中寫字節(jié)

ByteArrayOutputStream baos=new ByteArrayOutputStream();

baos.write(65);//往內(nèi)置字節(jié)數(shù)組中寫一個字節(jié)

baos.write(66);

baos.write(67);

//從中拿出之前寫的字節(jié)生成的數(shù)組

byte[] array =baos.toByteArray();

for(byte b : array){//遍歷打印,用于驗證

System.out.println(b);

}

//源文件流

FileInputStream fis = newFileInputStream("g:/output.txt");

//目標內(nèi)存輸出流

ByteArrayOutputStream baos=new? ByteArrayOutputStream();

int n=0;

byte[] buf = new byte[4];//緩沖數(shù)組創(chuàng)建

//每次從文件讀4個字節(jié)方法緩沖中,有效字節(jié)數(shù)賦給n,和-1比較判斷是否讀完

while((n=fis.read(buf))!=-1){

baos.write(buf,0,n);?? //沒有讀完就將有效字節(jié)寫到內(nèi)存輸出流

}

fis.close();//需要關(guān)閉

//?????????????? baos.close();//不需要關(guān)閉

byte[]array=baos.toByteArray();?? //獲取字節(jié)數(shù)組

for (byte b : array) {//遍歷,驗證

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é)寫到內(nèi)存輸出流

}

fis.close();

byte[] array =baos.toByteArray(); //用寫進的字節(jié)生成數(shù)組

//準備從這個字節(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é)寫到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){//讀源文件只進行一次

baos.write(buf,0,n);

}

fis.close();

byte[] array =baos.toByteArray();

//把文件放到內(nèi)存中,這些動作不重復進行,這些動作包含了對磁盤的操作

//把內(nèi)存中的內(nèi)容拷貝到文件,重復進行

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é)點流、字節(jié)流

ByteArrayInputStream

ByteArrayOutputStream

構(gòu)造方法:

ByteArrayInputStream(byte[]bytes)創(chuàng)建一個內(nèi)存流,可以從參數(shù)字節(jié)數(shù)組中讀取字節(jié)

常用方法:

int read()

int read(byte[] buf)

不需要調(diào)用close()方法

構(gòu)造方法:

ByteArrayOutputStream()創(chuàng)建一個內(nèi)存輸出流,無參數(shù),可以往內(nèi)置的字節(jié)數(shù)組中寫字節(jié)

常用方法:

write(int b)

write(byte[] buf,intoff,int len)

不需要調(diào)用close()方法

toByteArray()獲得字節(jié)數(shù)組(之前寫到其中的字節(jié)組成的字節(jié)數(shù)組)

在文件小且不經(jīng)常變更的情況下,可以用內(nèi)存流先進行緩存,避免反復磁盤操作

實例:

public static void main(String[] args)throws IOException {

//字節(jié)數(shù)組輸出流

//是以數(shù)組作為數(shù)據(jù)源,將數(shù)據(jù)寫到數(shù)組中

//當數(shù)組輸出流被創(chuàng)建的時候內(nèi)部會自動創(chuàng)建一個數(shù)組

ByteArrayOutputStream baso =new ByteArrayOutputStream();

//將數(shù)據(jù)寫出到數(shù)組流內(nèi)部的數(shù)組(內(nèi)存)中

baso.write("強風125".getBytes());

//取出流中的字節(jié)數(shù)組

byte[]buf? =baso.toByteArray();

System.out.println(newString(buf));

//在這里因為操作的是內(nèi)存,所以不需要釋放存放

//?????????????? baso.close();

//使用場景:從網(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));

//如果一個數(shù)組中的數(shù)據(jù)比較多,需要分批讀取,那么使用數(shù)組流能簡化我們的代碼

//比如:現(xiàn)在有一個字節(jié)數(shù)組大小為1000,每次讀取300個字節(jié),自到將數(shù)據(jù)讀完

}

1.3????對象流

對象流是一種處理流、字節(jié)流

對象流

ObjectInputStream

readObject()

ObjectOutputStream

writeObject()

注意事項:

1、被對象流操作的對象必須先進行序列化(實現(xiàn)Serializable接口)

1)需要在類中定義一個靜態(tài)常量(序列值,static final longserialVersionUID)

2)在數(shù)據(jù)序列化的時候不會對靜態(tài)字段(static )和瞬態(tài)字段(transient)進行序列化

2、一個文件只能存儲一個對象

實例:

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)部自動進行了反序列化

Student stu =(Student)ois.readObject();

System.out.println(stu);

}

private static void writeObj() throwsIOException {

Student stu = new Student("小強", "男", 18);

//對象流,用于直接操作對象

FileOutputStream fos = newFileOutputStream("objdemo.object");

ObjectOutputStream oos = newObjectOutputStream(fos);

//將對象寫出到指定設備

//注意:對象流操作的對象必須進行序列化

//序列化:只需要實現(xiàn)Serializable

oos.writeObject(stu);

oos.close();

}

private static void test1() throwsIOException, FileNotFoundException {

Student stu = newStudent("小強","男", 18);

FileWriter fw?=? newFileWriter("object.txt");

fw.write(stu.name+"|");

fw.write(stu.gender+"|");

fw.write(stu.age +"");

fw.close();

//從磁盤上讀取對象的數(shù)據(jù)并生成對象

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/*標記接口*/{

/**

* 序列值,用于標記類的唯一性

* 如果沒有指定序列值,那么編譯器會自動根據(jù)類中的成員來自動生成一個序列值

* 建議:在序列化的時候最好要寫上序列值

*/

private static final long serialVersionUID= 10000L;

/**

* static 修飾的類成員不會被序列化

*/

String name;

String gender;

transient int age;???? //瞬態(tài)的(不會進行序列化)

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

+"]";

}

}

1.3.1? ObjectOutputStream

//文件的文件輸出流

FileOutputStream fos = newFileOutputStream("g:/obj");

//用對象輸出流去處理、裝飾fos文件輸出流

ObjectOutputStream oos = newObjectOutputStream(fos);

oos.writeObject("1000phone");//寫一個字符串對象到流中

oos.close();

//對象流裝飾文件流

ObjectOutputStream oos = newObjectOutputStream(

newFileOutputStream("g:/elephant"));

//初始化對象

Elephant mike = newElephant("Mike", 1000);

oos.writeObject(mike);??? //把大象塞進去

oos.close();

構(gòu)造方法:ObjectOutputStream(OutputStream os)參數(shù)是它要處理、裝飾的流,增加了寫對象的功能

writeObject(Objectobj)

1.3.2? ObjectInputStream

ObjectInputStream ois= //用對象流裝飾文件流

newObjectInputStream(new FileInputStream("g:/obj"));

String str =(String)ois.readObject();?? //讀一個對象

System.out.println("從obj文件中拿出來了:"+str);

ois.close();

ObjectInputStream ois= new ObjectInputStream(

newFileInputStream("g:/elephant"));

//把大象從流中拖出來,拿到的是Object類型,強轉(zhuǎn)為大象類型

Elephant e =(Elephant)ois.readObject();

System.out.println(e.getName()+"?? "+e.getWeight());

ois.close();

構(gòu)造方法:ObjectInputStream(InputStream is)參數(shù)是它要處理、裝飾的流,增加了讀對象的功能

Object readObject()

對象流讀寫,寫的和讀的類型一定要一致。

對象流讀寫的對象必須要可序列化,必須實現(xiàn)Serializable接口,這個接口無抽象方法。

用途:信息的存儲、信息在網(wǎng)絡上的傳遞、信息在組件間傳遞

1.4????輸出流(打印流)

PrintWriterpw = new PrintWriter(

newFileOutputStream("g:/answer.txt",true));

//由于構(gòu)造方法第二個參數(shù)為true ,println會自動刷緩存

pw.println("1000phone");//打印1000phone到文件中并換行

pw.println("Android");//打印android到文件中并換行

pw.println("java");//打印java到文件中并換行

pw.close();

PrintWriter輸出流、字符流、處理流

構(gòu)造方法:

PrintWriter(OutputStreamos,boolean autoFlush)第一個參數(shù)是所要裝飾的字節(jié)輸出流,第二個參數(shù)是表示是否自動刷緩存

PrintWriter(Writerwriter,boolean autoFlush)裝飾字符流

PrintWriter(Stringpath,String csn)在以第一個參數(shù)為路徑的文件上建立打印流,字符集由第二個參數(shù)指定

println()打印并且換行,在autoFlush為true時,會自動刷緩存

PrintStream用法和PrintWriter差不多,構(gòu)造方法少一點

實例

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();

}

1.5????數(shù)據(jù)流

DataOutputStream dos= //用數(shù)據(jù)流裝飾文件流

newDataOutputStream(new FileOutputStream("g:/answer.txt"));

dos.writeInt(101);//向數(shù)據(jù)流中寫100

dos.writeInt(100);

dos.writeInt(70);

dos.writeInt(66);

dos.close();//關(guān)閉處理會自動關(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é)輸出流,添加了寫基本類型數(shù)據(jù)的功能

writeInt(int i)

writeXXX(xxx i)

DataInputStream數(shù)據(jù)輸入流

DataInputStream(InputStreamis)構(gòu)造方法參數(shù)為它所裝飾的字節(jié)輸入流,添加了讀基本數(shù)據(jù)類型的功能

int readInt()

xxx readXXX()

實例:

publicstatic void main(String[] args) throws IOException {

//數(shù)據(jù)流(過濾流)

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.6????裝飾模式

裝飾模式:

1、把被裝飾者通過構(gòu)造方法傳入裝飾者

2、被裝飾者和裝飾者具有相同的方法(方法名、返回、參數(shù))、具有相同的接口或父類

3、被裝飾者以屬性的形式存在于裝飾者中

1.7????隨機訪問文件

RandomAccessFile raf= new RandomAccessFile("g:/answer.txt", "rw");

raf.write(65);//A|

raf.write(66);//AB|

raf.seek(0);//將游標一下子跳到第一個位置|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);? //游標放到最前

System.out.println(raf.read());

System.out.println(raf.read());

raf.close();

RandomAccessFile隨機訪問文件,不是InputStream、OutputStream、Reader、Writer中的任一個子類

RandomAcceessFile(Stringpath,String mode)

構(gòu)造方法第一個參數(shù)表示文件路徑,第二個參數(shù)打開模式,如果是"rw"表示可讀可寫,如果是"r"表示只讀

seek(int pos)定位,游標可以隨便向前向后跳,只要不超出范圍(Stream、Reader、Writer只能往后不能往前)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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

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