1

I have a function that copies binary file

    public static void copyFile(String Src, String Dst) throws FileNotFoundException, IOException {
    File f1 = new File(Src);
    File f2 = new File(Dst);
    FileInputStream in = new FileInputStream(f1);

    FileOutputStream out = new FileOutputStream(f2);

    byte[] buf = new byte[1024];
    int len;
    while ((len = in.read(buf)) > 0) {
        out.write(buf, 0, len);
    }
    in.close();
    out.close();
}

and the second function

    private String copyDriverToSafeLocation(String driverPath) {
    String safeDir = System.getProperty("user.home");
    String safeLocation = safeDir + "\\my_pkcs11tmp.dll";
    try {
        Utils.copyFile(driverPath, safeLocation);
        return safeLocation;
    } catch (Exception ex) {
        System.out.println("Exception occured while copying driver: " + ex);
        return null;
    }
}

The second function is run for every driver found in the system. The driver file is copied and I am trying to initialize PKCS11 with that driver. If initialization failed I go to next driver, I copy it to the tmp location and so on.

The initialization is in try/catch block After the first failure I am no longer able to copy next driver to the standard location.

I get the exception

Exception occured while copying driver: java.io.FileNotFoundException: C:\Users\Norbert\my_pkcs11tmp.dll (The process cannot access the file because it is being used by another process)

How can I avoid the exception and safely copy the driver file?

For those curious why am I trying to copy the driver ... PKCS11 has nasty BUG, which prevents using drivers stored in the location that has "(" in the path ... and this is a case I am facing.

I will appreciate your help.

norbi771
  • 814
  • 2
  • 12
  • 29
  • Thank all of you for your comments. I don't want to use extra libraries like apache as finally this code is to be run by applet. All the rest I tried, but it seems that dest file is in use. I even tried nasty solution and enumerated drivers (and added the number to dst file name), but when I run this by applet dst file is in use, when the applet is run more then once. – norbi771 Jun 14 '12 at 17:12

5 Answers5

1

I would move the try-catch block into the copyFile method. That way you can properly handle closing the InputStreams (which is probably causing the JVM to hold onto the file handle). Something like this:

public static void copyFile(String Src, String Dst) {
    try {
        File f1 = new File(Src);
        File f2 = new File(Dst);
        FileInputStream in = new FileInputStream(f1);

        FileOutputStream out = new FileOutputStream(f2);

        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
    }
    catch(Exception e) {
        System.out.println("Exception occured while copying driver: " + ex);
    }
    finally {
        in.close();
        out.close();
    }
}

Then you can remove the try-catch from the copyDriverToSafeLocation method.

Poindexter
  • 2,396
  • 16
  • 19
1

Or there's the Java 7 Way:

public static void copyFile(String src, String dst) throws FileNotFoundException, IOException {
  try (FileInputStream in = new FileInputStream(new File(src))) {
    try (FileOutputStream out = new FileOutputStream(new File(dst))) {
      byte[] buf = new byte[1024];
      int len;
      while ((len = in.read(buf)) > 0) {
        out.write(buf, 0, len);
      }
    }
  }
}

Edit: And the Java 7 NIO way.

public static void copyFile(String src, String dst) throws FileNotFoundException, IOException {
  copyFile(new File(src), new File(dst));
}

public static void copyFile(File src, File dst) throws FileNotFoundException, IOException {
  try (FileInputStream in = new FileInputStream(src)) {
    try (FileOutputStream out = new FileOutputStream(dst)) {
      copyFile(in, out);
    }
  }
}

public static void copyFile(FileInputStream in, FileOutputStream out) throws IOException {
  FileChannel cin = in.getChannel();
  FileChannel cout = out.getChannel();
  cin.transferTo(0, cin.size(), cout);
}
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
0

I would choose to go with Apache Commons IO and their FileUtils.copyFile() routine(s).

Standard concise way to copy a file in Java?

Community
  • 1
  • 1
Justin Jasmann
  • 2,363
  • 2
  • 14
  • 18
0

I'm not sure why a problem with one file would prevent copying a different file. However, not closing a file when an exception occurs could definitely cause problems. Use try...finally to make sure you call close on every file you open.

Chris
  • 4,734
  • 2
  • 19
  • 26
0

If the file is used by an other process and locked, there is no generic solutions to be able to access it. You best chance is to use FileLock but it's plateform-dependant, read the documentation, it's written that the results are "advisory", so be carefull. you can also take a look at the ReentrantReadWriteLock class.

alain.janinm
  • 19,951
  • 10
  • 65
  • 112