Home > Mobile >  OutputStreamWriter only writing one item into file
OutputStreamWriter only writing one item into file

Time:10-19

I have used the following code to write elements from an arraylist into a file, to be retrieved later on using StringTokenizer. It works perfect for 3 other arraylists but somehow for this particular one, it throws an exception when reading with .nextToken() and further troubleshooting with .countTokens() shows that it only has 1 token in the file. The delimiters for both write and read are the same - "," as per the other arraylists as well.

I'm puzzled why it doesnt work the way it should as with the other arrays when I have not changed the code structure.

=================Writing to file==================

public static void copy_TimeZonestoFile(ArrayList<AL_TimeZone> timezones, Context context){

    try {

        FileOutputStream fileOutputStream = context.openFileOutput("TimeZones.dat",Context.MODE_PRIVATE);
        OutputStreamWriter writerFile = new OutputStreamWriter(fileOutputStream);

        int TZsize = timezones.size();

        for (int i = 0; i < TZsize; i  ) {
            writerFile.write(
                    timezones.get(i).getRegion()   ","  
                            timezones.get(i).getOffset()   "\n"
            );
        }

        writerFile.flush();
        writerFile.close();

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

==========Reading from file (nested in thread/runnable combo)===========

        public void run() {


            if (fileTimeZones.exists()){

                System.out.println("Timezone file exists. Loading.. File size is : "   fileTimeZones.length());
                try{

                    savedTimeZoneList.clear();

                    BufferedReader reader = new BufferedReader(new InputStreamReader(openFileInput("TimeZones.dat")));
                    String lineFromTZfile = reader.readLine();
                    while (lineFromTZfile != null ){
                        StringTokenizer token = new StringTokenizer(lineFromTZfile,",");
                        AL_TimeZone timeZone = new AL_TimeZone(token.nextToken(),
                                token.nextToken());

                        savedTimeZoneList.add(timeZone);
                    }


                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }

===================Trace======================

I/System.out: Timezone file exists. Loading.. File size is : 12373
W/System.err: java.util.NoSuchElementException
    at java.util.StringTokenizer.nextToken(StringTokenizer.java:349)
    at com.cryptotrac.trackerService$1R_loadTimeZones.run(trackerService.java:215)
W/System.err:     at java.lang.Thread.run(Thread.java:764)

CodePudding user response:

It appears that this line of your code is causing the java.util.NoSuchElementException to be thrown.

AL_TimeZone timeZone = new AL_TimeZone(token.nextToken(), token.nextToken());

That probably means that at least one of the lines in file TimeZones.dat does not contain precisely two strings separated by a single comma.

This can be easily checked by making sure that the line that you read from the file is a valid line before you try to parse it.

Using method split, of class java.lang.String, is preferable to using StringTokenizer. Indeed the javadoc of class StringTokenizer states the following.

StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code. It is recommended that anyone seeking this functionality use the split method of String or the java.util.regex package instead.

Try the following.

String lineFromTZfile = reader.readLine();
while (lineFromTZfile != null ){
    String[] tokens = lineFromTZfile.split(",");
    if (tokens.length == 2) {
        // valid line, proceed to handle it
    }
    else {
        // optionally handle an invalid line - maybe write it to the app log
    }
    lineFromTZfile = reader.readLine(); // Read next line in file.
}

CodePudding user response:

There are probably multiple things wrong, because I'd actually expect you to run into an infinite loop, because you are only reading the first line of the file and then repeatedly parse it.

You should check following things:

  • Make sure that you are writing the file correctly. What does the written file exactly contain? Are there new lines at the end of each line?
  • Make sure that the data written (in this case, "region" and "offset") never contain a comma, otherwise parsing will break. I expect that there is a very good chance that "region" contains a comma.
  • When reading files you always need to assume that the file (format) is broken. For example, assume that readLine will return an empty line or something that contains more or less than one comma.
  • Related