content: package com.zzzmode.apkeditor.utils;
  
  import java.io.*;
  import java.nio.channels.FileChannel;
  
  /**
   * Created by zl on 15/9/7.
   */
  public class FileUtils {
      private static final long FILE_COPY_BUFFER_SIZE = 1024 * 1024 * 1;
  
      public static FileInputStream openInputStream(final File file) throws IOException {
          if (file.exists()) {
              if (file.isDirectory()) {
                  throw new IOException("File '" + file + "' exists but is a directory");
              }
              if (file.canRead() == false) {
                  throw new IOException("File '" + file + "' cannot be read");
              }
          } else {
              throw new FileNotFoundException("File '" + file + "' does not exist");
          }
          return new FileInputStream(file);
      }
  
      public static void copyFile(final File srcFile, final File destFile) throws IOException {
          checkFileRequirements(srcFile, destFile);
          if (srcFile.isDirectory()) {
              throw new IOException("Source '" + srcFile + "' exists but is a directory");
          }
          if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath())) {
              throw new IOException("Source '" + srcFile + "' and destination '" + destFile + "' are the same");
          }
          final File parentFile = destFile.getParentFile();
          if (parentFile != null) {
              if (!parentFile.mkdirs() && !parentFile.isDirectory()) {
                  throw new IOException("Destination '" + parentFile + "' directory cannot be created");
              }
          }
          if (destFile.exists() && destFile.canWrite() == false) {
              throw new IOException("Destination '" + destFile + "' exists but is read-only");
          }
          doCopyFile(srcFile, destFile);
      }
  
      private static void doCopyFile(final File srcFile, final File destFile)
              throws IOException {
          if (destFile.exists() && destFile.isDirectory()) {
              throw new IOException("Destination '" + destFile + "' exists but is a directory");
          }
  
          FileInputStream fis = null;
          FileOutputStream fos = null;
          FileChannel input = null;
          FileChannel output = null;
          try {
              fis = new FileInputStream(srcFile);
              fos = new FileOutputStream(destFile);
              input = fis.getChannel();
              output = fos.getChannel();
              final long size = input.size(); // TODO See IO-386
              long pos = 0;
              long count = 0;
              while (pos < size) {
                  final long remain = size - pos;
                  count = remain > FILE_COPY_BUFFER_SIZE ? FILE_COPY_BUFFER_SIZE : remain;
                  final long bytesCopied = output.transferFrom(input, pos, count);
                  if (bytesCopied == 0) { // IO-385 - can happen if file is truncated after caching the size
                      break; // ensure we don't loop forever
                  }
                  pos += bytesCopied;
              }
          } finally {
              IOUtils.closeQuietly(output, fos, input, fis);
          }
  
          final long srcLen = srcFile.length(); // TODO See IO-386
          final long dstLen = destFile.length(); // TODO See IO-386
          if (srcLen != dstLen) {
              throw new IOException("Failed to copy full contents from '" +
                      srcFile + "' to '" + destFile + "' Expected length: " + srcLen + " Actual: " + dstLen);
          }
  
      }
  
      private static void checkFileRequirements(File src, File dest) throws FileNotFoundException {
          if (src == null) {
              throw new NullPointerException("Source must not be null");
          }
          if (dest == null) {
              throw new NullPointerException("Destination must not be null");
          }
          if (!src.exists()) {
              throw new FileNotFoundException("Source '" + src + "' does not exist");
          }
      }
  
  }
  