我遇到了这种方法的问题。该方法应该读取一系列数据的文本文件(攻击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();
}
}
答案 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;
}
}