Java中的IO框架流三

1? ? ? IO(三)No20

1.1????Properties 屬性集

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

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

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

常用方法:

1、添加、獲取

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

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

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

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

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

store(OutputStreamout,Stringcomments)

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

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

load(InputStreaminStream)load(Readerreader)

3、遍歷數據

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

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類中的數據要求應該都是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的作用是將數據持久化保存,實際上就是將數據保存在磁盤上

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

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

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

//從磁盤上讀取屬性數據

Properties prop2 = newProperties();

FileInputStream fis = newFileInputStream("prop.properties");

prop2.load(fis);

System.out.println(prop2);

//遍歷Properties集合(是Map集合)

//list方法一般是用于調試用的

prop2.list(System.out);

//傳統的遍歷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("程序開啟.......");

//檢測使用的次數

check();

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

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

}

private static void check() {

/*

* 思路:記錄用戶打開程序的次數,每次打開的時候都記一次,將次數保存在配置文件中,

* 每次打開的時候讀取上一次記錄的次數,如果超出上限,就提示用戶

*/

//

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

//從文件中加載數據到Properties集合中

prop.load(fis);

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

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

count ++;

//判斷打開的次數是否已經超過了上限

if(count>5){

throw newRuntimeException("適用用次數已經超過5次上限,請續費!.......");

}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????內存流

數組流

byte[] bytes ={97,98,99,100,101};//源字節數組

ByteArrayInputStream bais =//在源數組上創建一個內存輸入流

newByteArrayInputStream(bytes);

int n=0;

byte[] buf = new byte[4];

//讀4個字節放到緩沖buf中,返回有效讀取數

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

for(int i=0;i

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

}

}

}

//不需要關閉

//創建一個內存輸出流,可以通過它向內置的字節數組中寫字節

ByteArrayOutputStream baos=new ByteArrayOutputStream();

baos.write(65);//往內置字節數組中寫一個字節

baos.write(66);

baos.write(67);

//從中拿出之前寫的字節生成的數組

byte[] array =baos.toByteArray();

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

System.out.println(b);

}

//源文件流

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

//目標內存輸出流

ByteArrayOutputStream baos=new? ByteArrayOutputStream();

int n=0;

byte[] buf = new byte[4];//緩沖數組創建

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

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

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

}

fis.close();//需要關閉

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

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

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字節,有效字節數賦值給n,和-1比較判斷是否結束

baos.write(buf, 0,n);//把有效字節寫到內存輸出流

}

fis.close();

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

//準備從這個字節數組中讀字節

ByteArrayInputStream bais =new ByteArrayInputStream(array);

FileOutputStream fos = newFileOutputStream("g:/copy.jar");

while ((n = bais.read(buf))!= -1) {//從數組讀1024字節,有效字節數賦給n,和-1比較

fos.write(buf, 0,n); //把有效字節寫到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();

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

//把內存中的內容拷貝到文件,重復進行

for(int i=1;i<=100;i++){

ByteArrayInputStreambais = new ByteArrayInputStream(array);

FileOutputStream fos= new FileOutputStream("g:/100/"+i+".jar");

//這里也要讀100次,但是每次都是讀內存數組,所以效率大大提高

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

fos.write(buf,0,n);

}

fos.close();

}

內存流(字節數組)節點流、字節流

ByteArrayInputStream

ByteArrayOutputStream

構造方法:

ByteArrayInputStream(byte[]bytes)創建一個內存流,可以從參數字節數組中讀取字節

常用方法:

int read()

int read(byte[] buf)

不需要調用close()方法

構造方法:

ByteArrayOutputStream()創建一個內存輸出流,無參數,可以往內置的字節數組中寫字節

常用方法:

write(int b)

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

不需要調用close()方法

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

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

實例:

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

//字節數組輸出流

//是以數組作為數據源,將數據寫到數組中

//當數組輸出流被創建的時候內部會自動創建一個數組

ByteArrayOutputStream baso =new ByteArrayOutputStream();

//將數據寫出到數組流內部的數組(內存)中

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

//取出流中的字節數組

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

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

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

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

//使用場景:從網上下載圖片并顯示在界面上

//從內存數組中去數據

ByteArrayInputStream bais =new ByteArrayInputStream(buf);

byte[] cubf? = new byte[1024];

bais.read(cubf);

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

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

//比如:現在有一個字節數組大小為1000,每次讀取300個字節,自到將數據讀完

}

1.3????對象流

對象流是一種處理流、字節流

對象流

ObjectInputStream

readObject()

ObjectOutputStream

writeObject()

注意事項:

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

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

2)在數據序列化的時候不會對靜態字段(static )和瞬態字段(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);

//內部自動進行了反序列化

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

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

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

//序列化:只需要實現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();

//從磁盤上讀取對象的數據并生成對象

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

/**

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

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

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

*/

private static final long serialVersionUID= 10000L;

/**

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

*/

String name;

String gender;

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

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

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

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類型,強轉為大象類型

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

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

ois.close();

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

Object readObject()

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

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

用途:信息的存儲、信息在網絡上的傳遞、信息在組件間傳遞

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

PrintWriterpw = new PrintWriter(

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

//由于構造方法第二個參數為true ,println會自動刷緩存

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

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

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

pw.close();

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

構造方法:

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

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

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

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

PrintStream用法和PrintWriter差不多,構造方法少一點

實例

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

// 打印流(只有輸出流)PrintStream(字節打印流)? 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????數據流

DataOutputStream dos= //用數據流裝飾文件流

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

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

dos.writeInt(100);

dos.writeInt(70);

dos.writeInt(66);

dos.close();//關閉處理會自動關閉所裝飾的流

DataInputStream dis =new DataInputStream(

new FileInputStream("g:/answer.txt"));

int a=dis.readInt();//用數據流裝飾文件流

System.out.println(a);

System.out.println(dis.readInt());//打印讀出的int數據

System.out.println(dis.readInt());

System.out.println(dis.readInt());

dis.close();

DataOutputStream數據輸出流,字節流、處理流

DataOutputStream(OutputStreamos)構造方法參數為它所裝飾的字節輸出流,添加了寫基本類型數據的功能

writeInt(int i)

writeXXX(xxx i)

DataInputStream數據輸入流

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

int readInt()

xxx readXXX()

實例:

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

//數據流(過濾流)

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

//讀取數據

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、把被裝飾者通過構造方法傳入裝飾者

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

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)

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

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,772評論 3 422
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,947評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,960評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,350評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,549評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,104評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,914評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,089評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,340評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,834評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,106評論 2 375

推薦閱讀更多精彩內容