Copy file with stream

The following example shows how to copy a file using streams.

private void copyWithStreams(File aSourceFile, File aTargetFile, boolean aAppend) { log("Copying files with streams."); ensureTargetDirectoryExists(aTargetFile.getParentFile()); InputStream inStream = null; OutputStream outStream = null; try{ try { byte[] bucket = new byte[32*1024]; inStream = new BufferedInputStream(new FileInputStream(aSourceFile)); outStream = new BufferedOutputStream(new FileOutputStream(aTargetFile, aAppend)); int bytesRead = 0; while(bytesRead != -1){ bytesRead = inStream.read(bucket); //-1, 0, or more if(bytesRead > 0){ outStream.write(bucket, 0, bytesRead); } } } finally { if (inStream != null) inStream.close(); if (outStream != null) outStream.close(); } } catch (FileNotFoundException ex){ log("File not found: " + ex); } catch (IOException ex){ log(ex); } } private void ensureTargetDirectoryExists(File aTargetDir){ if(!aTargetDir.exists()){ aTargetDir.mkdirs(); } } private static void log(Object aThing){ System.out.println(String.valueOf(aThing)); } 

For the code snippet above, I feel embarrassed at four points:

1) The bucket is allocated as byte [] bucket = new byte [32 * 1024]; Is there any criterion for choosing the size, for example 32 * 1024

2) Why should he β€œcatch” here? Is there a rule to include catches in writing?

3) I also do not really understand how to use "try" here. It seems the author is using a nested attempt in this program.

0
source share
3 answers

1) There is no criterion for determining the size of your byte array. In this code, it used 32 kbytes, but you can use any value. The size of the byte array and the size of your file determine how many times you will read the file, more buffers lead to fewer read requests, but not necessary if you are working with small files.

2) Whenever you use a method in Java that can throw an exception, you need to catch that exception and do something with it. You can handle the exception in your code (usually print a stack trace for debugging purposes) or throw it, which means that when someone uses your code, you need to catch the exception of your code.

3) What he did was to catch two possible exceptions and indicate what was happening. Since FileNotFoundException extends an IOException , it can just use one try and catch only an IOException , it encoded this method to find out if the IOException FileNotFoundException or any other IOException . Personally, I will not write code in the same way as the author did, it is easy to read.

Rewriting the code may make it easier to understand attempts and traps:

  System.out.println("Copying files with streams."); InputStream inStream = null; OutputStream outStream = null; try { inStream = new BufferedInputStream(new FileInputStream(aSourceFile)); outStream = new BufferedOutputStream(new FileOutputStream(aTargetFile, aAppend)); } catch (FileNotFoundException ex){ // TODO Handle FileNotFoundException ex.printStackTrace(); } try { byte[] bucket = new byte[32*1024]; int bytesRead = 0; while(bytesRead != -1){ bytesRead = inStream.read(bucket); //-1, 0, or more outStream.write(bucket, 0, bytesRead); } } catch (IOException ex){ // TODO Handle IOException ex.printStackTrace(); } finally { try { if (inStream != null) inStream.close(); if (outStream != null) outStream.close(); } catch (IOException ex){ // TODO Handle IOException ex.printStackTrace(); } } 

He does the same.

0
source
  • We assume that you cannot fit the entire file into memory conveniently, so we select a small piece at a time, process it, and then capture the next fragment. In this case, we use 32 kilobytes. You can use more or less, but working (small) multiple sector sizes of the hard drive (usually 4kb) will be more efficient and will result in fewer I / O operations.

  • If you throw an exception or call a method that throws an exception, you must handle it. You can combine it with a block of try{} and catch{} (or finally{} ) try{} , or you can throw an exception up in any method called this. In this case, you have a try{} , so you have accompanying catch and finally statements.

  • The author did something unnecessary: ​​he could use one try{} , and then placed the finally{} block after the catch{} statements. Instead, the inner try{} passes the exception to the outer try{} after the finally{} block is executed. After that, catch{} blocks are activated, depending on the type of Exception .

+1
source

1) 32 * 1024 is allocated up to 32 kilobytes, which, in my opinion, is the default unit size when formatting an NTFS volume. While agreeing with the underlying file system, there are probably some performance improvements because you do not overwrite the disk sectors if they are not cached properly. The larger the buffer, the smoother the operation. You cannot use huge buffers on smaller devices though (phones come with more and more memory)

2) The catch here can be very annoying. If you ask to copy the file and the source file does not exist, all you get is a log, and the program that calls this method may assume that it worked. This method can repeatedly throw an exception, and the calling program will deal with a file that is not found. The same goes for I / O issues.

3) Finally, it is important because you want to ensure that resources are shut down no matter what happens. In fact, there is no execution time when nested try statements have private resources after other exceptions are logged. (An insignificant point, if there is an exception throw when closing inStream, outStream will not be closed, and any other exception will be lost). The programmer might have thought that he looked cleaner to close the theses next to reading and writing, but they could well be moved into an external attempt.

+1
source

Source: https://habr.com/ru/post/1390023/


All Articles