JavaSE基礎之IO流
Java中把輸入/輸出(input/output)操作稱為流(Stream)。
流:即為起點到接收點有序的資料序列。
流的分類:
1.按照流的方向分為:
輸入流:只讀,只會從流中讀取資料;
輸出流:只寫,只會向流中寫入資料;
2.按照處理的資料分:
位元組流(InputStream/OutputStream):讀或寫的時候以位元組為單位;
字元流(Reader/Writer):讀或寫的時候以字元為單位;
一般情況下(排除特殊情況),一個漢字佔一個字元,一個字元佔兩個位元組,如果讀或寫的時候只讀或寫一個位元組的話,那麼就會出現亂碼。
3.按照功能分為:
低階流:直接從資料的源頭讀取資料或者直接把資料寫到目標位置的流,稱為低階流,也稱為節點流;
高階流:對一個已經存在的流的連線和封裝,稱為高階流,也稱為處理流;
先從位元組流中的FileInputStream和FileOutputStream說起:以下是兩者的模型
程式碼如下:
package com.Jevin.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class ByteStreamTest {
public static void main(String[] args) {
//readFile1();
//readFile2();
//writeFile1();
writeFile2();
}
/**
* 用FileInputStream讀取檔案的內容,一個一個位元組的讀取(出現中文亂碼問題)
*/
public static void readFile1() {
FileInputStream fin = null;
try {
//檔案的完整路徑有三部分組成:路徑名稱+分隔符+檔名稱;
//如果指定檔案不存在,或者他是一個目錄,而不是一個常規檔案,抑或因為其他原因無法開啟進行讀取,則丟擲FileNotFoundException;
//注意:FileInputStream只能讀取並顯示純文字檔案的內容(也就是能用記事本開啟的檔案)
fin = new FileInputStream("d:\\aa.txt");
int i = 0;
//從檔案中讀取一個位元組以int值返回,當讀到檔案末尾沒有資料時返回-1;
while((i=fin.read()) != -1){
//byte->int->char
System.out.print((char)i);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
//流開啟之後,必須進行關閉
try {
if(fin != null){
fin.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 用FileInputStream讀取檔案的內容,一次讀取多個位元組的內容(有些中文沒有亂碼,有些亂碼;並且還多讀了一些內容)
*/
public static void readFile2() {
FileInputStream fin = null;
try {
fin = new FileInputStream("d:\\aa.txt");
int i = 0;
byte[] b = new byte[100];
//從檔案中讀取100個位元組,放大陣列中,i返回的是讀取到的位元組的數量,當讀到檔案末尾沒有資料時返回-1;
while((i=fin.read(b)) != -1){
//byte[] -> char[] -> String
String str = new String(b);
System.out.print(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
//流開啟之後,必須進行關閉
try {
if(fin != null){
fin.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 用FileOutputStream寫String到檔案
*/
public static void writeFile1(){
FileOutputStream fout = null;
try {
//當目標檔案不存在時,JVM會自動建立這個檔案,若已存在,則將內容寫到這個檔案中;
fout = new FileOutputStream("d:\\bb.txt",true); //true表示追加寫檔案
String str = "2.用FileOutputStream寫String到檔案";
//將String轉換為byte[]
byte[] b = str.getBytes();
fout.write(b);
System.out.println("檔案寫入完成");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
//流開啟之後,必須進行關閉
try {
if(fout != null){
fout.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 用FileOutputStream寫String到檔案,解決換行
*/
public static void writeFile2(){
FileOutputStream fout = null;
try {
//當目標檔案不存在時,JVM會自動建立這個檔案,若已存在,則將內容寫到這個檔案中;
fout = new FileOutputStream("d:\\bb.txt",true); //true表示追加寫檔案
for(int i=0;i<=10;i++){
//由於FileOutputStream不會處理換行,需要我們在String結尾加入\n
//記事本不能識別\n,能夠識別\r\n;
String str = i+".用FileOutputStream寫String到檔案\r\n";
//將String轉換為byte[]
byte[] b = str.getBytes();
fout.write(b);
}
System.out.println("檔案寫入完成");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
//流開啟之後,必須進行關閉
try {
if(fout != null){
fout.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
然後將FileInputStream和FileOutputStream拼接起來,就組成了拷貝貼上的功能;
但是這樣直接使用低階流去讀和寫檔案顯然不是我們想要的,因為效率有點低,於是我們需要在低階流上接上一個高階流,像這樣:
下面有程式碼來實現上面的過程,也即是拷貝檔案的過程:
package com.Jevin.io;
import java.io.*;
/**
* 檔案拷貝器
*/
public class FileCoper {
private FileCoper(){
}
/**
* 拷貝檔案的操作
* @param srcFile 原始檔
* @param desPath 目標路徑
*/
public static void copyFile(String srcFile,String desPath){
//從原始檔的String中取出檔名稱,也就是從例如:"D:\\tools\\Navicat.rar"中取到"Navicat.rar";
String[] arr = srcFile.split("\\\\");
String fileName = arr[arr.length-1];
//組織目標檔案:路徑名稱+分隔符+檔名稱
String desFile = desPath+"\\"+fileName;
//宣告輸入流:
FileInputStream fin = null;
BufferedInputStream bin = null;
//宣告輸出流:
FileOutputStream fout = null; //低階輸出流
BufferedOutputStream bout = null; //高階輸出流
try {
//建立輸入流:
fin = new FileInputStream(srcFile);
bin = new BufferedInputStream(fin);
//建立輸出流:首先初始化低階流,然後初始化高階流
fout = new FileOutputStream(desFile);
bout = new BufferedOutputStream(fout);
int i=0;
byte[] b = new byte[1024*1024];
while((i=bin.read(b))!=-1){
bout.write(b,0,i);
}
/**
* 如果關閉低階流,那麼會導致小於8k的檔案滯留在bout的緩衝區,所以要重新整理快取區
* 拷貝過程中,只要檔案的大小大於8k,則無需重新整理快取
*/
//bout.flush();
//由於採用了正確的流的關閉方式,所以無論檔案大小,無需重新整理快取
System.out.println("檔案拷貝完成,"+srcFile+"拷貝到目標檔案"+desFile+"完成");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
//錯誤的關閉方式
//if(fin != null){
// try {
// fin.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
//}
//if(fout != null){
// try {
// fout.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
//}
//正確的關閉方式
//高階流在關閉的時候:1.會自動關閉低階流;2.會自動重新整理快取
try {
if(bin != null){
bin.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
//bout關閉的時候,會自動重新整理緩衝區
if(bout != null){
bout.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args){
String file = "D:\\tools\\aa.txt";
//String file = "D:\\tools\\Navicat.rar";
copyFile(file,"d:\\");
}
}
但是上面的程式碼有點問題,問題出在取檔名和拼接目標檔案路徑上,採用了"\\"和"\\\\"這兩種分隔符,但是不同作業系統上的分隔符是不一樣的,這樣寫的話就寫死了,違背java的可移植性特點,所以我們採用java.io.File來解決這個問題:
package com.Jevin.io;
import java.io.*;
/**
* 檔案拷貝器
*/
public class FileCoper {
private FileCoper(){
}
/**
* 拷貝檔案的操作
* @param srcFile 原始檔
* @param desPath 目標路徑
*/
public static void copyFile(String srcFile,String desPath){
//從原始檔的String中取出檔名稱
//File file = new File(srcFile);
//copyFile(file,desPath);
//繼續簡化
copyFile(new File(srcFile),desPath);
}
/**
* 拷貝檔案的操作
* @param srcFile 原始檔
* @param desPath 目標路徑
*/
public static void copyFile(File srcFile,String desPath){
//從原始檔的String中取出檔名稱
String fileName = srcFile.getName();
//組織目標檔案:路徑名稱+分隔符+檔名稱
String desFile = desPath+File.separator+fileName;
//宣告輸入流:
FileInputStream fin = null;
BufferedInputStream bin = null;
//宣告輸出流:
FileOutputStream fout = null; //低階輸出流
BufferedOutputStream bout = null; //高階輸出流
try {
//建立輸入流:
fin = new FileInputStream(srcFile);
bin = new BufferedInputStream(fin);
//建立輸出流:首先初始化低階流,然後初始化高階流
fout = new FileOutputStream(desFile);
bout = new BufferedOutputStream(fout);
int i=0;
byte[] b = new byte[1024*1024];
while((i=bin.read(b))!=-1){
bout.write(b,0,i);
}
System.out.println("檔案拷貝完成,"+srcFile+"拷貝到目標檔案"+desFile+"完成");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
//正確的關閉方式
//高階流在關閉的時候:1.會自動關閉低階流;2.會自動重新整理快取
try {
if(bin != null){
bin.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
//bout關閉的時候,會自動重新整理緩衝區
if(bout != null){
bout.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args){
String file = "D:\\tools\\aa.txt";
//String file = "D:\\tools\\Navicat.rar";
copyFile(file,"d:\\");
}
}
但是這裡還有一個問題,一個相對較大的檔案拷貝是需要時間的,如果在拷貝的這段時間內,程式突然停下來的,檔案看似拷貝下來了,但是這個檔案是不完整的,那麼該如何解決這個問題呢?下面程式碼演示:
package com.Jevin.io;
import java.io.*;
/**
* 檔案拷貝器
*/
public class FileCoper {
private FileCoper(){
}
/**
* 拷貝檔案的操作
* @param srcFile 原始檔
* @param desPath 目標路徑
*/
public static void copyFile(String srcFile,String desPath){
//從原始檔的String中取出檔名稱
//File file = new File(srcFile);
//copyFile(file,desPath);
//繼續簡化
copyFile(new File(srcFile),desPath);
}
/**
* 拷貝檔案的操作
* @param srcFile 原始檔
* @param desPath 目標路徑
*/
public static void copyFile(File srcFile,String desPath){
//從原始檔的String中取出檔名稱
String fileName = srcFile.getName();
//判斷目標路徑是否存在,如果不存在,就把他創造出來;
File dpath = new File(desPath);
if(!dpath.exists()){
dpath.mkdirs();
}
//組織目標檔案:路徑名稱+分隔符+檔名稱
String desFile = desPath+File.separator+fileName;
String tempFile = desFile + ".td"; //拷貝過程中的臨時檔名稱
//宣告輸入流:
FileInputStream fin = null;
BufferedInputStream bin = null;
//宣告輸出流:
FileOutputStream fout = null; //低階輸出流
BufferedOutputStream bout = null; //高階輸出流
try {
//建立輸入流:
fin = new FileInputStream(srcFile);
bin = new BufferedInputStream(fin);
//建立輸出流:首先初始化低階流,然後初始化高階流
fout = new FileOutputStream(tempFile);
bout = new BufferedOutputStream(fout);
int i=0;
byte[] b = new byte[1024*1024];
while((i=bin.read(b))!=-1){
bout.write(b,0,i);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
//正確的關閉方式
//高階流在關閉的時候:1.會自動關閉低階流;2.會自動重新整理快取
try {
if(bin != null){
bin.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
//bout關閉的時候,會自動重新整理緩衝區
if(bout != null){
bout.close();
}
} catch (IOException e) {
e.printStackTrace();
}
//當檔案拷貝完成之後,把臨時檔名稱改成目標檔名稱
//這裡注意:需要在流關閉的時候才可以重新命名,要不然流將執行緒鎖住,無法改名
File file1 = new File(desFile);
File file2 = new File(tempFile);
if(file2.renameTo(file1)){
System.out.println("檔案拷貝完成,"+srcFile+"拷貝到目標檔案"+desFile+"完成");
}else{
System.err.println("拷貝失敗");
}
}
}
public static void main(String[] args){
//String file = "D:\\tools\\aa.txt";
String file = "D:\\tools\\Navicat.rar";
copyFile(file,"d:\\abc");
}
}
但是這裡還有一個問題,以上只是解決了拷貝一個檔案到任意指定的資料夾中,但是實際還有將任意資料夾(包括其中的檔案)拷貝到任意資料夾中,這個又該如何實現呢?一下程式碼演示:
package com.Jevin.io;
import java.io.*;
/**
* 檔案拷貝器
*/
public class FileCoper {
private FileCoper(){
}
/**
* 拷貝檔案的操作
* @param srcFile 原始檔
* @param desPath 目標路徑
*/
public static void copyFile(File srcFile,String desPath){
//從原始檔的String中取出檔名稱
String fileName = srcFile.getName();
//判斷目標路徑是否存在,如果不存在,就把他創造出來;
File dpath = new File(desPath);
if(!dpath.exists()){
dpath.mkdirs();
}
//組織目標檔案:路徑名稱+分隔符+檔名稱
String desFile = desPath+File.separator+fileName;
String tempFile = desFile + ".td"; //拷貝過程中的臨時檔名稱
//宣告輸入流:
FileInputStream fin = null;
BufferedInputStream bin = null;
//宣告輸出流:
FileOutputStream fout = null; //低階輸出流
BufferedOutputStream bout = null; //高階輸出流
try {
//建立輸入流:
fin = new FileInputStream(srcFile);
bin = new BufferedInputStream(fin);
//建立輸出流:首先初始化低階流,然後初始化高階流
fout = new FileOutputStream(tempFile);
bout = new BufferedOutputStream(fout);
int i=0;
byte[] b = new byte[1024*1024];
while((i=bin.read(b))!=-1){
bout.write(b,0,i);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
//正確的關閉方式
//高階流在關閉的時候:1.會自動關閉低階流;2.會自動重新整理快取
try {
if(bin != null){
bin.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
//bout關閉的時候,會自動重新整理緩衝區
if(bout != null){
bout.close();
}
} catch (IOException e) {
e.printStackTrace();
}
//當檔案拷貝完成之後,把臨時檔名稱改成目標檔名稱
//這裡注意:需要在流關閉的時候才可以重新命名,要不然流將執行緒鎖住,無法改名
File file1 = new File(desFile);
File file2 = new File(tempFile);
if(file2.renameTo(file1)){
System.out.println("檔案拷貝完成,"+srcFile+"拷貝到目標檔案"+desFile+"完成");
}else{
System.err.println("拷貝失敗");
}
}
}
/**
* 拷貝資料夾的功能
* @param srcPath 原資料夾
* @param desPath 目標路徑
*/
public static void copyDir(String srcPath,String desPath){
copyDir(new File(srcPath),desPath);
}
/**
* 拷貝資料夾的功能
* @param srcPath 原資料夾
* @param desPath 目標路徑
*/
public static void copyDir(File srcPath,String desPath){
//判斷srcPath是檔案還是資料夾:
if(srcPath.isFile()){
//是檔案,那麼呼叫之前拷貝檔案的方法:
copyFile(srcPath,desPath);
}else{
//是資料夾:
//從原檔案中獲取要拷貝的資料夾名稱,例如,我要拷貝jdk原始碼"D:\\file\\src",從中獲取src
String pathName = srcPath.getName();
//在目標路徑中建立要拷貝的目錄,例如在"d:\\"建立"src"目錄:
String dPath = desPath+File.separator+pathName; //"d:\\src"
File file = new File(dPath);
file.mkdirs();
//獲取原資料夾中所有子檔案(夾)
File[] files = srcPath.listFiles();
//遍歷存放子檔案的陣列,一個個的拷貝到目標路徑中,也就是dPath
for(File file1:files){
copyDir(file1,dPath); //遞迴呼叫
}
}
}
public static void main(String[] args){
//String file = "D:\\tools\\aa.txt";
//String file = "D:\\tools\\Navicat.rar";
//copyFile(file,"d:\\abc");
String file = "D:\\file\\src";
copyDir(file,"d:\\");
}
}
這裡檔案或資料夾拷貝告一段落了,反觀之前的FileOutputStream這個低階流在實現寫的時候,有一些瑕疵,模型如下:
package com.Jevin.io;
import java.io.*;
public class ByteStreamTest {
public static void main(String[] args) {
writeFile3();
}
/**
* 在FileOutputStream上接一個高階流PrintStream輸出
*/
public static void writeFile3(){
FileOutputStream fout = null;
PrintStream ps = null;
try {
fout = new FileOutputStream("d:\\dd.txt",true);
ps = new PrintStream(fout);
for(int i=0;i<1000;i++){
String str = i+"在FileOutputStream上接一個高階流PrintStream輸出";
//為了方便操作,ps.println(str)/ps.close()暫時不需要處理異常;
ps.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally{
if(ps != null){
ps.close();
}
}
}
}
================================================================================================
以上講的都是位元組流,從這裡我們開始講講字元流的使用。
首先是使用字元流去讀取檔案中的資料,模型如下:
以下是程式碼演示:
package com.Jevin.io;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class CharacterStreamTest {
public static void main(String[] args){
//readFile1();
readFile2();
}
/**
* 用FileReader讀取檔案的內容,一個一個字元的讀取
*/
public static void readFile1(){
FileReader fr = null;
try {
fr = new FileReader("d:\\aa.txt");
int i = 0;
//讀取一個字元,當做int返回,直到檔案末尾沒有字元時返回-1;
while((i=fr.read()) != -1){
//char -> int -> char
System.out.print((char)i);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if(fr != null){
fr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 用FileReader讀取檔案的內容,一次讀取多個字元的資料
*/
public static void readFile2(){
FileReader fr = null;
try {
fr = new FileReader("d:\\aa.txt");
int i = 0;
char[] c = new char[1024];
//讀取多個字元,儲存到陣列中,i是讀取到的字元的數量
while((i=fr.read(c)) != -1){
//char[] -> String
String str = new String(c,0,i);
System.out.print(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if(fr != null){
fr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
但是這樣用低階流去讀取檔案是字元陣列,然後還要手動轉換為字串,這樣在讀取大檔案時效率不高,這時我沒需要在低階流上接一個高階流,利用高階流的快取一行一行的讀取資料,效率大大提高,一下模型演示:
下面是程式碼演示:
package com.Jevin.io;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class CharacterStreamTest {
public static void main(String[] args) {
readFile3();
}
/**
* 用FileReader和BufferReader讀取檔案中的內容
*/
public static void readFile3() {
FileReader fr = null;
BufferedReader br = null;
try {
fr = new FileReader("d:\\aa.txt");
br = new BufferedReader(fr);
String str = null;
while ((str = br.readLine()) != null) {
System.out.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
這裡簡單的位元組流和字元流就介紹到這裡,接下來介紹一個有意思的流:RandomAccessFile,它可以從檔案的任意位置讀,也可以從檔案的任意位置寫。寫個功能有什麼用呢?換言之:可以將一個大檔案切割成多個小檔案分別讀寫。
模型如下所示:
程式碼如下所示:
package com.Jevin.io.demo;
import java.io.File;
/**
* 檔案拷貝包工頭
*/
public class FileCopyContractor {
private File srcFile; //原始檔
private String desFile; //目標檔案
private String tempFile; //拷貝過程中的臨時檔案
private int splitCount; //檔案切分的份數
public FileCopyContractor(){}
public FileCopyContractor(File srcFile, String desPath, int splitCount) {
super();
this.srcFile = srcFile;
this.splitCount = splitCount;
//組織目標檔案:
String fileName = srcFile.getName();
this.desFile = desPath + File.separator + fileName;
this.tempFile = desFile + ".td";
}
public FileCopyContractor(String srcFile, String desPath, int splitCount) {
this(new File(srcFile),desPath,splitCount);
}
/**
* 包工頭開始工作:
*/
public void start(){
//獲取原檔案的大小:
long fileSize = srcFile.length();
System.out.println("檔案的大小是:"+fileSize);
//根據切分的份數和原始檔的大小,計算每個工人的平均工作量
long perWorkerSize = fileSize/this.splitCount;
//計算第一個工人的開始位置和結束位置:
long startPost = 0L;
long endPost = perWorkerSize;
//包工頭建立多個工人:
for(int i=0;i<this.splitCount;i++){
//建立工人物件:
FileCopyWorker fileCopyWorker = new FileCopyWorker("工人-"+i,srcFile,tempFile,startPost,endPost);
//工人開始工作:
fileCopyWorker.work();
//包工頭計算下一個工人的開始位置和結束位置:
startPost = endPost;
endPost = startPost + perWorkerSize;
//如果是最後一個工人,則做到最後;
if(i == this.splitCount-2){
endPost = fileSize;
}
}
//所有工人完成工作之後,把臨時檔名稱改成目標檔名稱:
File file1 = new File(this.tempFile);
File file2 = new File(this.desFile);
if(file1.renameTo(file2)){
System.out.println(this.srcFile + "拷貝到"+this.desFile+"完成");
}else{
System.out.println("重新命名檔案失敗");
}
}
}
package com.Jevin.io.demo;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* 檔案拷貝工人
*/
public class FileCopyWorker {
private String name; //工人名稱
private File srcFile; //原始檔
private String desFile; //目標檔案
private long startPost; //開始位置
private long endPost; //結束位置
private long copyedPost; //已經拷貝的位置
public FileCopyWorker(String name, File srcFile, String desFile, long startPost, long endPost) {
super();
this.name = name;
this.srcFile = srcFile;
this.desFile = desFile;
this.startPost = startPost;
this.endPost = endPost;
this.copyedPost = this.startPost; //初始化拷貝位置即為初始位置
System.out.println(name+"[開始位置是:"+this.startPost+",結束位置是:"+this.endPost+"]");
}
/**
* 工人開始工作
*/
public void work(){
RandomAccessFile rin = null; //讀資料流
RandomAccessFile rout = null; //寫資料流
try {
rin = new RandomAccessFile(this.srcFile,"r");
rout = new RandomAccessFile(this.desFile,"rw");
//定位讀寫的位置:
rin.seek(this.startPost); //開始讀的位置
rout.seek(this.startPost); //開始寫的位置
byte[] b = new byte[1024*1024];
int i = 0;
//當已經拷貝的位置小於結束位置,並且未拷貝到檔案結尾,就一直迴圈拷貝下去:
while((this.copyedPost < this.endPost) && (i=rin.read(b)) != -1){
if((this.copyedPost + i) > this.endPost){
i = (int) (this.endPost - this.copyedPost);
}
rout.write(b,0,i);
this.copyedPost += i;
System.out.println(name+"正在工作,已經拷貝的位置是:"+this.copyedPost+",結束位置是:"+this.endPost);
}
System.out.println(name+"結束工作,已經拷貝的位置是:"+this.copyedPost+",結束位置是:"+this.endPost);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if(rin != null){
rin.close();
}
if(rout != null){
rout.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package com.Jevin.io.demo;
public class MainTest {
public static void main(String[] args){
String file = "D:\\tools\\Navicat.rar";
FileCopyContractor fileCopyContractor = new FileCopyContractor(file,"d:\\",15);
fileCopyContractor.start();
}
}
“流”暫時就到這裡吧,又補充的再繼續吧!