用java寫檔案輸入輸出流,實現複製貼上的方法
java中檔案輸入輸出流是FileInputStream和FileOutputStream,檔案輸入流從檔案系統中的某個檔案中獲得輸入位元組,然後可以用輸出流將資料寫入檔案中。
首先建立兩個流的物件:
FileInputStream的構造方法有三種過載方式,常用的是FileInputStream(File file)和FileInputStream(String path),前者需要傳遞的是一個File物件,輸入流將直接與這個檔案相關聯,獲取這個檔案的資料;後者需要傳遞的引數是檔案的路徑名,輸入流則將關聯此路徑下的檔案。
FileOutputStream的構造方法有五種過載形式,常用的是FileOutputStream(File file),FileOutputStream(File file, boolean append),FileOutputStream(String name)和FileOutputStream(String name, boolean append),第一個和第三個與FileInputStream相同,都是將檔案或路徑對應的檔案與輸出流相關聯,其他兩種的引數多了一個布林型的append,是指定輸出流是否追加的,如果為true
無論是建立FileInputStream還是建立FileOutputStream時,如果指定檔案不存在,或者它是一個目錄,而不是一個常規檔案,抑或因為其他某些原因而無法開啟進行讀取,則丟擲 FileNotFoundException異常,所以建立這兩類物件時,應該處理這些異常,一般將它們放到try/catch塊中進行捕獲。
進行檔案的讀寫操作時首先是關聯好讀取的檔案和要寫出的檔案,接下來就需要呼叫檔案輸入輸出流中的幾個重要的方法,輸入流中的read()方法讀取資料,輸出流的write()方法輸出資料,呼叫這兩個方法時需要進行異常捕獲IO異常。
read()有幾種過載方式,其中常用的有int read()和int read(byte[] bytes),前者是一次讀取一個位元組,讀取的資料作為返回值返回,如果讀到檔案末尾則返回-1,後者是從此輸入流中將最多bytes.length
個位元組的資料讀入一個 byte 陣列中,返回讀入緩衝區的位元組總數,如果因為已經到達檔案末尾而沒有更多的資料,則返回-1。這如同檔案是一缸水,前者是一滴一滴去取,後者是用一個容器去取,顯然前者更安全,後者更快速。
同樣的write()也有void write(int i)和void write(byte[] bytes)兩種過載,前者是將指定位元組寫入此檔案輸出流,後者是將bytes.length
另外檔案輸入流和檔案輸出流中都有一個close()的方法,這個方法用來關閉流物件並釋放與此流有關的所有系統資源,所以每次在使用完流物件後應注意分別呼叫檔案輸入流和檔案輸出流的close()方法,此方法有可能拋異常,必須進行捕捉。
使用以上的內容我們可以實現簡單的檔案複製貼上。
複製貼上的思路是:
1、建立輸出流物件,並與需要複製的檔案相關聯。因為過載方法有幾種,所以可以按需要選擇。
如:
- FileInputStream fis = new FileInputStream("C:\\Users\\lenovo\\Desktop\\新建文字文件.txt");
- File file = new File("C:\\Users\\lenovo\\Desktop\\新建文字文件.txt");
- FileInputStream fis = new FileInputStream(file);
如:
- FileOutputStream fos = new FileOutputStream("C:\\Users\\lenovo\\Desktop\\123.txt");
- File file = new File("C:\\Users\\lenovo\\Desktop\\123.txt");
- FileOnputStream fos = new FileOnputStream(file);
2、讀取檔案並輸出
這裡可以用一個位元組一個位元組讀取寫出或用位元組陣列來讀寫。
- //寫法一:一個位元組一個位元組讀取檔案並輸出
- int i = fis.read();
- while(i!=-1)
- {
- fos.write(i);
- i = fis.read();
- }
- //寫法二:用位元組陣列來作為緩衝區進行讀寫
- byte[] bytes = newbyte[fis.available()];
- fis.read(bytes);
- fos.write(bytes);
while(fis.read()!=-1)
{
fos.write(fis.read());
}
則會出現錯誤,因為在while括號裡面讀一次後如果檔案沒有結束進入迴圈則寫出的是檔案的下一個資料(因為剛才while括號裡面讀了一個,就要進行下一個)
上面的寫法二可以看到位元組陣列的引數這個地方用的是available(),這個方法返回的是下一次對此輸入流呼叫的方法可以不受阻塞地從此輸入流讀取(或跳過)的估計剩餘位元組數,那上面的用法就是一次讀完檔案所有的資料,放在bytes裡面,也就是上面說的一次性把水缸裡面的水都取出來,這種方法一般不推薦用,因為水缸的水是固定的,但在其他一些情況下,像兩個人打電話說話的人像輸入流,聽的人像輸出流,這時呼叫available()方法就是要將對方的話全部取出來,一次性聽完,然而你並不知道對方有多少話要說。(這種情況在網路通訊那一塊會涉及),這時就不能使用這種方法了,所以bytes的大小應該設定一個合適的值,水缸的水一盆一盆來取。
比如可以將fis.available()改成1024,這樣取的時候就是1024的位元組來取,但是這時又有一個問題了,當要複製的檔案大小不是1024個位元組的整數倍的時候,呼叫write()方法還是會按bytes的長度寫入1024個位元組(用盆取水,最後缸裡的水不足一盆還是認為取了一盆),所以粘貼後的檔案往往大於複製的檔案,要解決這個辦法需要用read()和write()的第三個過載方式int read(byte[ ] b, int off, int len)和voidwrite(byte[ ] b, int off, int len)
- byte[] bytes = newbyte[1024];
- int i = fis.read(bytes,0,1024);
- while(i!=-1)
- {
- fos.write(bytes,0,i);
- i = fis.read(bytes,0,1024);
- }
最後再呼叫fis.close()和fos.close()關閉流,這樣就可以實現簡單的檔案複製了。
程式碼實現:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class F {
//程式碼實現檔案的複製
//原始檔,與複製檔案
File srcFile,coyFile;
//輸入輸出流
InputStreamReader read;
OutputStreamWriter write;
public static void main(String[] args) {
String path=null,path1=null;
if(args.length>0)
{
path=args[0];
path1=args[1];
}
try {
new F(path, path1);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public F(String path,String path1) throws IOException
{
//建立檔案物件
srcFile=new File(path);
//讀取位元組快取
int i;
//判斷檔案是否存在
if(srcFile.exists())
{
//判斷檔案是否為資料夾
if(srcFile.isFile())
{
//對檔案進行讀取
read=new InputStreamReader(new FileInputStream(srcFile));
coyFile=new File(path1);
coyFile.createNewFile();
write=new OutputStreamWriter(new FileOutputStream(coyFile));
while((i=read.read())!=-1)
{
write.write(i);
}
//關閉物件流
write.close();
read.close();
}else
{
System.out.println("暫時不支援複製資料夾!");
}
}else
{
System.out.println("找不到指定路徑下的檔案!");
}
}
}