How to load and save table on android without error "File contains a path separator"?

edited December 2017 in Android Mode

Hey! I'm trying to develop an app on android with processing that needs to save information in a table for next time use and then retrieve it later on. (Sort of like a leaderboard record). The problem is that saveTable() and loadTable() don't work because the error java.lang.IllegalArgumentException: File contains a path separator is returned. Here is bascially what I'm trying to do (Which works fine on normal PC): In setup:

try { PersonalDetails = loadTable("AccountInfo.csv", "header"); // PersonalDetails is my table variable. if (PersonalDetails.getRowCount() > 0) { Registered = true; LocalScore = PersonalDetails.getRow(0).getInt("Score"); } } catch (NullPointerException e) { Table createCSV = new Table(); createCSV.addColumn("ID", Table.INT); createCSV.addColumn("Score", Table.INT); createCSV.addColumn("Name", Table.STRING); saveTable(createCSV, "data/AccountInfo.csv"); PersonalDetails = loadTable("AccountInfo.csv", "header"); if (PersonalDetails.getRowCount() > 0) { Registered = true; LocalScore = PersonalDetails.getRow(0).getInt("Score"); } }

And then in draw basically continuously save as score updates:

void draw() { if (Start) { if (Registered) { PersonalDetails.setInt(0, "Score", LocalScore); saveTable(PersonalDetails, "data/AccountInfo.csv"); } } background(255); }

As for android I continued to get the error stated above. I've tried multiple solutions to try to fix this including an InputStream and BufferedReader, this read the file perfectly fine:

BufferedReader br; String line; void readInfo() { try { InputStream is = createInput("AccountInfo.txt"); br = new BufferedReader(new InputStreamReader(is, "UTF-8")); while ((line=br.readLine())!=null) { System.out.println(line); } } catch (IOException e) { System.out.println("IOException when trying to read AccountInfo.txt:\n"+e); System.exit(0); } }

But, every approach i've taken so far to try to write the file failed. I'm assuming read works better because it will auto search the /files/ directory when not specified with a path. So far i've tried to use a BufferedWriter and PrintWriter in the same way as readInfo() above, hoping it would work, but it didn't:

PrintWriter saveInformation; BufferedWriter writer = null; void saveInfo() { try { writer = new BufferedWriter(new FileWriter("accountinfo.csv")); saveInformation = new PrintWriter("accountinfo.csv"); saveInformation.println("Changed Text File..."); writer.write("Changed Text file..."); } catch ( IOException e) { } finally { try { if ( writer != null ) writer.close( ); if (saveInformation != null) saveInformation.close(); } catch ( IOException e) { } } }

I have also tried to use the AssetManager, couldn't get that working. Also, I tried to use all above listed methods with relative file path and absolute file path. Each of these would similarly return the same error "java.lang.IllegalArgumentException: File contains a path separator".

Any help or feedback on the matter would be immensely very much greatly incredibly much appreciated!

Answers

  • Not tested but try replacing "AccountInfo.csv" with dataPath("AccountInfo.csv")

    Kf

  • Hey Kf, I tried this but sadly it didn't seem to fix the issue :( Still keeps getting the same path separator error. Thanks, Night.

  • edited December 2017 Answer ✓

    @Night===

    the error is a standard one with Android: the name of the created file cannot contain any separator(/); so you have to change your:

    saveTable(createCSV, "data/AccountInfo.csv");

    Instead write:

    String chemin = dataPath();
    saveTable(chemin+"AccountInfo.csv");
    

    it could be also possible to use File for doing the same; in this case you get your files dir with File monFichier = this.getActivity().getFilesFir() and use this as path adding a"/" to it.

  • @akenaton WOW Thankyou SOOO much! Your answer was the only one that actually worked! I've been searching and trying every single solution on the forum for agesss and none of them worked!

    Your first method actually still returned the same error using dataPath(). But, the second worked perfectly!

    Just to clarify for anyone coming into this: Use this.getActivity().getFilesDir(); for the directory in the file variable, you don't need a "/", just write monFichier+"AccountInfo.csv" in saveTable() and loadTable()!

  • edited March 2018

    @Night I'm completely lost on how you got this to work, I keep getting the same error about the path separator, even though I'm using path = this.getActivity().getFilesDir();

    This function also doesn't add a / to the end of the file it returns, so when I do path+"save.csv", it returns data/user/0/com.d3f4alt.tap/filessave.csv

    saveTable(table, path+"save.csv"); is how I'm saving it, am I doing something wrong?

    EDIT: I managed to fix it somehow, but now the app crashes when it's relaunched, but doesn't report any errors

  • edited March 2018

    Hopefully the following sketch provides some insight of how to manage resources. The main purpose of this demo is to show how to save or open files. When the application runs for the first time, it shows the content of the folder where any new files are created (either by saveStrings(), saveBytes(), etc) as well as the content of the assets folder. Notice that any created file by Processing function is not created in the assets folders as this folder is read only and any of these assets are only access via surface.getAssets().open(filename) function.

    As I was describing, when the application runs the first time, it list the content of resources. Then you will have a split screen. Do the following:

    1. Click on open file: Notice that at this point the file doesn't exist, so not file found is seen in the console
    2. Click on save data: A file is created with three lines
    3. Click on open data: The first line of the last saved file is presented.

    When the green message box is shown, it last for 2 seconds. For those two seconds you are not allowed to neither open nor create any file. However, if you click on the screen before the green box disappears, you will get a report of your resource folders and your current file storing strings will be deleted.

    Notice that when you save a file, and if you are not using the external storage, you do not need to specify the folder "data" inside this path. This is handled by Processing either if you are running your sketch in Java or in Android mode. Check the code and ask any question you have or if you have any idea to improve it or provide additional comment.

    Last point: No permissions required for this sketch. Notice that "write on external device" permission is required if you decide to use external storage to save your files.

    Kf

    //===========================================================================
    // IMPORTS:
    
    import android.app.Activity;
    import android.content.Context;
    import android.widget.FrameLayout;
    //import android.app.Fragment;
    
    import android.os.Environment;
    import android.graphics.Color;
    import android.widget.Toast;
    import android.os.Looper;
    import android.view.WindowManager;
    import android.os.Bundle;
    import android.view.ViewParent;
    import android.view.ViewGroup;
    import android.view.View;
    import android.widget.RelativeLayout;
    import android.view.LayoutInflater;
    import android.R.string;
    
    
    //===========================================================================
    // FINAL FIELDS:
    final int DURATION=2000;
    final String FILENAME="mylist.txt";
    
    //===========================================================================
    // GLOBAL VARIABLES:
    
    Activity act;
    Context mC;
    int startTime=0;
    String message;
    
    //===========================================================================
    // PROCESSING DEFAULT FUNCTIONS:
    
    void setup() {
      fullScreen();
      orientation(PORTRAIT);
      background(0);
    
      act = this.getActivity();
      Looper.prepare();
    
      textAlign(CENTER, CENTER);  
    
      fill(255);
      noStroke();
      textSize(32);
      message="";
    
      reportAssetsAndFiles();
    }
    
    
    void draw() {
      if (frameCount%300==0) background(0);
    
      fill(88);
      rect(0, 0, width, height/2);
      fill(255);
      text("Save file", width/2, height/4);
    
      fill(144);
      rect(0, height/2, width, height/2);
      fill(25);
      text("Open file", width/2, 3*height/4);
    
      //SHOW messagge
      if (doneTime()==false) {
        background(0);
        fill(0, 200, 0, 150);
        rect(width/4, height/2-100, width/2, 200);
        fill(255);
        text(message, width>>1, height>>1);
      }
    }
    
    
    void mouseReleased() {
    
      //  xxxxxxxxxx_____________xxxxxxxxxx
      //If showing message, do not event try to open or save file
      if (doneTime()==false) {
        reportAssetsAndFiles();
        return;
      }
    
      //  xxxxxxxxxx_____________xxxxxxxxxx
      //Clicked on bottom half: Open file
      if (mouseY>height/2) {
        File cfile = surface.getFileStreamPath(FILENAME);  
        if (!cfile.exists()) {
          println("File NOT found");
          return;
        }
    
        String[] in=loadStrings(FILENAME);
    
        if (in!=null) {
          if (in.length>1) 
            message="Read first line=>"+in[0];
        } else {
          message="Fail to open file";
        }
        startTime=millis();
        return;
      }
    
      //  xxxxxxxxxx_____________xxxxxxxxxx
      //Click on top half: Save file
      String[] list ={"Time:"+millis(), "Date:"+day()+"/"+month(), "Info:123456789"};
      saveStrings(FILENAME, list);
      startTime=millis();
      message="Saved text => " + list[0];
    }
    
    boolean doneTime() {
      return millis()-startTime>DURATION;
    }
    
    
    //===========================================================================
    // OTHER FUNCTIONS:
    void reportAssetsAndFiles() {
    
      //List content of your sketchPath: https:// github.com/processing/processing-android/blob/master/core/src/processing/core/PApplet.java#L5068
      println("====***=== SKETCHPATH report");
      File folder = surface.getFileStreamPath("");
      String[] sketchPathLoc=folder.list();
      println(folder.getAbsolutePath());
    
    
      if (sketchPathLoc!=null) println(sketchPathLoc);
      else                     println("NOTHING in current loc");
    
      //Delete file if exists
      File cfile = surface.getFileStreamPath(FILENAME);  
      if (cfile.exists()) {
        println("====**=== "+FILENAME+" deleted");
        cfile.delete();
      }
    
      println("====***=== ASSETS report");
      try {
        String[] con=surface.getAssets().list("");
        if (con!=null)  println(con);
        else            println("NOTHING in current assets");
      } 
      catch(IOException e) {
        //Do nothing
      }
    }
    
    
    @ Override 
      public void onResume() {
      super.onResume();
    
      act = this.getActivity();
      mC= act.getApplicationContext();
    
    }
    

    Keyword: kf_keyword android_assets android_sketchpath android_savefile save_files savefiles

Sign In or Register to comment.