Java基礎---I/O流--序列流+PrintStream+轉換流+Serializable+Properties
阿新 • • 發佈:2018-12-12
一、序列流
SequenceInputStream (序列流) : 可以把多個輸入流串聯起來讀取,先從第一個開始i讀取,然後再下一個....
方式一:只合並兩個流
public SequenceInputStream(InputStream s1,InputStream s2)
將按順序讀取這兩個引數,先讀取 s1 然後讀取 s2
引數:兩個輸入流
// 方式一:合併兩個檔案 public static void merge1() throws IOException { // 找到目標檔案物件 File inFile1 = new File("g:\\a.txt"); File inFile2 = new File("g:\\b.txt"); File outFile = new File("g:\\s.txt"); // 第二步:建立資料的輸入輸出通道 FileOutputStream fileOutputStream = new FileOutputStream(outFile); // 建立資料的輸入輸出通道 FileInputStream fileInputStream1 = new FileInputStream(inFile1); fileInputStream2 = new FileInputStream(inFile2); // 建立序列流物件 SequenceInputStream sequenceInputStream = new SequenceInputStream(fileInputStream1, fileInputStream2); // 邊讀邊寫 byte[] buf = new byte[1024]; int length = 0; while ((length = sequenceInputStream.read(buf)) != -1) { fileOutputStream.write(buf, 0, length); } // 關閉資源 sequenceInputStream.close(); fileOutputStream.close(); }
方式二:合併多個流 (重點是構造迭代器)
public SequenceInputStream(Enumeration<? extends InputStream> e)
將按順序讀取由該列舉生成的輸入流,呼叫該流的 close 方法將其關閉
引數:必須是InputStream物件的Enumeration型引數
// 把三個檔案合併成一個。 public static void merge2() throws IOException { // 找到目標檔案物件 File inFile1 = new File("g:\\a.txt"); File inFile2 = new File("g:\\b.txt"); File inFile3 = new File("g:\\c.txt"); File outFile = new File("g:\\s.txt"); // 建立資料的輸入輸出通道 FileOutputStream fileOutputStream = new FileOutputStream(outFile); FileInputStream fileInputStream1 = new FileInputStream(inFile1); FileInputStream fileInputStream2 = new FileInputStream(inFile2); FileInputStream fileInputStream3 = new FileInputStream(inFile3); // 通過Vector得到一個迭代器。 Vector<FileInputStream> v = new Vector<FileInputStream>(); v.add(fileInputStream1); v.add(fileInputStream2); v.add(fileInputStream3); Enumeration<FileInputStream> e = v.elements(); // 建立一個序列流物件 SequenceInputStream inputStream = new SequenceInputStream(e); // 建立緩衝陣列,邊讀邊寫 byte[] buf = new byte[1024]; int length = 0; while ((length = inputStream.read(buf)) != -1) { fileOutputStream.write(buf, 0, length); } // 關閉資源 inputStream.close(); fileOutputStream.close(); }
應用:MP3檔案的切割與合併
//檔案切割與合併 public class SequenceInputStream2 { public static void main(String[] args) throws IOException { //cutFile(); mergeFile(); } // 切割mp3檔案 public static void cutFile() throws IOException { File file = new File("g:/1.mp3"); FileInputStream fileInputStream = new FileInputStream(file); byte[] buf = new byte[1024 * 1024]; int length = 0; int count = 1; while ((length = fileInputStream.read(buf)) != -1) { // 每讀取一次,則生成一個檔案 注意檔案路徑的設定 FileOutputStream fileOutputStream = new FileOutputStream("g:/music/" + count + ".mp3"); // 把讀取到的資料寫出 fileOutputStream.write(buf, 0, length); count++; // 關閉資源 fileOutputStream.close(); } // 關閉資源 fileInputStream.close(); } // 合併mp3檔案 public static void mergeFile() throws IOException { // 資料夾路徑 File dir = new File("g:/music"); // 獲取到資料夾中的所有子檔案 File[] files = dir.listFiles(); // 建立一個Vector物件儲存FileInputStream物件 Vector<FileInputStream> vector = new Vector<FileInputStream>(); // 遍歷陣列,新增到集合 for (int i = 0; i < files.length; i++) { if (files[i].getName().endsWith(".mp3")) { vector.add(new FileInputStream(files[i])); } } // 建立一個序列流物件 SequenceInputStream inputStream = new SequenceInputStream(vector.elements()); // 建立一個輸出流物件 FileOutputStream fileOutputStream = new FileOutputStream("g:/合併.mp3"); // 邊讀邊寫 byte[] buf = new byte[1024]; int length = 0; while ((length = inputStream.read(buf)) != -1) { fileOutputStream.write(buf, 0, length); } // 關閉資源 fileOutputStream.close(); inputStream.close(); }
二、物件輸入輸出流
ObjectOutputStream(物件的輸出流類): 把 物件資料 寫出到硬碟檔案上 序列化
ObjectInputStream(物件的輸入流類): 把 硬碟中的 物件資料 讀取回來 反序列化
Serializable介面 沒有任何方法,這種介面稱作為標識介面
serialVersionUID版本號 :通過類名、包名、工程名、成員一起計算得出的id號
序列反序列注意:
1.ObjectOutputStream的writeObject方法只能寫出實現了Serializable介面的物件
2.物件反序列化建立物件時是不會呼叫構造方法。
3.把物件寫到檔案上時,檔案記錄物件資訊,還記錄class的版本號(serialVersionUID)
4.反序列化時,jvm使用本地class檔案算出一個id號與檔案記錄的id號進行對比,如果不一致,反序列化失敗。
5.如果一個類的成員可能在後期會發生改動,那麼可以在序列化之前就指定一個serialVersionUID , 如果一個類一家指定了一個serialVersionUID那麼java虛擬機器則不會再計算該class檔案的serialVersionUID了。
6.果一個類的某些成員不想被序列化到硬碟上,可以使用關鍵字transient修飾。
7.一個類的內部維 護了另外一個類物件,則另外一個類也必須要實現Serializable介面
//使用者類
class User implements Serializable {
// 提前生成一個serialVersionUID
private static final long serialVersionUID = -4964722333163184880L;
String name;
String password;
transient int age; // transient 透明
public User(String name, String password, int age) {
this.name = name;
this.password = password;
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", password=" + password + ", age=" + age + "]";
}
}
public class Serializable1 {
private static ObjectInputStream inputStream;
public static void main(String[] args) throws Exception {
writeObj();
readObj();
}
// 把物件寫到檔案上------>物件的序列化。
public static void writeObj() throws IOException {
User user = new User("chao", "ttt", 16);
// 找到目標
File file = new File("g:/obj.txt");
// 建立資料的輸出通道
FileOutputStream fileOutputStream = new FileOutputStream(file);
// 建立物件的輸出流物件
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
// 把物件寫出到輸出流中
objectOutputStream.writeObject(user);
// 關閉資源
objectOutputStream.close();
}
// 物件的反序列化-----> 讀取硬碟中的物件到記憶體中。
public static void readObj() throws Exception {
// 找到目標檔案
File file = new File("g:/obj.txt");
// 建立資料的輸入流物件
FileInputStream fileInputStream = new FileInputStream(file);
inputStream = new ObjectInputStream(fileInputStream);
// 讀取物件的資料
// 反序列化的時候需要建立物件,建立物件需要依賴:Class檔案
User user = (User) inputStream.readObject();
// 測試檢視
System.out.println("物件的資訊:" + user);
}
}
Properties配置檔案類 (屬於Map集合體系)
作用:
1. 生成配置檔案
2. 讀取配置
注意:
1.新增資料時不要新增非字串型別的資料,否則強轉報錯
2.新增中文字元資料,使用store方法時,使用字元流
3.修改了properties裡面的資料,一定要重新生成一個配置檔案
4.properties.setProperty(String key,String value)設定值或修改值(map)
5.保證鍵值對為字串型別的資料
6.properties.store(OutputStream out,String comments); comments:描述隨便寫
store()方法寫入硬碟
7.載入:載入配置檔案到Properties使用load方法
Properties建立+修改+讀取配置檔案
public class Properties1 {
public static void main(String[] args) throws IOException {
createProperties();
readProperties();
}
// 建立一個配置檔案
public static void createProperties() throws IOException {
// 建立一個Properties物件
Properties properties = new Properties();
properties.setProperty("迪迦", "1234");
properties.setProperty("奧特曼", "2345");
properties.setProperty("abc", "4567");
// 當存非中文資料時用位元組流
// FileOutputStream fileOutputStream = new
// FileOutputStream("g:/users.properties");
FileWriter fileWriter = new FileWriter("g:/users.properties");
// 利用Properties生成一個配置檔案。
properties.store(fileWriter, "jinchao94"); // 第二個引數是使用一段文字對引數列表進行描述。
}
// 讀取配置檔案 ---- 載入配置檔案到Properties是使用load方法。
public static void readProperties() throws IOException {
// 建立一個Properties
Properties properties = new Properties();
// 建立輸入字元流物件
FileReader fileReader = new FileReader("g:/users.properties");
// 載入配置檔案的資料到Properties是使用load方法。
properties.load(fileReader);
// 遍歷元素
Set<Entry<Object, Object>> set = properties.entrySet();
for (Entry<Object, Object> entry : set) {
System.out.println("鍵:" + entry.getKey() + " 值:" + entry.getValue());
}
// 修改奧特曼...
properties.setProperty("奧特曼", "110");
// 重新生成一個配置檔案
properties.store(new FileWriter("g:/users.properties"), "jinchao94");
}
}
Properties應用:正版軟體:只能試用三次,三次之後提示購買正版並退出
public class Properties2 {
public static void main(String[] args) throws IOException {
// 先檢查是否存在配置檔案
File file = new File("g:/usetime.properties");
if (!file.exists()) {
// ,如果不存在,建立配置檔案
file.createNewFile();
}
// 建立一個Properties物件
Properties properties = new Properties();
// 載入配置檔案
properties.load(new FileReader(file));
// 定義一個變數記錄執行的次數
int count = 0;
// 如果配置檔案記錄了執行次數,則應該使用配置檔案的執行次數
String num = properties.getProperty("num");
if (num != null) {
count = Integer.parseInt(num);
}
// 判斷是否已經運行了三次
if (count == 3) {
System.out.println("達到限制次數,請購買正版!!");
System.exit(0);
}
count++;
properties.setProperty("num", count + "");
// count+""將count轉換成字串格式(自動)
System.out.println("軟體已使用" + count + "次,還剩餘" + (3 - count) + "次");
// 重新生成配置檔案
properties.store(new FileWriter(file), "runtime");
}
}
PrintStream 列印(輸出)流:
列印流的好處:
1. 列印流可以列印任意型別的資料。
2. 列印流列印任意型別資料之前,會先把資料轉成字串然後再列印輸出
3. 原樣輸出
// 作用一:列印任意型別的資料
public static void function1() throws FileNotFoundException {
// 找到目標檔案
File file = new File("g:/c.txt");
// 建立列印流物件
PrintStream printStream = new PrintStream(file);
// 列印資料
printStream.println(99160);
// 關閉資源
printStream.close();
}
// 作用二: 收集日誌資訊
public static void function2() throws FileNotFoundException {
File file = new File("g:/c.txt");
FileOutputStream fileOutputStream = new FileOutputStream(file, true);
PrintStream printStream = new PrintStream(fileOutputStream);
try {
str = null;
System.out.println("字元個數:" + str.length());
result = 4 / 0;
} catch (Exception e) {
e.printStackTrace(printStream);
}
}
轉換流:
InputStreamReader :輸入位元組流轉換成輸入字元流
OutputStreamWriter :輸出位元組流轉換成輸出字元流
轉換流的作用:
1. 可以把位元組流轉換成字元流。
2. 可以指定任意的碼錶進行讀寫資料。支援編碼指定
作用詳細說明:無非就是指定碼錶 所有轉換成字串輸出 快捷方便,功能強大
//轉換流
public class IOswitch {
public static void main(String[] args) throws IOException {
readTest1();
writeTest1();
readData();
readData();
}
// 作用一、把輸入位元組流轉換成輸入字元流 -----> InputStreamReader
// 此方法可從控制檯取一行資料,取代scanner方法
public static void readTest1() throws IOException {
// 先獲取標準 的輸入流
InputStream in = System.in;
// 把位元組流轉換成字元流
InputStreamReader inputStreamReader = new InputStreamReader(in);
// 一次讀取一行的功能 只有BufferedReader才有,故需要引用
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
// 簡寫:一行頂三行
// BufferedReader bufferedReader2 = new BufferedReader(new
// InputStreamReader(System.in));
String line = null;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
}
// 作用二、把輸出位元組流轉換成輸出字元流
public static void writeTest1() throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("g:/b.txt");
String data = "hello world";
OutputStreamWriter writer = new OutputStreamWriter(fileOutputStream);
// 寫出資料
writer.write(data);
// 關閉資源
writer.close();
}
// 作用三、指定碼錶讀取資料
public static void readData() throws IOException {
FileInputStream fileInputStream = new FileInputStream("g:/b.txt");
// FileReader 預設使用的碼錶是gbk碼錶,而且不能指定碼錶讀。
// 指定解碼格式
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "utf-8");
char[] buf = new char[1024];
int length = 0;
while ((length = inputStreamReader.read(buf)) != -1) {
System.out.println(new String(buf, 0, length));
}
// 關閉資源
inputStreamReader.close();
}
// 指定碼錶進行寫資料
public static void writeData() throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("g:/b.txt");
// FileWriter 預設使用的碼錶是gbk碼錶,而且不能指定碼錶寫。
OutputStreamWriter fileWriter = new OutputStreamWriter(fileOutputStream, "utf-8");
fileWriter.write("奧特曼");
fileWriter.close();
}
}