Прочитайте файл, разделенный вкладкой, и поместите слова в ArrayList

Я занимаюсь самообучением, чтобы помочь мне больше узнать о Java, но я застрял в этом вопросе. У меня есть следующий файл txt:

Name  Hobby 
Susy  eat fish 
Anna  gardening
Billy bowling with friends

Примечание. имя и хобби разделены вкладкой

Каков наилучший способ прочитать всю строку и поместить ее в arraylist (имя, хобби). Трудная часть состоит в том, что

eat fish or bowling with friends

имеет белые пробелы, и он должен быть помещен под один массив и, очевидно, я не могу его жестко кодировать. Вот мой текущий код:

 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");

Появилась ошибка:

java.lang.StringIndexOutOfBoundsException: индекс строки за пределами диапазона: -1

Я подозреваю, что подсчет индекса не очень полезен на вкладке. Любая идея?

Ответ 1

Хорошо, вам нужно сделать рецепт, показанный ниже:

  • Создайте BufferedReader
  • Создайте ArrayList<String>
  • Начните чтение данных в переменную String с именем lineJustFetched.
  • Разделите String, вызвав lineJustFetched.split("\t");
  • Итерации над созданным String[]. Убедитесь, что токен, который вы хотите ввести в ArrayList, не ""
  • Если нет, добавьте слово в ArrayList

Вы указываете, что вам нужно разделить на основе значений \t, поэтому пробелы не будут проблемой.

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();
        }
    }
}    

Выход

John
likes to play tennis
Sherlock
likes to solve crime

Ответ 2

Если вы разделили столбец Name и Hobby с вкладкой \t, вы должны сделать что-то вроде этого (и не забудьте закрыть сканирование в конце):

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();
}

Ответ 3

Ибо другие все еще спотыкаются на это.

Используя Stream API (Java 8), это можно сделать как

Это показывает

  • Метод фильтра для фильтрации первого элемента заголовка из списка
  • метод карты для сопоставления каждого элемента потока с другим элементом для нового потока.
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();
    }
  }
}

И вывод

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

==HashMap==
{Susy=eat fish}
{Anna=gardening}
{Billy=bowling with friends} 

Ответ 4

Вы должны попробовать библиотеку commons-lang. Среди многих других полезных вещей вы можете разбить строку, используя разделитель:

String x="Billy bowling with friends";

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

Предполагая, что есть вкладка между Billy и bowling,

  • y [0] содержит "Билли"
  • у 1 содержится "боулинг с друзьями"

Ответ 5

Для будущих ссылок, когда вы просматриваете вкладку, существует разделитель, такой как "\ t" для вкладки. Используйте это вместо .split("")

Также, когда вы ошиблись, потому что это означает, что символ не найден, следовательно, -1, поэтому при попытке сохранить его в массиве... -1 недействительно. (бросьте на это проверку)

Вы можете набросать свою программу F10 или F11..или другой ключ в зависимости от вашей IDE

Несколько советов