简体   繁体   English

Java从文件中读取字符串

[英]Java reading Strings from a file

I am having trouble with this method. 我在使用此方法时遇到麻烦。 The method is supposed to read a text file for a series of data (Attack ID [int], date [String saved in the format MM/DD/YYYY], name of monster [String], location [String], and reporter of the attack [String])separated by commas and put those values into an ArrayList called monsterAttacks. 该方法应该读取一系列数据的文本文件(攻击ID [int],日期[以MM / DD / YYYY格式保存的字符串],怪物[String]的名称,位置[String]和报告者)攻击[String]),以逗号分隔,然后将这些值放入名为MonsterAttacks的ArrayList中。 Every time I run this method I get an InputMismatchException. 每次我运行此方法时,都会收到一个InputMismatchException。 I have a feeling it has something to do with the date but I'm not sure where or how to use the String split() method in this case. 我感觉它与日期有关,但是在这种情况下我不确定在哪里或如何使用String split()方法。 How can I make this work properly? 我该如何使其正常工作?

Disclaimer: This is part of a homework assignment. 免责声明:这是家庭作业的一部分。

Thanks in advance. 提前致谢。

Edit: Sample Data from text file: 编辑:来自文本文件的样本数据:

23,12/23/1994,Dracula,California,Trisha Takinawa 1994年12月23日,德古拉,加利福尼亚,Trisha Takinawa

25,11/12/1992,Godzilla,New York,David 1992年11月25日,哥斯拉,纽约,大卫

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

}

You told us that your data is 您告诉我们您的数据是

separated by commas 被逗号隔开

If so, then you would have to take these token separators into account. 如果是这样,那么您将不得不考虑这些令牌分隔符。 One way to proceed here would be to just read in an entire line and then split by comma to access each term: 进行此操作的一种方法是只读整行,然后用逗号分隔以访问每个术语:

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

I highly recommend to just use a file reader for this, it has everything u will need and the streams collection that comes with Java 8 offers some nice operations you can perform on the given input. 我强烈建议为此使用文件读取器,它具有您所需的一切,并且Java 8附带的流集合提供了一些可以在给定输入上执行的不错的操作。

Here is the code: 这是代码:

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

Now, we first get a stream of all the lines and we collect each separate line into one final string. 现在,我们首先获得所有行的流,然后将每条单独的行收集到一个最终字符串中。 This string we split by ")" as this is the end mark of each individual entry. 我们用“)”分隔该字符串,因为这是每个单独条目的结束标记。 Then we loop through each entry and return a substring of the entry. 然后,我们遍历每个条目并返回该条目的子字符串。 Starting at index 1 and ending at the final index minus 1, this we do solely to get rid of the "(" and ")". 从索引1开始到最后的索引减1结束,这只是为了摆脱“(”和“)”。 Now we got our raw entry containing all the information we need to cache the definition. 现在,我们获得了原始条目,其中包含缓存定义所需的所有信息。 We split the entry by using "," as the regex and thus get an array of each individual data entry. 我们使用“,”作为正则表达式来分割条目,从而获得每个单独数据条目的数组。

However, I really encourage you to use something as JSON for this kind of definition serialization and deserialization. 但是,我真的鼓励您使用JSON作为某种类型的定义序列化和反序列化。 It's much easier to work with and offers a lot more flexibility in operating with the data. 使用起来更容易,并且在操作数据时提供了更大的灵活性。


Edit: just noticed that u didn't have any splitters for each entry. 编辑:只是注意到您没有为每个条目的任何拆分器。 Unless every entry it just split by a line break. 除非每个条目都以换行符分隔。 In that case, u could just do something like this: ` 在那种情况下,你可以做这样的事情:

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

            for(String entry : entries){`

Considering that your project uses Java 8, you can simply manipulate the file data using stream (with line() ) and map them to the desired class (using map() ), in this case, MonsterAttack . 考虑到您的项目使用Java 8,您可以使用流(使用line() )简单地操作文件数据,并将它们映射到所需的类(使用map() ),在这种情况下为MonsterAttack It would be something like this: 就像这样:

public void readFromFile(String path) throws Exception {
    final File definitions = Paths.get(path).toFile();
    final BufferedReader reader = new BufferedReader(new FileReader(definitions));

    monsterAttacks = reader.lines().map(line -> {
        String[] entry = line.split(",");
        return new MonsterAttack(Integer.parseInt(entry[0]), entry[1], entry[2], entry[3], entry[4]);
    }).collect(Collectors.toList());

    reader.close();
}

I hope it helps. 希望对您有所帮助。

Some good answers have been provided already, I just wanted to point out a more "professional" solution in the case you were looking into a developing a structured application then consider Spring Batch flat file reader here . 已经提供了一些很好的答案,如果您正在研究开发结构化的应用程序,然后在这里考虑Spring Batch平面文件阅读器,我只是想指出一个更“专业”的解决方案。

Although I am not crazy i know this is quite a overhead and I understand this is a homework and possibly a simple Java application. 尽管我并不疯,但我知道这是相当大的开销,而且我知道这是一项家庭作业,并且可能是一个简单的Java应用程序。 I just think this is a nice reference for the future though. 我只是认为这是将来的不错参考。

With flat file reader / writer you can map your flat file into a POJO (Plain Old Java Object) and you can also use Spring batch to concatenate operations to give your batch application a nicer structure. 使用平面文件读取器/写入器,您可以将平面文件映射到POJO(普通的旧Java对象)中,还可以使用Spring批处理连接操作,从而为批处理应用程序提供更好的结构。

Here a simple snippet of how it works (from the link above): 以下是其工作原理的简单片段(来自上面的链接):

@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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM