Чтение файлов GEDCOM: как вставить соответствующий день рождения, месяц и год в переменную Integer из входного файла в выходной файл
У меня есть входной файл GEDCOM с тоннами индивидуальных / семейных записей. Цель состоит в том, чтобы отформатировать их данные в эту форму:
имя (стр. 6, "Гарри Буис"). рождение (р6, дата (1927,11,17)). смерть (р6, дата (2001,08,21)). Famc(p6, f3). Fams(p6, f2).
Мне удалось вытащить номер человека и его имя и распечатать его в выходном файле, однако у меня возникли проблемы с анализом дат рождения / смерти. Я хочу иметь возможность использовать подстроку, чтобы назначить birthDay, birthMonth и BirthYear как целые числа, чтобы я мог распечатать его в выходной файл. Это должны быть целые числа, чтобы я мог сортировать по дате. Вот пример данных одного клиента из входного файла.
0 @P6@ INDI
1 BIRT
2 DATE 17 Nov 1924
1 NAME Harry /Buis/
1 DEAT Age: 76
2 DATE 21 Aug 2001
1 SEX M
1 FAMC @F3@
1 FAMS @F2@
И вот мой исходный код того, что я имею до сих пор:
public class Main {
static Scanner scan;
static BufferedWriter outFile;
static int birthYear = 0;
static int birthMonth = 0;
static String birthDay = "";
static int deathYear = 0;
static int deathMonth = 0;
static int deathDay = 0;
static String name = "";
static String person = "";
static String sex = "";
static String famC = "";
static String famS = "";
static String man = "";
static String woman = "";
static String child = "";
public static void parse() throws IOException {
scan = new Scanner(new FileReader("pbuis.ged"));
outFile = new BufferedWriter(new FileWriter("output.txt"));
String reader = scan.nextLine();
int count = 0;
while (scan.hasNextLine()) {
if (reader.contains("NAME") && count < 1) {
reader = reader.substring(1).replace("/", "");
count++;
System.out.println(reader);
name = reader.replace("NAME", "");
}
if (reader.startsWith("0")) {
person = reader.trim().substring(2, 7).replace("@", "")
.replace("I", "").trim().toLowerCase();
System.out.print(person);
count = 0;
}
if (reader.contains("BIRT")) {
scan.nextLine();
birthDay = Integerreader.substring(6, 9).trim();
}
if (reader.equalsIgnoreCase("") || reader.equalsIgnoreCase(" ")) {
outFile.write("name(" + person + ", " + "'" + name.trim() + "'"
+ ")." + "\n" + birthDay);
}
reader = scan.nextLine();
}
}
public static void main(String[] args) throws IOException {
parse();
}
}
Без оператора if (содержит "BIRT") и "birthDay" нет в методе outFile.write(), мой вывод выглядит следующим образом:
name(p1, 'Paul Edward Buis').
name(p2, 'Thomas Edward Buis').
name(p3, 'Jennifer Joy Buis').
name(p4, 'Daniel Paul Buis').
name(p5, 'Barbara Joy VanderWall').
name(p6, 'Harry Buis').
это хорошее начало
Но когда я получаю это утверждение if, я получаю такую ошибку, и ничего не печатается:
p1Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 9
at java.lang.String.substring(Unknown Source)
at Main.parse(Main.java:50)
at Main.main(Main.java:64)
Теперь, я попробовал каждую комбинацию значений индекса подстроки, и ничего, кажется, не работает. Есть идеи, как мне это исправить?
Заранее спасибо.
2 ответа
Я предлагаю вам использовать функцию даты. Функции даты можно сортировать проще, чем год / месяц / дата. Если вы действительно хотите, храните их в миллисекундах с начала эпохи.
Чтобы разобрать дату, используйте SimpleDateFormatter. Я считаю, что-то вроде этого будет работать:
SimpleDateFormatter dateFormat=new SimpleDateFormat("dd mmm yyyy")
Date birth=date.parse("17 jul 1984",0);
Когда вы добавите его в формат Date, вы сможете сделать много полезных вещей, например:
Date date1, date2;
date1.after(date2);
date1.compareTo(date2)
Вы могли бы даже получить минуты или секунды, но я не рекомендую это. Обратите внимание, что 0 относится к индексу, начинающему строку, так что вы можете просто указать индекс, с которого начинается формат, и все хорошо. В целом, я думаю, что это намного чище.
Парсинг даты из файлов GEDCOM сложен. Вы можете использовать SimpleDateFormatter для любых дат в формате дд MMM гггг (например, 26 сентября 2015 г.), но GEDCOM поддерживает множество странных изменений, включая неточные даты, когда у вас есть только месяц и год или только год. Он также позволяет использовать такие префиксы, как "ABT", чтобы указать, что что-то произошло около определенной даты, допускает диапазоны ("BET date1 AND date2") и ("FROM date1 TO date2"), а также множество других сложных действий (французский республиканец или Еврейские календари, кто-нибудь?)
Я бы порекомендовал использовать gedcom4j ( http://gedcom4j.org/), которая является библиотекой Java, которую вы можете добавить в свою программу для загрузки данных в объекты Java, а затем делать то, что вам нужно. Класс DateParser в этой библиотеке может интерпретировать ваши строковые значения и превращать их в значения java.util.Date, чтобы вы могли делать то, что вы описываете.