11

我正在做一个自学练习,以帮助我更多地了解 Java,但我被困在这个问题上。我有以下 txt 文件:

Name  Hobby 
Susy  eat fish 
Anna  gardening
Billy bowling with friends

注意:姓名和爱好用tab分隔

阅读所有行并将其放入 arraylist(name,hobby) 的最佳方法是什么。棘手的部分是

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

我怀疑计算索引在选项卡上不是很有用。任何想法?

4

5 回答 5

12

好的,您需要执行如下所示的配方:

  1. 创建一个BufferedReader
  2. 创建一个ArrayList<String>
  3. 开始将数据读入一个String名为lineJustFetched.
  4. String通过调用拆分lineJustFetched.split("\t");
  5. 迭代String[]产生的。检查您要输入的令牌是否ArrayList不是""
  6. 如果不是,请将该词添加到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
于 2013-10-24T19:58:34.887 回答
3

如果你用 tab 分隔 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();
}
于 2013-10-24T20:29:02.813 回答
1

对于其他人仍然偶然发现这一点。

使用StreamAPI (Java 8),可以这样做

由此可见

  • 过滤方法来过滤列表中的第一个标题元素
  • map 方法将流中的每个元素映射到新流的另一个元素。
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} 
于 2016-11-08T22:09:29.733 回答
0

你应该试试commons-lang library。在许多其他有用的事情中,您可以使用分隔符拆分字符串:

String x="Billy bowling with friends";

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

Billy假设和之间有一个制表符bowling

  • y[0] 包含“比利”
  • y 1包含“与朋友打保龄球”
于 2013-10-24T20:11:09.620 回答
0

对于将来解析制表符时的参考,有一个分隔符,例如制表符的“\ t”。使用它代替 .split(" ")

此外,当你的错误被抛出是因为它意味着没有找到字符,因此是 -1,所以当你尝试将它存储在一个数组中时...... -1 是无效的。(为此投入支票)

您可以根据您的 IDE 逐步抛出您的程序 F10 或 F11..或其他一些键

只是一些提示

于 2013-10-24T20:15:08.483 回答