[英]Java reading Strings from a file
我在使用此方法時遇到麻煩。 該方法應該讀取一系列數據的文本文件(攻擊ID [int],日期[以MM / DD / YYYY格式保存的字符串],怪物[String]的名稱,位置[String]和報告者)攻擊[String]),以逗號分隔,然后將這些值放入名為MonsterAttacks的ArrayList中。 每次我運行此方法時,都會收到一個InputMismatchException。 我感覺它與日期有關,但是在這種情況下我不確定在哪里或如何使用String split()方法。 我該如何使其正常工作?
免責聲明:這是家庭作業的一部分。
提前致謝。
編輯:來自文本文件的樣本數據:
1994年12月23日,德古拉,加利福尼亞,Trisha Takinawa
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();
}
}
您告訴我們您的數據是
被逗號隔開
如果是這樣,那么您將不得不考慮這些令牌分隔符。 進行此操作的一種方法是只讀整行,然后用逗號分隔以訪問每個術語:
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();
}
我強烈建議為此使用文件讀取器,它具有您所需的一切,並且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){`
考慮到您的項目使用Java 8,您可以使用流(使用line()
)簡單地操作文件數據,並將它們映射到所需的類(使用map()
),在這種情況下為MonsterAttack
。 就像這樣:
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();
}
希望對您有所幫助。
已經提供了一些很好的答案,如果您正在研究開發結構化的應用程序,然后在這里考慮Spring Batch平面文件閱讀器,我只是想指出一個更“專業”的解決方案。
盡管我並不瘋,但我知道這是相當大的開銷,而且我知道這是一項家庭作業,並且可能是一個簡單的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;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.