Чтение файлов 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, чтобы вы могли делать то, что вы описываете.

Другие вопросы по тегам