views:

87

answers:

2

I'm trying to write a method to take a multiline tab-delimited file and return the contents of that file as an arraylist of String arrays (each line is a String[], and each such String[] is an element of an arraylist). My problem is, I can't tell if the output is correct or not. I've printed each arraylist element and String[] element as they are saved to the arraylist, and those printings look correct. But after the arraylist is returned and I print the String[] in it, they appear to only have the contents of the very last line of the file. I'm suspecting it might be something about FileReader or BufferedReader that I don't know. Anyhoo, here's the code:

public class DataParsingTest {

    static File AAPLDailyFile = new File("./textFilesForMethodTests/dataParsingPractice2.tsv");

    public static void main(String[] args) throws FileNotFoundException, IOException {
        ArrayList<String[]> stringArrayList = fileToStringArray(AAPLDailyFile);
        System.out.println("stringArray.size() = " + stringArrayList.size());
        System.out.println(stringArrayList.get(0)[0]);

        for (int i = 0; i < stringArrayList.size(); i++) {
            for (int j = 0; j < stringArrayList.get(i).length; j++) {
                System.out.println("index of arraylist is " + i + " and element at index " + j + " of that array is " + stringArrayList.get(i)[j]);
            }
        }
    }

    public static ArrayList<String[]> fileToStringArray(File file) throws FileNotFoundException, IOException {
        ArrayList<String[]> arrayListOfStringArrays = new ArrayList<String[]>();
        FileReader fileReader = new FileReader(file);
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        int nextChar = 0;
        int noOfTokens = 1; // because the first token doesn't have a tab or newline before it
        int startIndex = 0, endIndex = 0, tokenIndex = 0;
        String toRead = "";
        toRead = bufferedReader.readLine();
        for (int i = 0; i < toRead.length(); i++) {
            if (toRead.charAt(i) == '\t') {
                noOfTokens++;
            }
        }
        System.out.println("noOfTokens = " + noOfTokens);
        bufferedReader.close();
        fileReader.close();
        String[] productString = new String[noOfTokens];
        startIndex = 0;
        endIndex = 0;
        tokenIndex = 0;
        FileReader fileReader2 = new FileReader(file);
        BufferedReader bufferedReader2 = new BufferedReader(fileReader2);

        tokenIndex = 0;
        int count = 1;
        while ((toRead = bufferedReader2.readLine()) != null) { 
            System.out.println("toRead = " + toRead);
            startIndex = -1; // [L - so that the first time an array element is assigned, it's upped to 0]
            endIndex = 0;
            tokenIndex = 0;
            while (true) {  
                endIndex = toRead.indexOf("\t", startIndex + 1);  
                if (endIndex == -1) {
                    productString[tokenIndex] = toRead.substring(startIndex + 1);
                    System.out.println("tokenIndex = " + tokenIndex);
                    System.out.println("productString[" + tokenIndex + "] = " + productString[tokenIndex]);
                    tokenIndex++;
                    count++;
                    arrayListOfStringArrays.add(productString);
                    System.out.println("just added an array to the list. the first element is " + productString[0]);
                    break;
                }
                productString[tokenIndex] = toRead.substring(startIndex + 1, endIndex);
                System.out.println("tokenIndex = " + tokenIndex);
                System.out.println("productString[" + tokenIndex + "] = " + productString[tokenIndex]);
                startIndex = endIndex;
                tokenIndex++;
                count++;
            }
        }
        fileReader2.close();
        bufferedReader2.close();
        return arrayListOfStringArrays;
    }
}

The input file is:

1   2
3   4
5   6

The output is:

noOfTokens = 2
toRead = 1        2
tokenIndex = 0
productString[0] = 1
tokenIndex = 1
productString[1] = 2
just added an array to the list. the first element is 1
toRead = 3        4
tokenIndex = 0
productString[0] = 3
tokenIndex = 1
productString[1] = 4
just added an array to the list. the first element is 3
toRead = 5        6
tokenIndex = 0
productString[0] = 5
tokenIndex = 1
productString[1] = 6
just added an array to the list. the first element is 5
stringArray.size() = 3
5 // from here on up, it looks like the method works correctly
index of arraylist is 0 and element at index 0 of that array is 5
index of arraylist is 0 and element at index 1 of that array is 6
index of arraylist is 1 and element at index 0 of that array is 5
index of arraylist is 1 and element at index 1 of that array is 6
index of arraylist is 2 and element at index 0 of that array is 5
index of arraylist is 2 and element at index 1 of that array is 6 //these 6 lines only reflect the last line of the input file.

Thanks a mil!

+7  A: 

You're only creating a single string array, and reusing that for all lines. So your ArrayList just contains multiple references to the same object. You need to understand that when you call arrayListOfStringArrays.add(productString); that's not adding a copy of the array to the ArrayList - it's just adding a reference. (The value of productString is just a reference, not the array itself.)

Just move this:

String[] productString = new String[noOfTokens];

into the while loop, and all should be well. (In this respect, anyway. You should also be closing your file handles in finally blocks.)

Jon Skeet
I'll upvote yours if you upvote mine! `:P`
jjnguy
*(However, I'm sure any more upvotes really won't help you today)*
jjnguy
Duh! It's always silly stuff like that that gets me. Great explanation. It works perfectly now.Also, can you explain the thinking that led you to spot that?
Anita
+2  A: 

That looks like too much code for me to process. Try this altered fileToStringArray method.

public static ArrayList<String[]> fileToStringArray(File file) throws FileNotFoundException, IOException {
    ArrayList<String[]> returnVal = new ArrayList<String[]>();
    // Scanner is a nifty utility for reading Files
    Scanner fIn = new Scanner(file);
    // keep reading while the Scanner has lines to process
    while (fIn.hasNextLine()) {
        // take the next line of the file, and split it up by each tab
        // and add that String[] to the list
        returnVal.add(fIn.nextLine().split("\t", -1));
    }
    return returnVal;
}
jjnguy
Thanks! I've only just started with Java and have never used a Scanner. Really should know the API better. This is ridiculously more efficient.
Anita
@Anita, well, you can learn lots by coming to Stack Overflow. You should also look up String.split() it is super helpful too!
jjnguy
Oh, the splitter was meant as an exercise :) So why would anyone use FileReader if Scanner seems so much more versatile?
Anita