12

I am doing a self learning exercise to help me understand more about Java, but I am stuck at this question. I have the following txt file:

Name  Hobby 
Susy  eat fish 
Anna  gardening
Billy bowling with friends

Note: name and hobby are separated by tab

What is the best way to read all the line and put it in arraylist(name,hobby). The tricky part is that

eat fish or bowling with friends

has white spaces and it must be put under one array and obviously I cannot hardcode it. Here is my current code:

 public void openFile(){
            try{
                FileInputStream fstream = new    FileInputStream("textfile.txt");
          // use DataInputStream to read binary NOT text
          BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
          ArrayList<String> names = new ArrayList<String>();
          ArrayList<String> hobbies = new ArrayList<String>();
          String lineJustFetched;
          while ((lineJustFetched = br.readLine()) != null)   {
          String[] tokens = lineJustFetched.split(" \t");

I got an error:

java.lang.StringIndexOutOfBoundsException: String index out of range: -1

I suspect counting the index is not very useful on a tab. Any idea?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
user2891092
  • 163
  • 1
  • 2
  • 10

5 Answers5

14

Alright, you need to do the recipe shown below:

  1. Create a BufferedReader
  2. Create an ArrayList<String>
  3. Start reading data into a String variable named lineJustFetched.
  4. Split the String by calling lineJustFetched.split("\t");
  5. Iterate over the String[] produced. Check if the token you want to enter into the ArrayList is not ""
  6. If not, add the word to the ArrayList

You specify that you need to split based on \t values so white spaces won't be an issue.

SSCCE

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;

public class WordsInArray {
    public static void main(String[] args) {
        try{
            BufferedReader buf = new BufferedReader(new FileReader("/home/little/Downloads/test"));
            ArrayList<String> words = new ArrayList<>();
            String lineJustFetched = null;
            String[] wordsArray;

            while(true){
                lineJustFetched = buf.readLine();
                if(lineJustFetched == null){  
                    break; 
                }else{
                    wordsArray = lineJustFetched.split("\t");
                    for(String each : wordsArray){
                        if(!"".equals(each)){
                            words.add(each);
                        }
                    }
                }
            }

            for(String each : words){
                System.out.println(each);
            }

            buf.close();

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

Output

John
likes to play tennis
Sherlock
likes to solve crime
An SO User
  • 24,612
  • 35
  • 133
  • 221
4

If you separated Name and Hobby column with tab \t, you should do something like this (and don't forget to close scan at end):

public void readFile() throws FileNotFoundException{
    Scanner scan = new Scanner(new File("D://a.txt"));
    ArrayList<String> names = new ArrayList<String>();
    ArrayList<String> hobbies = new ArrayList<String>();

    while(scan.hasNext()){
        String curLine = scan.nextLine();
        String[] splitted = curLine.split("\t");
        String name = splitted[0].trim();
        String hobby = splitted[1].trim();
        if(!"Name".equals(name)){
            names.add(name);
        }
        if(!"Hobby".equals(hobby)){
            hobbies.add(hobby);
        }
    }
    System.out.println(names);
    System.out.println(hobbies);
    scan.close();
}
Stevoisiak
  • 23,794
  • 27
  • 122
  • 225
Arya
  • 2,809
  • 5
  • 34
  • 56
1

For others still stumbling upon this.

Using Stream API (Java 8), this can be done as

This shows

  • Filter method to filter the first header element from the list
  • map method to map each element in stream to another element for new stream.
package com.bhavya.stackoverflow.examples.q19575308;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.function.Predicate;

/**
 * Java 8 Stream API to handle file reading.
 *
 * @author bhavya.work
 */
public class StreamTests {
  public static void main(String[] args) {
    try {
      InputStream fileInputStream;
      BufferedReader bufferedReader;
      final String filepathInSamePackage = "textfile.txt";
      //filter predicate
      Predicate<String> filterFirstLine =
          line -> !(
              "Name".equals(line.split("\t", -1)[0])
                  && "Hobby".equals(line.split("\t", -1)[1])
          );

      //Implementation 1 returns Arrays as asked.

      System.out.println("==ArrayList==");
      fileInputStream = StreamTests.class.getResourceAsStream(filepathInSamePackage);
      bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));

      bufferedReader
          .lines()
          .filter(filterFirstLine)
          .map(s -> {
            String[] splitStrings = s.split("\t", -1);
            return Arrays.asList(splitStrings);
          }).forEach(System.out::println);

      //Implementation 2 returns HashMap as another example

      fileInputStream = StreamTests.class.getResourceAsStream(filepathInSamePackage);    
      bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
      System.out.println("\n==HashMap==");

      bufferedReader
          .lines()
          .filter(filterFirstLine)
          .map(s -> {
            String[] splitStrings = s.split("\t", -1);
            HashMap<String, String> stringStringMap = new HashMap<>();
            stringStringMap.put(splitStrings[0], splitStrings[1]);
            return stringStringMap;
          }).forEach(System.out::println);
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

And the output

==ArrayList==
[Susy, eat fish]
[Anna, gardening]
[Billy, bowling with friends]

==HashMap==
{Susy=eat fish}
{Anna=gardening}
{Billy=bowling with friends} 
bhavya.work
  • 411
  • 3
  • 14
0

You should try the commons-lang library. Among many other useful things you can split a string using a delimiter:

String x="Billy bowling with friends";

String y[]=StringUtils.split(x, '\t');

Assuming there is a tab between Billy and bowling,

  • y[0] contains "Billy"
  • y1 contains "bowling with friends"
Nayantara Jeyaraj
  • 2,624
  • 7
  • 34
  • 63
windjammer
  • 168
  • 6
0

For future references when you parse out tab there is a delimiter such as "\t" for tab. Use that instead of .split(" ")

Also, when your error is thrown because it means no character is found, hence the -1, so when you try to store it in an Array... -1 is not valid. (throw in a check for that)

You can step throw your program F10 or F11..or some other key depending on your IDE

Just some tips

Seifo84
  • 1
  • 1