引言
在上一篇中提到了IO流中的位元組流和字元流的相關概念,那麼,在這個部分,主要說明其它相關IO流的知識。
LineNumberReader類:
跟蹤行号的緩沖字元輸入流,此類定義了方法 setLineNumber(int) 和 getLineNumber(),它們可分别用于設定和擷取目前行号。
String readLine():讀取一行
做一個簡單的案例進行了解:
案例:讀取檔案,每次讀取一行列印并且加上行号
package com.stu_02;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
/*
案例:讀取檔案,每次讀取一行列印并且加上行号
*/
public class LineNumberReaderStu {
public static void main(String[] args) throws IOException {
//建立跟蹤行号的字元緩沖輸入流
LineNumberReader lnr = new LineNumberReader(new FileReader("prop1.txt"));
// public void setLineNumber(int lineNumber):設定起始行号
lnr.setLineNumber();
String line;
//周遊
while ((line=lnr.readLine())!=null) {
//擷取行号和内容
System.out.println(lnr.getLineNumber()+" "+line);
}
//關流
lnr.close();
}
}
編譯運作結果如下:
11 #Sat May 13 16:41:42 CST 2017
12 zhangsan=10
13 lisi=100
14 wangwu=4
操作基本資料類型的流
可以操作基本類型的流對象。
DataInputStream:讀資料
DataOutputStream:寫資料
注意:
讀寫順序必須一緻,否則資料有問題。
記憶體操作流:
解決臨時資料存儲的問題。
操作位元組數組
ByteArrayInputStream
ByteArrayOutputStream
byte[] toByteArray() 将之前寫入記憶體的流轉換成位元組數組
操作字元數組
CharArrayReader
CharArrayWrite
操作字元串
StringReader
StringWriter
将資料寫到流中儲存在記憶體,并且讀取,在這裡,用一個操作字元數組做一解釋說明:
package com.stu_04;
import java.io.CharArrayReader;
import java.io.CharArrayWriter;
import java.io.IOException;
/*
* 操作字元數組
CharArrayReader
CharArrayWrite
*/
public class CharArrayReaderStu {
public static void main(String[] args) throws IOException {
//給記憶體中寫資料
CharArrayWriter caw = new CharArrayWriter();
caw.write();
//将記憶體中的資料讀出來
char[] ch=caw.toCharArray();
int len;
CharArrayReader car = new CharArrayReader(ch);
while ((len=car.read())!=-) {
System.out.println((char)len);
}
//關流
caw.close();
car.close();
}
}
編譯運作結果如下:
c
列印流
位元組列印流 PrintStream
字元列印流 PrintWriter
特點:
A:隻能操作目的地,不能操作資料源
B:可以操作任意類型的資料
C:如果啟動了自動重新整理,能夠自動重新整理
D:可以操作檔案的流
注意:什麼流可以直接操作檔案?
看流對象的API,如果其構造方法同時有File和String類型的參數,就可以直接操作檔案。
如何啟動自動重新整理:利用構造
PrintWriter(OutputStream out, boolean autoFlush)
PrintWriter(Writer out, boolean autoFlush)
注意:如果啟動了自動重新整理,就要使用println、printf 或 format的時候,才可以實作自動重新整理
啟動自動重新整理可以實作三個功能:1.寫資料 2.換行 3.重新整理
同樣的,用一個簡單的案例來了解:
利用字元流給檔案中寫資料(int類型,boolean類型),啟動自動重新整理
package com.stu_05;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
//利用字元流給檔案中寫資料(int類型,boolean類型),啟動自動重新整理
public class PrintWriterStu02 {
public static void main(String[] args) throws IOException {
//建立列印字元流對象
PrintWriter pw = new PrintWriter(new FileWriter("c.txt"),true);
//寫資料(寫資料、換行、重新整理)
pw.println();
pw.println(false);
//關流
pw.close();
}
}
編譯運作後會在命名為c.txt的文本文檔下看到如下内容:
20
false
标準輸入輸出流
System類下有這樣的兩個成員變量:
标準輸入流:
public static final InputStream in
标準輸出流:
public static final PrintStream out
合并流
SequenceInputStream類可以将多個輸入流串流在一起,合并為一個輸入流,是以,該流也被稱為合并流。
構造:
SequenceInputStream(InputStream s1, InputStream s2) :将s1和s2合并成一個輸入流,先讀取s1後讀取s2
利用該方法可以将兩個java檔案合并為一個java檔案
對象的序列化和反序列化
序列化流:把對象按照流一樣的方式寫到檔案或者在網絡中傳輸。
反序列化流:把檔案或者網絡中的流對象資料還原對象。
ObjectOutputStream:序列化流
writeObject(Object obj) 将指定的對象寫入 ObjectOutputStream。
ObjectInputStream:反序列化流
Object readObject() 從 ObjectInputStream 讀取對象。
注意:如果一個類不是實作Serializable接口無法把執行個體化,會報異常java.io.NotSerializableException
類通過實作 java.io.Serializable 接口以啟用其序列化功能。未實作此接口的類将無法使其任何狀态序列化或反序列化。
如何實作序列化?
讓對象所屬類的實作序列化接口。
舉一個簡單的例子來證明上面所說:
//建立學生對象
package com.stu_07;
import java.io.Serializable;
public class Student implements Serializable{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
}
//序列化流
package com.stu_07;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class ObjectOutputStreamStu {
public static void main(String[] args) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));
Student s = new Student("薛之謙", );
//将對象寫入序列化流中
oos.writeObject(s);
//關流
oos.close();
}
}
//反序列化流
package com.stu_07;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ObjectInputStreamStu {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));
Object object = ois.readObject();
System.out.println(object);
ois.close();
}
}
編譯運作後在oos.txt中會出現如下内容:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0NXYFhGd192UvwVe0lmdhJ3ZvwFM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2Lc1TPnNma1clWwhnMjZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39zN3MDOxQjMxEjNxUDM3EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
運作後在控制台輸出入下:
Student [name=薛之謙, age=35]
Properties(檢視api實作map接口本質是一個map集合)
Properties:Properties 類表示了一個持久的屬性集。屬性清單中每個鍵及其對應值都是一個字元串。
特點:Properties 可儲存在流中或從流中加載。
Properties的特有功能:
A:添加元素
public Object setProperty(String key,String value)
B:擷取元素
public String getProperty(String key)
public Set stringPropertyNames()
可以和IO流進行結合使用:
把檔案中的資料加載到集合中。注意:檔案中的資料必須是鍵值對象形式的(例如:張傑=謝娜)。
public void load(InputStream inStream): 從輸入流中讀取屬性清單(鍵和元素對)。
public void load(Reader reader):按簡單的面向行的格式從輸入字元流中讀取屬性清單(鍵和元素對)。
把集合中的資料存儲到文本檔案中,并且是按照鍵值對形式存儲的。
public void store(OutputStream out,String comments): 以适合使用 load(InputStream) 方法加載到 Properties 表中的格式,将此 Properties 表中的屬性清單(鍵和元素對)寫入輸出流。
public void store(Writer writer,String comments): 以适合使用 load(Reader) 方法的格式,将此 Properties 表中的屬性清單(鍵和元素對)寫入輸出字元。
結合上面所述,做一個簡單的案例進行了解:
我有一個猜數字小遊戲的程式,請寫一個程式實作在測試類中隻能用5次,超過5次提示:遊戲試玩已結束,請付費
//猜數字代碼
package com.stu_09;
import java.util.Scanner;
public class GuessNumber {
public static void playGame(){
int ran=(int) (Math.random()*+);
Scanner sc=new Scanner(System.in);
while(true){
System.out.println("請輸入你猜的數字:");
int number =sc.nextInt();
if(number<ran){
System.out.println("猜小了,請重新輸入:");
}else if(number>ran){
System.out.println("猜大了,請重新輸入:");
}else if(number==ran){
System.out.println("恭喜你,猜對了!");
break;
}
}
}
}
//測試代碼
package com.stu_09;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
/*
*我有一個猜數字小遊戲的程式,請寫一個程式實作在測試類中隻能用5次,
超過5次提示:遊戲試玩已結束,請付費
*/
public class Test {
public static void main(String[] args) throws IOException {
Properties prop = new Properties();
//将檔案中的資料加載到集合中
prop.load(new FileReader("count.txt"));
//用指定的鍵在屬性清單中搜尋屬性。
String string = prop.getProperty("count");
//轉換成int類型
int number=Integer.parseInt(string);
//進行判斷
if(number>){
System.out.println("次數已到5次,請付費");
}else{
GuessNumber.playGame();
number++;
//将改變後的鍵值對重新存儲到集合中去
prop.setProperty("count", number+"");
//将改變後的鍵值對存儲到檔案中
prop.store(new FileWriter("count.txt"),null);
}
}
}
每一次玩一次遊戲周,我們可以在count.txt中看到鍵值對的變化,如下:
第一次:
第二次:
第三次:
第四次:
第五次:
當猜完五次之後,第六次運作,在控制台會輸出:
次數已到5次,請付費