Java从文件中读取字符串

时间:2017-10-02 02:31:41

标签: java arraylist file-io

我遇到了这种方法的问题。该方法应该读取一系列数据的文本文件(攻击ID [int],日期[以MM / DD / YYYY格式保存的字符串],怪物名称[String],位置[String]和记者攻击[String])用逗号分隔,并将这些值放入名为monsterAttacks的ArrayList中。每次运行此方法时,我都会得到一个InputMismatchException。我觉得它与日期有关,但我不确定在这种情况下在哪里或如何使用String split()方法。我怎样才能正常工作?

免责声明:这是家庭作业的一部分。

提前致谢。

编辑:文本文件中的示例数据:

23,12 / 23/1994,Dracula,California,Trisha Takinawa

25,11 / 12/1992,哥斯拉,纽约,大卫

private void readFromFile(){
    if(!(monsterAttacks.isEmpty())) {
        monsterAttacks.clear();
        System.out.println("\nList cleared...");
    }
    System.out.println("Enter path: ");
    String pathName = getUserInput();
    File file = new File(pathName);
    Scanner read;
    MonsterAttack attack;

    try {
        read = new Scanner(file);
        do {
            int id = read.nextInt();
            String date = read.next();
            String name = read.next();
            String location = read.next();
            String reporter = read.next();
            attack = new MonsterAttack(id, date, name, location, reporter);
            monsterAttacks.add(attack);
        } while (read.hasNext());

        read.close();
    } catch(IOException e){
        e.printStackTrace();
    }

}

4 个答案:

答案 0 :(得分:1)

您告诉我们您的数据是

  

以逗号分隔

如果是这样,那么您必须考虑这些令牌分隔符。在这里继续进行的一种方法是只读取整行,然后用逗号分割以访问每个术语:

try {
    read = new Scanner(file);
    do {
        String line = read.nextLine();
        String[] parts = line.split(",\\s*");
        int id = Integer.parseInt(parts[0]);
        String date = parts[1];
        String name = parts[2];
        String location = parts[3];
        String reporter = parts[4];
        attack = new MonsterAttack(id, date, name, location, reporter);
        monsterAttacks.add(attack);
    } while (read.hasNext());

    read.close();
} catch(IOException e){
    e.printStackTrace();
}

答案 1 :(得分:1)

我强烈建议您只使用文件阅读器,它具有您需要的一切,Java 8附带的流集合提供了一些您可以对给定输入执行的不错操作。

以下是代码:

    final File definitions = Paths.get("some/dir", "monster_definitions.txt").toFile();
    final BufferedReader reader = new BufferedReader(new FileReader(definitions));

    final String[] entries = reader.lines().collect(Collectors.joining()).split(")");

    for(String entry : entries){

        final String[] data = entry.substring(1, entry.lastIndexOf(entry)-1).split(",");

        final int id = Integer.parseInt(data[0]);
        final String date = data[1];
        final String name = data[2];
        final String location = data[3];
        final String reporter = data[4];

        monsterAttacks.add(new MonsterAttack(id, date, name, location, reporter));
    }

    reader.close();

现在,我们首先获得所有行的流,然后将每个单独的行收集到一个最终字符串中。这个字符串我们用“)”分隔,因为这是每个条目的结束标记。然后我们遍历每个条目并返回条目的子字符串。从索引1开始到最终索引减1结束,我们只是为了摆脱“(”和“)”。现在我们得到了原始条目,其中包含了缓存定义所需的所有信息。我们使用“,”作为正则表达式来分割条目,从而得到每个单独数据条目的数组。

但是,我真的鼓励你使用JSON作为这种定义序列化和反序列化的东西。它更易于使用,并且在使用数据时提供了更大的灵活性。

编辑:只是注意到你没有为每个条目分配任何分割符。除非每个条目只是换行符。在这种情况下,你可以做这样的事情:`

final List<String> entries = new ArrayList<>(reader.lines().collect(Collectors.toList()));

            for(String entry : entries){`

答案 2 :(得分:0)

考虑到您的项目使用Java 8,您可以使用流(使用line())简单地操作文件数据,并将它们映射到所需的类(使用map()),在本例中为{{ 1}}。它会是这样的:

MonsterAttack

我希望它有所帮助。

答案 3 :(得分:0)

已经提供了一些好的答案,我只是想指出一个更“专业”的解决方案,在你研究开发结构化应用程序然后考虑Spring Batch平面文件阅读器here的情况下。

虽然我并不疯狂但我知道这是一个相当大的开销,我知道这是一个家庭作业,可能是一个简单的Java应用程序。我认为这是对未来的一个很好的参考。

使用平面文件读取器/写入器,您可以将平面文件映射到POJO(普通旧Java对象),还可以使用Spring批处理来连接操作,从而为批处理应用程序提供更好的结构。

这是一个简单的代码片段(来自上面的链接):

@Configuration
public class CsvFileToDatabaseJobConfig {

    @Bean
    ItemReader<StudentDTO> csvFileItemReader() {
        FlatFileItemReader<StudentDTO> csvFileReader = new FlatFileItemReader<>();
        csvFileReader.setResource(new ClassPathResource("data/students.csv"));
        csvFileReader.setLinesToSkip(1);
 ...
    }

    private LineMapper<StudentDTO> createStudentLineMapper() {
        ...
    }

    private LineTokenizer createStudentLineTokenizer() {
        DelimitedLineTokenizer studentLineTokenizer = new DelimitedLineTokenizer();
        studentLineTokenizer.setDelimiter(";");
        studentLineTokenizer.setNames(new String[]{"name", "emailAddress", "purchasedPackage"});
        return studentLineTokenizer;
    }

    private FieldSetMapper<StudentDTO> createStudentInformationMapper() {
        BeanWrapperFieldSetMapper<StudentDTO> studentInformationMapper = new BeanWrapperFieldSetMapper<>();
        studentInformationMapper.setTargetType(StudentDTO.class);
        return studentInformationMapper;
    }
}