【问题标题】:Java: storing lines and words into separate arraylists, unable to print resultsJava:将行和单词存储到单独的数组列表中,无法打印结果
【发布时间】:2021-07-07 03:33:17
【问题描述】:

我正在处理一个需要我导入文本文件、读取文件并以不同方式对单词进行排序(即升序、唯一单词等)的项目。到目前为止,我已经能够导入文件并打印它,直到我添加了将列表排序为行和单词的命令。

我使用缓冲读取器来存储行和单词,但在执行时,我不知道数据是否已存储在单独的数组列表中,并且控制台不会打印存储的单词数在 ArrayList wordList 中。

我哪里错了?

到目前为止,这是我的代码:

public static void main(String[] args)throws IOException{
  if(args.length == 0){
    System.out.println("Error, usage: java ClassName inputfile");
    System.exit(1);
  }
  File randomText = new File(args[0]);
    if(randomText.exists() && randomText.isFile()){
      processFile(randomText);
    } else{
        System.err.println("ERROR: file does not exist");
        System.exit(1);
      }
 }

public static void processFile(File randomText)throws IOException, FileNotFoundException{
  ArrayList<String> lineList = new ArrayList<String>();
  ArrayList<String> wordList = new ArrayList<String>();

  BufferedReader br = new BufferedReader(new FileReader(randomText));
  StringBuffer sb = new StringBuffer();
  String line;
  while((line=br.readLine()) != null){
    sb.append(line);
    sb.append("\n");
    lineList.add(line);
  }
  while((line = br.readLine()) != null){
    wordList = new ArrayList<String>(Arrays.asList(line.split(" |.")));
    }
    System.out.println("Total number of words in the file: " + wordList.size());
    br.close();
}

【问题讨论】:

  • 文件阅读器(尤其是BufferedReader,在您的情况下)按顺序读取文件一次。一旦你读过它,它就消失了。您需要返回文件的开头或遍历 lines 数组以拆分为单词。
  • 您能否发布(至少部分)文本文件,以便我可以根据您的实际数据测试我的代码?文件是否只包含 ASCII 字符?

标签: java string arraylist bufferedreader


【解决方案1】:

你不见了wordList.addAll(Arrays.asList(line.split(" |.")));

声明:wordList = new ArrayList&lt;String&gt;(Arrays.asList(line.split(" |."))); 这只会添加最后一行字

有两种方法可以做到。

  1. 创建另一个 BufferedReader 并添加到 wordList
    BufferedReader br1 = new BufferedReader(new FileReader(randomText));
            while((line = br1.readLine()) != null){
              }
              System.out.println("Total number of words in the file: " + wordList.size());
              br1.close();
          }
  1. 在单个 while 循环中添加到 wordList
public static void main(String[] args) throws FileNotFoundException, IOException {
      if (args.length == 0) {
          System.out.println("Error, usage: java ClassName inputfile");
          System.exit(1);
      }
      File randomText = new File(args[0]);
      if (randomText.exists() && randomText.isFile()) {
          processFile(randomText);
      } else {
          System.err.println("ERROR: file does not exist");
          System.exit(1);
      }
  }
  public static void processFile(File randomText) throws IOException, FileNotFoundException {
      ArrayList<String> lineList = new ArrayList<String>();
      ArrayList<String> wordList = new ArrayList<String>();
      BufferedReader br = new BufferedReader(new FileReader(randomText));
      StringBuffer sb = new StringBuffer();
      String line;
      while ((line = br.readLine()) != null) {
          sb.append(line);
          sb.append("\n");
          lineList.add(line);
          wordList.addAll(Arrays.asList(line.split(" |.")));
      }
      System.out.println("Total number of words in the file: " + wordList.size());
      br.close();
  }

【讨论】:

  • 谢谢。我不得不在我的代码中移动一些东西,但是使用这种策略可以让我打印出正确的单词数。
【解决方案2】:

正如其他人所说,您不能重复使用文件阅读器。您读取文件一次,然后读取器对象就完成了。因此,让我们将该文件读入行列表。然后使用该行列表来获取单词列表。

顺便说一下,java.io.File 类已被java.nio.file 框架取代,如File Javadoc 概述末尾所述。该注释建议使用toPath 转换为Path 对象。

File file = new File( "/Users/basilbourque/names.txt" );
Path path = file.toPath();

Path 对象中,我们可以通过Files.lines 获得该文件中行的stream

Stream < String > lines = Files.lines( path )

例如,尝试将这些行转储到控制台。

try ( Stream < String > lines = Files.lines( path ) )
{
    lines.forEach( s -> System.out.println( s ) );
}
catch ( IOException e )
{
    e.printStackTrace();
}

我们希望将这些行收集到List。在 Java 16 中,我们使用新方法 Stream#toList 将流捕获到列表的语法更短,而不是显式使用收集器。

List < String > lines = List.of();
try { lines = Files.lines( path ).toList(); } catch ( IOException e ) { e.printStackTrace(); }

我们可以使用Files.readAllLines进一步缩短它。

List < String > lines = List.of();
try { lines = Files.readAllLines( path ); } catch ( IOException e ) { e.printStackTrace(); }

使用List.copyOf 生成unmodifiable list,确保不对列表内容进行任何更改。

List < String > lines = List.of();
try { lines = List.copyOf( Files.readAllLines( path ) ); } catch ( IOException e ) { e.printStackTrace(); }

lines.toString() = [爱丽丝工程师、鲍勃库克、卡罗尔飞行员、达伦宇航员、伊迪丝舞者、弗兰克诗人]

对于每一行,获取一个单词列表。

for ( String line : lines )
{
    List < String > words = List.of( line.split( " " ) );  // Pass `split` method’s returned array of strings to `List.of` to get an unmodifiable list of the words.
    System.out.println( words.size() + " words in: " + words );
}

将所有代码放在一起。

File file = new File( "/Users/basilbourque/names.txt" );
Path path = file.toPath();

List < String > lines = List.of(); // Default to empty list.
try { lines = List.copyOf( Files.readAllLines( path ) ); } catch ( IOException e ) { e.printStackTrace(); }
System.out.println( "lines = " + lines );

for ( String line : lines )
{
    List < String > words = List.of( line.split( " " ) );  // Pass `split` method’s returned array of strings to `List.of` to get an unmodifiable list of the words.
    System.out.println( words.size() + " words in: " + words );
}

运行时。

lines = [Alice engineer, Bob cook, Carol pilot, Darren astronaut, Edith dancer, Frank poet]
2 words in: [Alice, engineer]
2 words in: [Bob, cook]
2 words in: [Carol, pilot]
2 words in: [Darren, astronaut]
2 words in: [Edith, dancer]
2 words in: [Frank, poet]

【讨论】:

  • Files.lines() 是否优于 Files.readAllLines()?另外,您怎么知道文本文件中的单词仅由单个空格分隔?如果文本文件也包含标点符号,您的解决方案是否有效?
  • @Abra 当然,Files.readAllLines 也可以。至于解析单词,我举了一个简单的例子,因为问题中没有定义单词分隔符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-12-16
  • 1970-01-01
  • 2013-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多