1

I am trying to create a directory and then write data into a new file on an external SD card. I have previously written files successfully to internal storage, but with this I seem to have 2 problems (well, apart from myself, as this is only my second app!).

Having searched at length on stackoverflow for advice and sample code, I have built the following method:

void filewriter(String fnam,String mdata){
       if (useSD) {
           //test to see if a directory called AMJ exists on external storage and create one if it does not
           try {
               File folder = new File(Environment.getExternalStorageDirectory() + "/AMJ");
               if (folder.exists() && folder.isDirectory()) {

                   Toast.makeText(getApplicationContext(), "folder " + folder + " exists", Toast.LENGTH_LONG).show(); //##1
               } else {
                   Toast.makeText(getApplicationContext(), "folder " + folder + " does not exist", Toast.LENGTH_LONG).show(); //##2
                   folder.mkdirs();
               }
           } catch (Exception e) {
               Toast.makeText(getApplicationContext(), "Unable to find or create a directory for route data on SD card", Toast.LENGTH_LONG).show(); //##3
           }
           //create a file with file name fnam and write String mdata into the AMJ directory
           try {
               String namFile = Environment.getExternalStorageDirectory() + "/AMJ/" + fnam;
               File datfile = new File(namFile);
               Toast.makeText(getApplicationContext(), "File is:  " + datfile, Toast.LENGTH_LONG).show(); //##4
               datfile.createNewFile();
               FileOutputStream fOut = new FileOutputStream(datfile);
               OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
               myOutWriter.append(mdata);
               myOutWriter.close();
               fOut.close();
               Toast.makeText(getApplicationContext(), "Finished writing to SD", Toast.LENGTH_LONG).show(); //##5
           } catch (Exception e) {
               Toast.makeText(getApplicationContext(), "Write failure", Toast.LENGTH_SHORT).show(); //##6
           }
       }
   }

fnam and mdata are simple text such as "myfile" and "This is my test data".

The first problem is that the first time I run this I get the toast message ##2 (folder does not exist) as I expected. However, I expected a directory AMJ to be created so that the next time I run the code I would get message ##1 to say that the directory now exists, but that doesn't happen - it still says that the directory does NOT exist.

The second problem (which may of course just be a consequence of the first) is that the file creation/write does not work and I get the 'catch' message ##6 every time.

My manifest looks like this:

package="com.example.chris.filewritetests">
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

I am running this on an Android Studio emulator.

Can anyone tell me what is wrong here, please?

Chris S
  • 83
  • 3
  • 12
  • Get rid of all the `Toasts`. Use `Log.e()` to log messages to LogCat, in particular logging the specific exceptions that you are getting in your `catch` blocks. Also, there is no `android.permission.STORAGE` permission, you may not have code for [runtime permissions](https://developer.android.com/training/permissions/requesting.html), and you may eventually want to [get this file indexed so that it shows up for users](https://stackoverflow.com/questions/32789157/how-to-write-files-to-external-public-storage-in-android-so-that-they-are-visibl). – CommonsWare Jun 19 '17 at 17:20

2 Answers2

0

the directory is not created automatically. You need to create those directories call mkdir() on the file object datfile.mkdirs() change it ti

 try {
           String namFile = Environment.getExternalStorageDirectory() + "/AMJ/" + fnam;
           File datfile = new File(namFile);
           datfile.mkdirs();
           Toast.makeText(getApplicationContext(), "File is:  " + datfile, Toast.LENGTH_LONG).show(); //##4
           FileOutputStream fOut = new FileOutputStream(datfile);
           OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
           myOutWriter.append(mdata);
           myOutWriter.close();
           fOut.close();
           Toast.makeText(getApplicationContext(), "Finished writing to SD", Toast.LENGTH_LONG).show(); //##5
       } catch (Exception e) {
           Toast.makeText(getApplicationContext(), "Write failure", Toast.LENGTH_SHORT).show(); //##6
       }
Adithya
  • 1,688
  • 1
  • 10
  • 18
  • I tried just this code as suggested, but it didn't work. It fails on the line datfile.createNewFile() . Am I doing something wrong in the way I set the file path and name (String namFile=..........)? – Chris S Jun 20 '17 at 07:28
  • you dont need the first if to check if folder exists because `mkdirs()` does it for you.and `createNewFile()` is also not needed. – Adithya Jun 20 '17 at 14:44
0

The advice to use Log.e() helped to point me in the right direction - thanks. I think my problem was that I had not realised that built-in memory and SD card were not necessarily the same as internal and external storage, and that a device can sometimes use memory on the SD card as "internal".

I found out what was going on when I ran the code on real devices, one with an SD card and one without one, instead of using the emulator. That made it easy to use the devices' FileCommander to see exactly where folders and files were being created. I would recommend that to anyone struggling with this kind of problem.

Chris S
  • 83
  • 3
  • 12