2015-10-11 55 views
0

我有這種方法是應該使用流複製文件的問題:複製的圖像。例如,當發生複製使用流 - 丟失數據/字節

public static void copyFile() { 
    String[] paths = readSrcDestFromConsole(); //returns String array with two strings - source and destination file paths 
    InputStream is = null; OutputStream os = null; 
    File src = null; File dest = null; 
    boolean error = false; 
    long elapsedTimeSeconds = 0; 
    double speed = 0; 
    try { 
     src = new File(paths[0]); 
    }catch(Exception ex){ 
     System.err.println("File read from could not be opened."); 
     error = true; 
    } 
    if(!error) { 
     try { 
      dest = new File(paths[1]); 
     }catch(Exception ex){ 
      System.err.println("File written to could not be created."); 
      error = true; 
     } 
     if(src.exists() && !error) { 
      if(dest.exists()) { 
       System.out.println("File specified already exists. Do you want to overwrite it?"); 
       if(askForOverwrite()) { // gets Y or N from console using scanner and returns a boolean 
        try { 
         is = new FileInputStream(src); 
         os = new FileOutputStream(dest); 
         System.out.println("Copying from: " + paths[0] + " to: " + paths[1]); 
         byte[] buffer = new byte[4096]; 
         double read = 0; 
         long first = 0; 
         long second = 0; 
         long startTime = System.nanoTime(); 
         while(is.read(buffer) > 0) { 
          read += buffer.length; 
          os.write(buffer); 
          first = Math.round(read/src.length() * 100); 
          if(first != second) { 
           System.out.println(first + " % copied."); 
          } 
          second = Math.round(read/src.length() * 100); 
         } 
         elapsedTimeSeconds = (System.nanoTime() - startTime)/1_000_000_000; 
         speed = (src.length()/1024/1024)/elapsedTimeSeconds; 
         is.close(); os.close(); 
        }catch(Exception ex){ 
         System.err.println("File is or has been corrupted."); 
         error = true; 
        }finally{ 
         if(!error) { 
          if(src.length() == dest.length()) { 
           System.out.println("File copied successfully."); 
           System.out.println("Total size copied: " + ((dest.length())/1024/1024) + " MB"); 
           System.out.println("Copying speed: " + speed + " MB/s" + " in " + elapsedTimeSeconds + " seconds."); 
          }else{ 
           System.err.println("Error: " + "File sizes mismatch."); 
          } 
         } 
        } 
       }else{ 
        System.out.println("File has not been rewritten."); 
       } 
      }else{ 
       try { 
        is = new FileInputStream(src); 
        os = new FileOutputStream(dest); 
        System.out.println("Copying from: " + paths[0] + " to: " + paths[1]); 
        byte[] buffer = new byte[4096]; 
        double read = 0; 
        long first = 0; 
        long second = 0; 
        long startTime = System.nanoTime(); 
        while(is.read(buffer) > 0) { 
         read += buffer.length; 
         os.write(buffer); 
         first = Math.round(read/src.length() * 100); 
         if(first != second) { 
          System.out.println(first + " % copied."); 
         } 
         second = Math.round(read/src.length() * 100); 
        } 
        elapsedTimeSeconds = (System.nanoTime() - startTime)/1_000_000_000; 
        speed = (src.length()/1024/1024)/elapsedTimeSeconds; 
        is.close(); os.close(); 
       }catch(Exception ex){ 
        System.err.println("File is or has been corrupted."); 
        error = true; 
       }finally{ 
        if(!error) { 
         if(src.length() == dest.length()) { 
          System.out.println("File copied successfully."); 
          System.out.println("Total size copied: " + ((dest.length())/1024/1024) + " MB"); 
          System.out.println("Copying speed: " + speed + " MB/s" + " in " + elapsedTimeSeconds + " seconds."); 
         }else{ 
          System.err.println("Error: " + "File sizes mismatch."); 
         } 
        } 
       } 
      } 
     }else{ 
      System.err.println("File specified does not exist."); 
     } 
    }else{ 
     System.err.println("Operation could not be completed."); 
    } 
} 

問題,.txt文件或有時是視頻文件,錯誤「文件大小不匹配」。發生。當我比較源文件和目標文件大小時,大小確實不匹配,但打開後的圖像似乎是完整的,視頻也是如此。可見的問題在於文本文件 - 在複製並丟失少量字節後,沒有內容丟失,但在文件末尾有幾行標有「NUL」的標記 - 使用Notepad ++查看這些文件。

我試着用從文件,其正常工作的copy()方法,但我不能找出爲什麼我的方法失去字節。

非常感謝您的幫助,我不能在任何地方找到一個解決方案。

+0

1)消除重複的代碼,它毀了你的生活之前。 2)'buffer.length'總是'4096' 3)你總是寫滿整個緩衝區,因此如果你讀得更少,就會增加過多的字節。 –

回答

0

的讀取循環的問題是:

while(is.read(buffer) > 0) { 
    read += buffer.length; 
    os.write(buffer); 
    first = Math.round(read/src.length() * 100); 
    if(first != second) { 
     System.out.println(first + " % copied."); 
    } 
    second = Math.round(read/src.length() * 100); 
} 

is.read(buffer)返回讀取的字節數。首先,你必須檢查它是否大於或等於零,因爲如果緩衝區大小爲零,read的合約允許它讀取0字節。但除此之外 - 你需要保持這個價值,因爲你只需要寫入你讀的字節數。

一般情況下,文件的大小是不完全的4096的倍數。因此,最後的讀取值大於4096個字節少。而且合同實際上表示,如果此時可用的字節更少,它甚至可以在此之前讀取小於4096的數據。

所以,如果你不完全寫您已經閱讀什麼,你寫將包含自上一次讀取值,或零如果文件大於4096個字節的小緩衝區的一部分。

所以正確的它:

int numRead; 

while((numRead = is.read(buffer)) >= 0) { 
    read += numRead; 
    os.write(buffer,0,numRead); 
    first = Math.round(read/src.length() * 100); 
    if(first != second) { 
     System.out.println(first + " % copied."); 
    } 
    second = Math.round(read/src.length() * 100); 
} 

不過說實在的,建議使用Files類時,您的副本包括至少一個文件,並避免java.io.File贊成Path,在Paths可用操作和Files

+0

@JamesKPolk好吧,我更正了0時允許的條件。在任何情況下,文件結尾只能以'-1'而不是'0'到達。 – RealSkeptic