1、IO流的基本概念和原理
1.1 什麼是流
流:流動 、流向 從一端移動到另一端 源頭與目的地,程式 與 檔案|數組|網絡連接配接|資料庫 進行資料交換,都是以流進行的 ,以程式為中心
1.2 IO流分類
1、根據流向分:輸入流與輸出流
2、根據資料分:
位元組流:二進制,可以表示一切檔案 ,包括 :純文字 、doc、 音頻、視訊等等
字元流:文本檔案,隻能處理純文字。
3、根據功能分:
節點流:包裹源頭,比如:FileInputStream
處理流:增強功能,提升性能,比如:BufferedInputStream
1.3 IO流的相關接口及主要方法
1、位元組流
流 | 接口 | 方法 | 實作類 |
輸入流 | InputStream | read(byte[] b) 、read(byte[] b, int off, int len) 、close() | FileInputStream |
輸出流 | OutputStream | write(byte[] b) 、 write(byte[] b, int off, int len) 、flush() 、close() | FileOutputStream |
2、字元流
流 | 接口 | 方法 | 實作類 |
輸入流 | Reader | read(char[] cbuf)、 read(char[] cbuf, int off, int len) 、close() | FileReader |
輸出流 | Writer | write(char[] cbuf) write(char[] cbuf, int off, int len) 、flush() 、close() | FileWriter |
2、讀取檔案
2.1 位元組流讀取檔案
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
/**
* 檔案的讀取
* 1、建立聯系 File對象
2、選擇流 檔案輸入流 InputStream FileInputStream
3、操作 : byte[] car =new byte[1024]; +read+讀取大小
輸出
4、釋放資源 :關閉
*/
public class Demo01 {
public static void main(String[] args) {
//1、建立聯系 File對象
File src =new File("e:/xp/test/a.txt");
//2、選擇流
InputStream is =null; //提升作用域
try {
is =new FileInputStream(src);
//3、操作 不斷讀取 緩沖數組
byte[] car =new byte[1024];
int len =0; //接收 實際讀取大小
//循環讀取
StringBuilder sb =new StringBuilder();
while(-1!=(len=is.read(car))){
//輸出 位元組數組轉成字元串
String info =new String(car,0,len);
sb.append(info);
}
System.out.println(sb.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("檔案不存在");
} catch (IOException e) {
e.printStackTrace();
System.out.println("讀取檔案失敗");
}finally{
try {
//4、釋放資源
if (null != is) {
is.close();
}
} catch (Exception e2) {
System.out.println("關閉檔案輸入流失敗");
}
}
}
}
2.2 位元組流寫出到檔案
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* 寫出檔案
1、建立聯系 File對象 目的地
2、選擇流 檔案輸出流 OutputStream FileOutputStream
3、操作 : write() +flush
4、釋放資源 : 關閉
*/
public class Demo02 {
public static void main(String[] args) {
//1、建立聯系 File對象 目的地
File dest =new File("e:/xp/test/test.txt");
//2、選擇流 檔案輸出流 OutputStream FileOutputStream
OutputStream os =null;
//以追加形式 寫出檔案 必須為true 否則為覆寫
try {
os =new FileOutputStream(dest,true);
//3、操作
String str="bjsxt is very good \r\n";
//字元串轉位元組數組
byte[] data =str.getBytes();
os.write(data,0,data.length);
os.flush(); //強制重新整理出去
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("檔案未找到");
} catch (IOException e) {
e.printStackTrace();
System.out.println("檔案寫出失敗");
}finally{
//4、釋放資源 :關閉
try {
if (null != os) {
os.close();
}
} catch (Exception e2) {
System.out.println("關閉輸出流失敗");
}
}
}
}
2.3 檔案的拷貝
利用位元組流進行檔案的拷貝:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
1、建立聯系 File對象 源頭 目的地
2、選擇流
檔案輸入流 InputStream FileInputStream
檔案輸出流 OutputStream FileOutputStream
3、操作 : 拷貝
byte[] flush =new byte[1024];
int len =0;
while(-1!=(len=輸入流.read(flush))){
輸出流.write(flush,0,len)
}
輸出流.flush
4、釋放資源 :關閉 兩個流
*/
public class CopyFileDemo {
public static void main(String[] args) {
String src ="E:/xp/test";
String dest="e:/xp/test/4.jpg";
try {
copyFile(src,dest);
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("檔案不存在");
} catch (IOException e) {
e.printStackTrace();
System.out.println("拷貝檔案失敗|關閉流失敗");
}
}
/**
* 檔案的拷貝
* @param 源檔案路徑
* @param 目錄檔案路徑
* @throws FileNotFoundException,IOException
* @return
*/
public static void copyFile(String srcPath,String destPath) throws FileNotFoundException,IOException {
//1、建立聯系 源(存在且為檔案) +目的地(檔案可以不存在)
File src =new File(srcPath);
File dest =new File(destPath);
if(! src.isFile()){ //不是檔案或者為null
System.out.println("隻能拷貝檔案");
throw new IOException("隻能拷貝檔案");
}
//2、選擇流
InputStream is =new FileInputStream(src);
OutputStream os =new FileOutputStream(dest);
//3、檔案拷貝 循環+讀取+寫出
byte[] flush =new byte[1024];
int len =0;
//讀取
while(-1!=(len=is.read(flush))){
//寫出
os.write(flush, 0, len);
}
os.flush(); //強制刷出
//關閉流
os.close();
is.close();
}
}
2.4 檔案拷貝和檔案夾拷貝的工具類封裝
工具類:進行檔案和檔案夾拷貝
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* 檔案操作
* 1、檔案拷貝
* 2、檔案夾拷貝 拒絕自己拷貝給自己
*/
public class FileUtil {
/**
* 拷貝檔案夾
* @param src 源路徑
* @param dest 目标路徑
* @throws IOException
* @throws FileNotFoundException
*/
public static void copyDir(String srcPath,String destPath) throws FileNotFoundException, IOException{
//拒絕自己拷貝給自己
if(srcPath.equals(destPath)){
return ;
}
File src=new File(srcPath);
File dest =new File(destPath);
copyDir(src,dest);
}
/**
* 拷貝檔案夾
* @param src 源File對象
* @param dest 目标File對象
* @throws IOException
* @throws FileNotFoundException
*/
public static void copyDir(File src,File dest) throws FileNotFoundException, IOException{
if(src.isDirectory()){ //檔案夾
dest =new File(dest,src.getName());
if(dest.getAbsolutePath().contains(src.getAbsolutePath())){
System.out.println("父目錄不能拷貝到子目錄中");
return;
}
}
copyDirDetail(src,dest);
}
/**
* 拷貝檔案夾細節
* @param src
* @param dest
*/
public static void copyDirDetail(File src,File dest) throws FileNotFoundException,IOException{
if(src.isFile()){ //檔案
try {
FileUtil.copyFile(src, dest);
} catch (FileNotFoundException e) {
//e.printStackTrace();
throw e;
} catch (IOException e) {
//e.printStackTrace();
throw e;
}
}else if(src.isDirectory()){ //檔案夾
//確定目标檔案夾存在
dest.mkdirs();
//擷取下一級目錄|檔案
for(File sub:src.listFiles()){
copyDirDetail(sub,new File(dest,sub.getName()));
}
}
}
/**
* 檔案的拷貝
* @param 源檔案路徑
* @param 目錄檔案路徑
* @throws FileNotFoundException,IOException
* @return
*/
public static void copyFile(String srcPath,String destPath) throws FileNotFoundException,IOException {
//1、建立聯系 源(存在且為檔案) +目的地(檔案可以不存在)
copyFile(new File(srcPath),new File(destPath));
}
/**
* 檔案的拷貝
* @param 源檔案File對象
* @param 目錄檔案File對象
* @throws FileNotFoundException,IOException
* @return
*/
public static void copyFile(File src,File dest) throws FileNotFoundException,IOException {
if(! src.isFile()){ //不是檔案或者為null
System.out.println("隻能拷貝檔案");
throw new IOException("隻能拷貝檔案");
}
//dest為已經存在的檔案夾,不能建立于檔案夾同名的檔案
if(dest.isDirectory()){
System.out.println(dest.getAbsolutePath()+"不能建立于檔案夾同名的檔案");
throw new IOException(dest.getAbsolutePath()+"不能建立于檔案夾同名的檔案");
}
//2、選擇流
InputStream is =new BufferedInputStream(new FileInputStream(src));
OutputStream os =new BufferedOutputStream(new FileOutputStream(dest));
//3、檔案拷貝 循環+讀取+寫出
byte[] flush =new byte[1024];
int len =0;
//讀取
while(-1!=(len=is.read(flush))){
//寫出
os.write(flush, 0, len);
}
os.flush(); //強制刷出
//關閉流
os.close();
is.close();
}
}
檔案和檔案夾拷貝的測試代碼:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* 檔案夾的拷貝
* 1、檔案 指派 copyFile
* 2、檔案 建立 mkdirs()
* 3、遞歸查找子孫級
*/
public class CopyDir {
public static void main(String[] args) {
//源目錄
String srcPath="E:/xp/test/a";
//目标目錄
String destPath="E:/xp/test/a/b";
try {
FileUtil.copyDir(srcPath,destPath);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 拷貝檔案夾
* @param src 源路徑
* @param dest 目标路徑
*/
public static void copyDir(String srcPath,String destPath){
File src=new File(srcPath);
File dest =new File(destPath);
copyDir(src,dest);
}
/**
* 拷貝檔案夾
* @param src 源File對象
* @param dest 目标File對象
*/
public static void copyDir(File src,File dest){
if(src.isDirectory()){ //檔案夾
dest =new File(dest,src.getName());
}
copyDirDetail(src,dest);
}
/**
* 拷貝檔案夾細節
* @param src
* @param dest
*/
public static void copyDirDetail(File src,File dest){
if(src.isFile()){ //檔案
try {
FileUtil.copyFile(src, dest);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}else if(src.isDirectory()){ //檔案夾
//確定目标檔案夾存在
dest.mkdirs();
//擷取下一級目錄|檔案
for(File sub:src.listFiles()){
copyDirDetail(sub,new File(dest,sub.getName()));
}
}
}
}