0

I am trying to write a file to internal device storage on my phone (and on user's phones in the future). I was watching a video tutorial from 2016 (https://www.youtube.com/watch?v=EhBBWVydcH8) which shows how he writes output to a file very simply. If you want to see his code, skip forward to 8:23.

Anyway, I basically tried his code, then since that didn't work, I figured would search around.

Apparently, to create a file, I need these lines of code:

String filename = "textfile.txt";
File file = new File(filename);

file.mkdirs();
file.createNewFile();

On the second line, file.createNewFile(), I get the below error:

java.io.IOException: Read-only file system
  at java.io.UnixFileSystem.createFileExclusivel
  at java.io.UnixFileSystem.createFileExclusivel
  at java.io.File.createNewFile(File.java:948)
  etc......

And then, if I run my code just by using the lines of code from the tutorial, I get a Null pointer.

Code:

          try {
            FileOutputStream fos = openFileOutput(filename, Context.MODE_PRIVATE);
            fos.write(IDNum.getBytes());
            fos.close();
            System.out.println("Wrote STuff Outputtt?");
        } catch (Exception e) {
            e.printStackTrace();
        }

Error:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.FileOutputStream android.content.Context.openFileOutput(java.lang.String, int)' on a null object reference
  at android.content.ContextWrapper.openFileOutput(ContextWrapper.java:199)
  at com.lecconnect.lockoutdemo.FileManager.AddUser(FileManager.java:37)

Line 37 is the first line in the try/catch.

Please let me know if you require any additional information to assist me. Your replies are greatly appreciated.

  • Your `FileManager` class apparently extends a class that you should not be instantiating with `new`; like `Activity` or `Service`. I assume you did this so that `openFileOutput()` would resolve. You can't do that, as the `Context` that is ultimately called upon will be null, as you can see in the trace. If you want to keep that method in a separate class, add a `Context` parameter to `AddUser()`, and pass one in from your `Activity`, `Service`, etc. I should also mention that `openFileOutput()` opens files in your app's private, internal storage, which might not be what you're expecting. – Mike M. Jun 03 '17 at 03:49
  • @MikeM. I removed "...extends Activity" as you assumed was there by resolving "openFileOutput()." I am passing context through my other activity now. The line causing the error is rewritten as "FileOutputStream fos = context.openFileOutput(filename, Context.MODE_PRIVATE);" It seems that my code does not crash, but I cannot find my text file anywhere lol. I went to Internal_Storage/Android/Data/com.outputproject/demo, where the file should be, and it is not there. This is what you meant by internal private storate, right? Or is a private file not able to be seen? This location is okay. –  Jun 03 '17 at 04:18
  • Using append mode changes nothing - It looks like everything runs fine, but can't find the .txt document's location. Or maybe I misused context? –  Jun 03 '17 at 04:25
  • Yeah, internal/external storage is a confusing thing on Android. Internal storage, in Android terms, means the private app storage area that only the app can (normally) access. External storage is the area that is publicly accessible. Neither of those terms has anything to do with whether that storage is physically inside the device, or on a removable SD card, for example. If you want to write to a file that you can get to with a regular file explorer, the root directory for that area will be `Environment.getExternalStorageDirectory()`. You will need the `WRITE_EXTERNAL_STORAGE` permission. – Mike M. Jun 03 '17 at 04:28
  • You can use standard file I/O with that, creating a `File` where needed, then creating a `FileOutputStream` on that. The methods you might call on a `Context` to get a file stream are going to be in your app's internal storage, so that's not what you want. – Mike M. Jun 03 '17 at 04:35
  • That made it through my brain. Thanks! I will probably have to write something to read the file to test then –  Jun 03 '17 at 04:36
  • No problem. The easiest thing to start with would probably be to just create a file right in `Environment.getExternalStorageDirectory()`, write to that, then see if you can find it. Any basic file explorer app should be able to see it there, and it would likely be the default/root folder it opens. Alternatively, you should be able to see it in your IDE's explorer, though I'm not familiar enough with that to give specifics. – Mike M. Jun 03 '17 at 04:40
  • Btw, heads up on that `WRITE_EXTERNAL_STORAGE` permission. It's a dangerous permission, and needs to be requested at runtime on Marshmallow and above, if you're `targetSdkVersion` is >=23. For your initial testing here, though, you could just drop your `targetSdkVersion` to 22 or below, or possibly manually enable the permission in the app's Settings page on the device/emulator. http://stackoverflow.com/questions/32635704 – Mike M. Jun 03 '17 at 04:43
  • Thanks again for everything - I'll get back on this tomorrow and see what I come up with. –  Jun 03 '17 at 06:36

1 Answers1

4

It is important to separate the directory and the file itself.

In your code, you call mkdirs on the file you want to write, which is incorrect usage because mkdirs makes your file into a directory. You should call mkdirs for the directory only, so it will be created if it does not exist, and the file will be created automatically when you create a new FileOutputStream object for this file.

Try this one:

File directory = getFilesDir(); //or getExternalFilesDir(null); for external storage
File file = new File(directory, fileName);

FileOutputStream fos = null;
try {
    fos = new FileOutputStream(file);
    fos.write(IDNum.getBytes());
    fos.close();
} catch (IOException e) {
    e.printStackTrace();
}
double-beep
  • 5,031
  • 17
  • 33
  • 41
Alex Kamenkov
  • 891
  • 1
  • 6
  • 16
  • 1
    Wouldn't this be writing to external storage? I want to write to internal. –  Jun 03 '17 at 04:05
  • How do I use FileInputStream to read this file now that it's in its proper directory? Thanks. – Ben Alan May 21 '21 at 16:51