6

I have the following code where I need to catch AccessDeniedException exception

import java.io.PrintWriter;
import java.io.IOException;
import java.nio.file.AccessDeniedException;

class MyFileClass {
  public void write()
    throws IOException
  {
    PrintWriter out = new PrintWriter("sample.txt");

    out.printf("%8.2f\n", 3.4);

    out.close();

  }
}

public class MyClass {
  public static void main(String[] args)
    throws Exception
  {
    try {
      MyFileClass mf = new MyFileClass();
      mf.write();
    } catch (AccessDeniedException e) {
      print("Access denided");
    }
    catch (FileNotFoundException e) {
      print("File not found");
    }
  }
}

In case sample.txt is read only, I get output as "file not found" rather "Access denided". I would like to understand what is the reason for this? Also, is the above structure for catching AccessDeniedException correct?

P̲̳x͓L̳
  • 3,615
  • 3
  • 29
  • 37
Akg
  • 349
  • 1
  • 3
  • 15

2 Answers2

7

AccessDeniedException is only thrown by the new file API; the old file API (which you use with this PrintWriter constructor) only knows how to throw FileNotFoundException even if the real filesystem-level problem is not "the file does not exist".

You have to use the new API to open an output stream to the destination file; then you can have meaningful exceptions:

// _will_ throw AccessDeniedException on access problems
final OutputStream out = Files.newOutputStream(Paths.get(filename));
final PrintWriter writer = new PrintWriter(out);

More generally, the new file API defines FileSystemException (inheriting IOException), which all new, meaningful exceptions defined by the new API inherit.

This means among other things that you can clearly separate, in catch clauses, what is caused by filesystem-level errors and "real" I/O errors, which you can't do with the old API:

try {
    // some new file API operation
} catch (FileSystemException e) {
    // deal with fs error
} catch (IOException e) {
    // deal with I/O error
}
fge
  • 119,121
  • 33
  • 254
  • 329
  • And OP is using `import java.nio.file.AccessDeniedException;` Is that necessary? – AJ. Mar 14 '14 at 11:18
  • I can't quite make sense of your question... Yes it is, you need to import the exception and this is the package it is defined in... – fge Mar 14 '14 at 11:20
1

There is NO such AccessDeniedException in PrintWriter.

SecurityException is the exception thrown by PrintWriter

If a security manager is present and checkWrite(file.getPath()) denies write access to the file

AJ.
  • 4,526
  • 5
  • 29
  • 41
  • 1
    Sorry but unfortunately, that is wrong; the old file API is broken and _will_ throw `FileNotFoundException` if you don't have any access... – fge Mar 14 '14 at 11:11
  • 1
    @fge Please provide some docs. I don't know that. It will be helpful to me also. – AJ. Mar 14 '14 at 11:12
  • Eh, unfortunately that has never been documented properly. Except for the fact that `AccessDeniedException` did _not_ exist in Java 6, and for compatibility reasons they couldn't change the exceptions thrown – fge Mar 14 '14 at 11:15
  • @fge It's not that simple. You are both half right. A SecurityException is thrown if you're running under a security manager and your .policy file doesn't allow access to the file. A FileNotFoundException is thrown if the *operating system* doesn't allow access to the file. – user207421 Mar 14 '14 at 11:18
  • @AJ - Accepting your answer, now I understand that PrintWriter doesn't throw AccessDeniedException. However, FileNotFoundException will be caught when client is trying to write in a file which exists on the specified path but has read only access. – Akg Mar 14 '14 at 11:18
  • @EJP yes, which is why I say the old file API is terminally broken: `FileNotFoundException` is useless – fge Mar 14 '14 at 11:21
  • @fge I'm not interested in your views on the old File API. I am only interested in correcting your implication that this answer is wrong. It's incomplete, but not wrong. – user207421 Mar 14 '14 at 11:24