Search code examples
javaandroidpermissionsintentfilter

File not found exception for text file which exists


I want to open a .txt file with an intent-filter, but I get this exception

W/System.err: java.io.FileNotFoundException: file:/storage/emulated/0/Download/ApplicationProposal.txt: open failed: ENOENT (No such file or directory)

in the following line:

FileInputStream fis = new FileInputStream(note);

The path is, for example:

file:///storage/emulated/0/Download/filename.txt

For permissions I asked like that:

public void requestWritePermissions() {
    if(ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
        if(ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)){
            Toast.makeText(getApplicationContext(), "Permission needed to export Notes to SD-Card!", Toast.LENGTH_LONG);
        }
        else{
            ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSIONS_REQUEST_STORAGE);
        }
    }
}

It's called in the onCreate() of my main activity

EDIT: Further information:

This is how I call the method to read the file

File toOpen = new File(intent.getData().toString());
String text = noteHandler.loadNote(toOpen);

The loadNote method looks like that:

public String loadNote(File note){
        String content = "";

        try {
            FileInputStream fis = new FileInputStream(note);
            BufferedReader reader = new BufferedReader(new InputStreamReader(fis));

            StringBuilder data = new StringBuilder();
            String line;

            do{
                line = reader.readLine();
                if (line != null)
                    data.append(line).append("\n");
            }
            while (line != null);

            content = data.toString();

            reader.close();
            fis.close();

        } catch (Exception e){
            e.printStackTrace();
            Log.e("ERROR", e.toString());
        }

        return content;
    }

Solution

  • You are passing a URL string and trying to use it as if it was a pathname. Naturally, the OS tries to interpret it as a pathname ... and it can't resolve it.

    Assuming that you started out with a URL, what you should do is something like this:

        URL toOpen = new URL(intent.getData().toString());
        String text = noteHandler.loadNote(toOpen);
    
    public String loadNote(URL note){
        String content = "";
    
        try {
            InputStream is = note.openStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            ....
    

    Note that string bashing a "file:" URL is a bit risky:

    • In some contexts, the URL could possibly have a different protocol. If you assumed that the URL always started with "file://" you would probably end up with a non-resolvable path.
    • Even with a wel-formed "file:" URL, it is possible that certain characters in the URL have been %-encoded; e.g. a space in the original pathname becomes %20 in a URL. The OS probably doesn't know what to make of %-encoding, and you will get a non-resolvable path ... again.

    (These caveats may not apply in your use-case, but they do in general)