【问题标题】:Read a file separated by tab and put the words in an ArrayList读取由制表符分隔的文件并将单词放入 ArrayList
【发布时间】:2013-10-24 19:52:17
【问题描述】:

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

Name  Hobby 
Susy  eat fish 
Anna  gardening
Billy bowling with friends

注意:姓名和爱好用制表符隔开

阅读所有行并将其放入 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

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

【问题讨论】:

  • 确保文件末尾没有新行/空行。

标签: java file-io tabs


【解决方案1】:

好的,你需要按照如下所示的方法进行操作:

  1. 创建BufferedReader
  2. 创建一个ArrayList&lt;String&gt;
  3. 开始将数据读入名为lineJustFetchedString 变量。
  4. 通过调用lineJustFetched.split("\t");拆分String
  5. 迭代生成的String[]。检查你要进入ArrayList的token是否不是""
  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

【讨论】:

  • 按照您的指示编辑我的源代码.. 正确吗?
  • @user2891092 我为你发布了一个 SSCCE。
  • 但它将所有内容都放入一个数组列表中。是否可以将它们分成两个数组列表(例如,约翰被放入名字中,喜欢打网球被放入爱好中)?
  • 是的。在这种情况下,每一个奇数的单词都会变成名字,每一个偶数的单词都会变成爱好。明白我在说什么? =)
【解决方案2】:

如果您使用标签\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),可以这样做

    这表明

    • 从列表中过滤第一个标题元素的过滤方法
    • 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} 
    

    【讨论】:

      【解决方案4】:

      当您解析制表符时,为了将来的参考,有一个分隔符,例如制表符的“\t”。 使用它而不是 .split(" ")

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

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

      只是一些提示

      【讨论】:

        【解决方案5】:

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

        String x="Billy bowling with friends";
        
        String y[]=StringUtils.split(x, '\t');
        

        假设Billybowling 之间有一个标签,

        • y[0] 包含“比利”
        • y1 包含“与朋友打保龄球”

        【讨论】:

          猜你喜欢
          • 2012-04-18
          • 1970-01-01
          • 2013-03-09
          • 2016-08-10
          • 2023-04-11
          • 1970-01-01
          • 1970-01-01
          • 2012-04-01
          • 1970-01-01
          相关资源
          最近更新 更多