Java IO
本文記錄了在學習Java IO程序中的知識點,用于復習和快速查閱,不夠詳細的部分可能會在后續補充,
什么是流
流:記憶體與存盤設備(外存)之間傳輸資料的通道
IO:輸入流輸出流(如read, write)
流分類(按單位):
- 位元組流:以位元組為單位,可以讀寫所有資料
- 字符流:以字符為單位,只能讀寫文本資料
流分類(按功能):
- 節點流(底層流):具有實際傳輸資料的讀寫功能
- 過濾流:在節點流的基礎之上增強功能
位元組流
位元組流的父類(抽象類)有:InputStream, OutputStream
- FileInputSteam:
publib int read(byte[] b) 從流中讀取多個位元組,將讀取內容存入b陣列,回傳實際讀到的位元組數;若達到檔案尾部,則回傳-1;讀取的數量和b的大小也有關
具體方法可見JDK檔案,以下代碼需要加上例外處理
FileInputStream fis = new FileInputStream("a.txt"); //這里不是與class檔案的同目錄,需再考察,需寫絕對路徑
int data = https://www.cnblogs.com/gaoyuan206/p/0;
// while((data = fis.read()) != -1){ //一次只讀一個字符
// System.out.println(data);
// }
byte []a =new byte[3];
int count = fis.read(a);
for(Object ob : a){
System.out.println(ob);
}
System.out.println(count);
byte []b =new byte[3];
count = fis.read(b);
for(Object ob : b){
System.out.println(ob); //讀兩次,第二次是3-6段的字符 和C相似,類似檔案指標
}
System.out.println(count);
fis.close();
System.out.println("end");
- FileOutputSteam:
publib int write(byte[] b) 一次寫入多個位元組,將b陣列中所有位元組,寫入輸出流,回傳值為實際讀到的位元組數
FileOutputStream fio = new FileOutputStream("a.txt"); //直接覆寫原檔案,原有內容消失
fio.write(97);
fio.write('b');
String a = "hello,world";
fio.write(a.getBytes()); //這里需要將字串轉為 Byte[]
fio.close();
System.out.println("ending");
FileOutputStream("a.txt")改為("a.txt",true)將不會覆寫原檔案,保有原有內容
位元組緩沖流
BufferedInputStream, BufferedOutputStream 父類是過濾流
當創建BufferedInputStream時,將創建一個內部緩沖區陣列,當從流中讀取或跳過位元組時,內部緩沖區將根據需要從所包含的輸入流中重新填充,一次有多個位元組,mark操作會記住輸入流中的一點,并且reset操作會導致從最近的mark操作之后讀取的所有位元組在從包含的輸入流中取出新的位元組之前重新讀取,
- 提高IO效率,減少訪問磁盤的次數
- 資料存在緩沖區,flush是將緩沖區的內容寫入檔案,也可以直接close
BufferedInputStream(inputStream) //需要傳入一個輸入流
FileInputStream fis = new FileInputStream("a.txt"); //這里需要絕對路徑
BufferedInputStream bis = new BufferedInputStream(fis); //增強fis
int data = https://www.cnblogs.com/gaoyuan206/p/0;
while((data = bis.read())!=-1){
System.out.print((char)data);
}
bis.close();
先把一部分內容讀到緩沖區,再在緩沖區進行read, write操作,只需要關閉bis即可
BufferedOutputStream
- 該類實作緩沖輸出流, 通過設定這樣的輸出流,應用程式可以向底層輸出流寫入位元組,而不必為寫入的每個位元組導致底層系統的呼叫,
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write("hello,world".getBytes()); //寫入了8K的緩沖區
bos.flush(); //重繪到外存,正式寫入了
bos.close(); //即使上方沒有flush();在close()中也會再重繪一次
物件流
ObjectInputStream/ObjectOutputStream
- 增強了緩沖區功能
- 增強了讀寫8種基本資料型別和字串的功能
- 增強了讀寫物件的功能:readObject() 從流中讀取一個物件;writeObject(Object obj) 向流中寫入一個物件
使用流傳輸物件的程序成為序列化(write)、反序列化(read)
ObjectOutputStream oos = new ObjectOutputStream(fos);
Student s1 = new Student("xiaohong",12);
oos.writeObject(s1);·
oos.close();
- 使用物件流時,需要將類實作Serializable介面(序列化類中的屬性也需要實作該介面),例
public class Student implements Serializable //此介面內部沒有方法,只是宣告一下
否則將會出現不可序列化的例外
- 序列化版本號ID,可以保證序列化的類和反序列化的類是同一個類
private static final long serialVersionUID = 100L;
如果序列化之后,ID已固定,若改變ID,則不能反序列化,除非再次用改變后的ID再進行序列化
反序列化demo:
ObjectInputStream ois = new ObjectInputStream(fis);
Student s = (Student) ois.readObject();
ois.close();
System.out.println(s.toString());
-
反序列化的程序中,Student類也需要實作Serializable介面
-
使用transient修飾屬性,則這個屬性不能序列化,在序列化程序中,如果哪個屬性不想被序列化,可加此修飾符
-
靜態屬性也不能序列化
-
序列化多個物件,可借助集合實作
字符流
- 字符編碼
ISO-8859-1收錄除ASCII外,還包括西歐、希臘語等對應的文字符號, UTF-8針對Unicode碼表的可變長度字符編碼, GV2312簡體中文, GBK簡體中文、擴充, BIG5繁體中文
當編碼方式和解碼方式不一致,會出現亂碼
FileInputStream fis = new FileInputStream("a.txt"); //此處為絕對路徑,存盤了4個漢字“好好學習”,12個位元組,UTF-8編碼
int count = 0;
while((count = fis.read())!= -1){
System.out.println((char)count); //會輸出亂碼,因為每次輸出一個位元組
}
字符流的父類(抽象類):Reader/Writer
char型變數是用來存盤Unicode編碼的字符的,unicode 編碼字符集中包含了漢字,所以,char型變數中當然可以存盤漢字,
不過,如果某個特殊的漢字沒有被包含在 unicode 編碼字符集中,那么,這個char型變數中就不能存盤這個特殊漢字,
說明:unicode編碼占用兩個位元組,所以,char型別的變數也是占用兩個位元組,
FileReader fir = new FileReader("a.txt"); //檔案字符輸入流
int count = 0;
while((count = fir.read())!= -1){
System.out.print((char)count); //注意,txt檔案需要使用UTF-8編碼
}
fir.close();
檔案字符輸入流如上所示
也可以用字符陣列,如下
int count = 0;
char[] buf = new char[1024];
while((count = fir.read(buf))!= -1){
System.out.print(buf); //注意,txt檔案需要使用UTF-8編碼
}
字符復制(只能復制文本檔案,不能復制圖片等二進制檔案)
FileReader fir = new FileReader("a.txt"); //檔案字符輸入流
FileWriter fiw = new FileWriter("b.txt");
int count = 0;
char[] buf = new char[1024];
while((count = fir.read(buf))!= -1){
fiw.write(new String(buf).trim()); //注意,txt檔案需要使用UTF-8編碼
}
fir.close();
fiw.close();
fiw.close()時會呼叫fiw.flush(),trim()時為了消除char[1024]的空白字符
字符緩沖流
BufferedReader/BufferedWriter
- 高效讀寫
- 可支持換行符
- 可一次寫一行/讀一行 (readLine)
newLine(寫入一個行分隔符)
FileReader fir = new FileReader("a.txt");
BufferedReader bir = new BufferedReader(fir);
int count = 0;
char[] s = new char[1024];
// while((count=bir.read(s))!= -1){
// System.out.println(new String(s).trim());
// }
String s1 = bir.readLine();
System.out.println(s1);
兩種讀取方式
biw.write(s1);
biw.newLine(); //寫入一個換行符
biw.close(); //附帶重繪
BufferedWriter的使用示例如上
列印流
PrintWriter繼承Writer
- 將物件的格式表示列印到文本輸出流, 這個類實作了PrintStream中所有的print方法, 它不包含用于撰寫原始位元組的方法,程式應使用未編碼的位元組流,
PrintWriter pw = new PrintWriter("b.txt");
pw.println(97);
pw.println(true);
pw.println('a'); //需要重繪
pw.close();
也包含.write()方法,
轉換流
InputStreamReader/OutputStreamWriter(名字即InputStream+Reader,橋梁)
- 可將位元組流轉換為字符流
- 可設定字符的編碼方式
FileInputStream fis = new FileInputStream("a.txt"); //檔案是UTF-8編碼
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
int count;
char[] s = new char[1024];
while((count = isr.read(s))!=-1){
System.out.println(new String(s,0,count));
}
isr.close();
使用上大致相同
ANSI即為GBK編碼方式
OutputStreamWriter中的write則會根據編碼方式,自動將檔案轉為此類編碼方式
File類
代表物理盤符中的一個檔案或檔案夾

以上為常用的方法,具體方法請訪問JDK檔案
具體使用:
- 分隔符
- 檔案操作
- 檔案夾操作
路徑分隔符;
名稱分隔符\
相對路徑在與SRC檔案的同級目錄下
File f = new File("c.txt");
System.out.println(f);
// if(!f.exists()){
// boolean bo = f.createNewFile();
// System.out.println(bo);
// }
// f.delete(); //boolean
// f.deleteOnExit();// JVM退出時自動洗掉
System.out.println(f.getAbsoluteFile());
System.out.println(f.getPath());
System.out.println(f.getName());
System.out.println(f.getParent()); //File類的String中不包含父目錄時輸出Null
System.out.println(f.length());
System.out.println(new Date(f.lastModified()));
//判斷
System.out.println("是否可寫"+f.canWrite());
System.out.println("是否隱藏"+f.isHidden());
File類測驗用例,結果如下

檔案夾操作
File dir = new File("cc\\dd");
if(!dir.exists()){
// dir.mkdir(); //只能創建單級目錄
dir.mkdirs(); //可創建多級目錄
}
// dir.delete();
//遍歷檔案夾
File dir2 = new File("C:\\Users\\GaoYuan\\Pictures");
String[] files = dir2.list();
for(String s : files){
System.out.println(s);
}
其余操作與File類相同
FileFilter介面
File[]files = dir2.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if(pathname.getName().endsWith(".jpg")){
return true;
}
return false;
}
});
for(File f1 : files){
System.out.println(f1.getName());
}
添加一個過濾器,注意的是.listFiles回傳的是一個File[]
Properties
屬性集合,繼承HashTable,可保存在流中或在流中加載
- 存盤屬性名和屬性值
- 屬性名和屬性值都是字串型別
- 沒有泛型
- 和流有關
Properties properties = new Properties();
properties.setProperty("use","xiaoli");
properties.setProperty("age","20");
properties.setProperty("address","china");
System.out.println(properties);
Set<String> proname = properties.stringPropertyNames();
for(String pro : proname){
System.out.println(pro+"="+properties.getProperty(pro));
}
PrintWriter pw = new PrintWriter("b.txt");
properties.list(pw);
pw.close();
Properties,list()將該屬性集合列印到輸入流中,close()進行重繪寫入檔案
保存方法:
FileOutputStream fos = new FileOutputStream("store.properties");
properties.store(fos,"注釋");
fos.close();
加載方法:
Properties properties1 = new Properties();
FileInputStream fis = new FileInputStream("store.properties");
properties1.load(fis);
System.out.println(properties1);
fis.close();
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/271823.html
標籤:Java
