- 主要類
- File類
- 名稱分隔符
path1="d:/temp/test.txt";
path2="d:"+File.separator+"temp"+File.separator+"test.txt";
//1、建構File對象
File src = new File(path);
System.out.println(src.length());
//2、建構File對象
src = new File("D:/java300/IO_study01","IO.png");
src = new File("D:/java300/","IO_study01/IO.png");
System.out.println(src.length());
//3、建構File對象
src = new File(new File("D:/java300/IO_study01"),"IO.png");
System.out.println(src.length());
- 路徑基本資訊
//使用者目錄
System.out.println(System.getProperty("user.dir"));
//取得絕對路徑
src = new File("IO.png");
System.out.println(src.getAbsolutePath());
File src = new File("IO_study01/IO.png");
//基本資訊
System.out.println("名稱:"+src.getName());
System.out.println("路徑:"+src.getPath());
System.out.println("絕對路徑:"+src.getAbsolutePath());
System.out.println("父路徑:"+src.getParent());
System.out.println("父對象:"+src.getParentFile().getName());
//檔案狀态
src = new File("xxx");
if(null == src || !src.exists()) {
System.out.println("檔案不存在");
}else {
if(src.isFile()) {
System.out.println("檔案操作");
}else { //src.isDirectory()
System.out.println("檔案夾操作");
}
}
//擷取檔案的長度位元組數(檔案夾傳回0)
File src = new File("D:/java300/IO_study01/IO.png");
System.out.println("長度:"+ src.length());
//檔案操作
//createNewFile() : 不存在才建立,存在建立失敗,隻能建立檔案
//delete():删除已經存在的檔案
//作業系統的裝置名不能作為檔案名建立
File src = new File("D:/java300/IO_study01/io.txt");
boolean flag =src.createNewFile();
System.out.println(flag);
flag = src.delete();
System.out.println(flag);
- 建立目錄
//1、mkdir() : 確定上級目錄存在,不存在建立失敗
//2、mkdirs(): 上級目錄可以不存在,不存在一同來建立
File dir = new File("D:/java300/IO_study01/dir/test");
//建立目錄 mkdirs()
boolean flag = dir.mkdirs();
System.out.println(flag);
//建立目錄 mkdir()
dir = new File("D:/java300/IO_study01/dir/test2");
flag = dir.mkdirs();
System.out.println(flag);
- 列出目錄資訊
File dir = new File("D:/java300/IO_study01");
//下級名稱 list
String[] subNames = dir.list();
for(String s:subNames) {
System.out.println(s);
}
//下級對象 listFiles()
File[] subFiles = dir.listFiles();
for(File s:subFiles) {
System.out.println(s.getAbsolutePath());
}
//所有盤符
File[] roots = dir.listRoots();
for(File r:roots) {
System.out.println(r.getAbsolutePath());
}
- 統計目錄的大小(Byte)
public class Test {
public static void main(String[] args) {
File src = new File("D:\\java300\\IO_study01");
count(src);
System.out.println(len);
}
private static long len =0;
public static void count(File src) {
//擷取大小
if(null!=src && src.exists()) {
if(src.isFile()) { //大小
len+=src.length();
}else { //子孫級
for(File s:src.listFiles()) {
count(s);
}
}
}
}
}
-
字元編碼
Java字元使用16位的雙位元組存儲。
字元集 | 說明 |
US-ASCII | ASCII編碼 |
ISO-8859-1 | Latin-1 拉丁字元,包含中文,日文等 |
UTF-8 | 變長Unicode字元(1-3位元組),英文字元占1個位元組,中文字元占3個位元組。 |
UTF-16BE | 定長Unicode字元(2位元組),Gig-Ending編碼:高位元組低位址 |
UTF-16LE | 定長Unicode字元(2位元組),Little-Ending編碼:低位元組低位址 |
UTF_16 | 檔案的開頭指明BE/LE編碼方式,即BOM(Byte Order Mark):“FE FF”表示BE編碼,“FF FE”表示LE編碼 |
這裡ANSI指系統預設的字元集——windows中文環境下預設字元集是GBK。
- 字元編碼
String english = "abc";
String chinese = "将進酒";
byte[] data1 = english.getBytes();
System.out.println("英文\"" + english + "\"的長度:" + data1.length);
byte[] data2 = english.getBytes("GBK");
System.out.println("英文\"" + english + "\"的長度:" + data2.length);
byte[] data3 = chinese.getBytes(); // 預設getBytes("UTF8"),工程字元集,字元集名稱大小寫均可
System.out.println("中文\"" + chinese + "\"的長度:" + data3.length);
byte[] data4 = chinese.getBytes("GBK");
System.out.println("中文\"" + chinese + "\"的長度:" + data4.length);
-
字元解碼
String–>byte[]:編碼
byte[] -->String:解碼
String str1 = "米國USA";
byte[] data = str1.getBytes();
String str2 = new String(data, 0, data.length, "gbk");
System.out.println(str2);
String str3 = new String(data, "utf8");
System.out.println(str3);
- 亂碼的原因
- 位元組數不夠
- 編碼字元集不比對
-
中文字元集
cp936<gb2312<bgk
- IO流
-
位元組流
InputStream/OutputStream
-
字元流
Reader/Writer
- 讀操作步驟(概念)
//1、建立源
File src = new File("abc.txt");
//2、選擇流
try {
InputStream is =new FileInputStream(src);
//3、操作 (讀取)
int data1 = is.read(); //第一個資料s
int data2 = is.read(); //第二個資料x
int data3 = is.read(); //第三個資料t
int data4 = is.read(); //????不是資料,檔案的末尾傳回-1
System.out.println((char)data1);
System.out.println((char)data2);
System.out.println((char)data3);
System.out.println(data4);
//4、釋放資源
is.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
- 操作步驟
位元組讀
//1、建立源
File src = new File("abc.txt");
//2、選擇流
InputStream is =null;
try {
is =new FileInputStream(src);
//3、操作 (讀取)
int temp ;
while((temp=is.read())!=-1) { //一個位元組一個位元組地讀
System.out.println((char)temp);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、釋放資源
try {
if(null!=is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
塊讀
//1、建立源
File src = new File("abc.txt");
//2、選擇流
InputStream is =null;
try {
is =new FileInputStream(src);
//3、操作 (分段讀取)
byte[] flush = new byte[1024*10]; //緩沖容器
int len = -1; //接收長度
while((len=is.read(flush))!=-1) {
//位元組數組-->字元串 (解碼)
String str = new String(flush,0,len); //String str = new String(flush, "utf8");
System.out.print(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、釋放資源
try {
if(null!=is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
- 寫操作
//1、建立源
File dest = new File("dest.txt");
//2、選擇流
OutputStream os =null;
try {
os = new FileOutputStream(dest,true); //true表示追加寫入
//3、操作(寫出)
String msg ="IO is so easy\r\n";
byte[] datas =msg.getBytes(); // 字元串-->位元組數組(編碼,預設字元集)
//byte[] datas = msg.getBytes("utf8"); 按照utf8字元集編碼
os.write(datas,0,datas.length); //或者out.write(datas);
os.flush();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//4、釋放資源
try {
if (null != os) {
os.close();
}
} catch (Exception e) {
}
}
-
釋放資源
先打開的後關閉,後打開的先關閉。
可以利用Closeable接口封裝釋放資源的動作。
public static void close(Closeable... ios) {
for(Closeable io:ios) {
try {
if(null!=io) {
io.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
或者可以利用try …with…resources自動資源釋放(JDK7之後)
try(is;os) { //<----------is和os自動釋放
或者
try( InputStream is=new FileInputStream(src);
OutputStream os=new FileOutputStream(dest);){
......
......
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
-
純文字處理
FileReader/FileWriter(内置解決字元編解碼問題)
append()傳回Writer,故可以實作鍊式引用。
塊讀
//1、建立源
File src = new File("abc.txt");
//2、選擇流
Reader reader =null;
try {
reader =new FileReader(src);
//3、操作 (分段讀取)
char[] flush = new char[1024]; //緩沖容器,注意是字元數組不是位元組數組
int len = -1; //接收長度
while((len=reader.read(flush))!=-1) {
//字元數組-->字元串,解碼無需指定字元集(系統已經處理好了)
String str = new String(flush,0,len);
System.out.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、釋放資源
try {
if(null!=reader) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
塊寫
//1、建立源
File dest = new File("dest.txt");
//2、選擇流
Writer writer =null;
try {
writer = new FileWriter(dest);
//3、操作(寫出)
//寫法一
//String msg ="I love you baby\r\n你知道我在等你嗎";
//char[] datas =msg.toCharArray(); // 字元串-->字元數組(不存在編碼問題)
//writer.write(datas,0,datas.length);
寫法二
String msg ="I love you baby\r\n你知道我在等你嗎";
writer.write(msg);
writer.write("add");
writer.flush();
//寫法三
//writer.append("I love you baby\r\n").append("你知道我在等你嗎");
//writer.flush();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//4、釋放資源
try {
if (null != writer) {
writer.close();
}
} catch (Exception e) {
}
}
-
位元組數組流
ByteArrayInputStream&ByteArrayOutputStream,在記憶體中,Java可以直接通路,無需關閉。
-
處理流
使用了裝飾模式。
- 裝飾器類包裹/包裝基本類。接口方法(産生多态行為)從裝飾器類向基本類方向層層調用,然後由内層的基本類向外部的包裝類層層傳回。抽象類實作接口,但主要是要提供公共屬性。
- 流的緩沖
- 提供緩沖的裝飾流類可以提高IO性能。
- 控制流的基礎是節點流,底層不能沒有節點流。
- 釋放外層裝飾器流類的對象,則内層的基本流類對象資源會自動釋放。釋放是從裡到外依次釋放。
這裡節點流是基本IO流類,而控制流是裝飾器IO流類。裝飾器IO流類提供流的緩沖提升IO效能。控制流類包裝節點流類——裝飾器類包裝基本類。
示例如下:
File src = new File("abc.txt");
...
is=new BufferedInputStream(new FileInputStream(src));
裝飾器類 基本類
控制流類 節點流類
提升IO效能
後釋放(手動) 先釋放(自動)
-------------------------------------------------------------------
File dest = new File("dest.txt");
...
os =new BufferedOutputStream( new FileOutputStream(dest));
- 字元輸入輸出加入緩沖流
- 讀入
//1、建立源
File src = new File("abc.txt");
//2、選擇流
BufferedReader reader =null;
try {
reader =new BufferedReader(new FileReader(src));
//3、操作 (分段讀取)
String line =null;
while((line=reader.readLine())!=null) {
//字元數組-->字元串
System.out.println(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、釋放資源
try {
if(null!=reader) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
- 寫出
//1、建立源
File dest = new File("dest.txt");
//2、選擇流
BufferedWriter writer =null;
try {
writer = new BufferedWriter(new FileWriter(dest));
//3、操作(寫出)
writer.append("I love you baby");
writer.newLine(); //輸出一個\r\n
writer.append("偏偏喜歡你");
writer.flush();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//4、釋放資源
try {
if (null != writer) {
writer.close();
}
} catch (Exception e) {
}
}
-
轉換流
CharactorStreams—>InputStreamReader/OutputStreamWriter—>ByteStreams
- 将位元組流轉換成字元流
//操作System.in 和System.out
try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter writer =new BufferedWriter(new OutputStreamWriter(System.out));){
//循環擷取鍵盤的輸入(exit退出),輸出此内容
String msg ="";
while(!msg.equals("exit")) {
msg = reader.readLine(); //循環讀取
writer.write(msg); //循環寫出
writer.newLine();
writer.flush(); //強制重新整理。不強制重新整理,在緩存未滿時不輸出,卡在上一步。
}
}catch(IOException e) {
System.out.println("操作異常");
}
- 處理指定字元集
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
public class ConvertTest {
public static void main(String[] args) {
try(BufferedReader reader =
new BufferedReader(
new InputStreamReader(
new URL("http://www.baidu.com").openStream(),"UTF-8"));
BufferedWriter writer =
new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream("baidu.html"),"UTF-8"));){
//3、操作 (讀取)
String msg ;
while((msg=reader.readLine())!=null) {
//System.out.println(msg);
writer.write(msg); //如果字元集不統一将出現亂碼
writer.newLine();
}
writer.flush();
}catch(IOException e) {
System.out.println("操作異常");
}
}
}
-
資料流
DataInputStream/DataOutputStream儲存了資料及其類型。
//寫出
ByteArrayOutputStream baos =new ByteArrayOutputStream();
DataOutputStream dos =new DataOutputStream(new BufferedOutputStream(baos));
//操作資料類型 + 資料
dos.writeUTF("白日依山盡");
dos.writeInt(18);
dos.writeBoolean(false);
dos.writeChar('a');
dos.flush();
byte[] datas =baos.toByteArray();
System.out.println(datas.length);
//讀取
DataInputStream dis =new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(datas)));
//順序與寫出一緻
String msg = dis.readUTF();
int age = dis.readInt();
boolean flag = dis.readBoolean();
char ch = dis.readChar();
System.out.println(flag);