RandomAccessFile записывает в файл правильно, но при поиске записей это не удается

Я студент по информатике, изучаю диплом IB. У меня есть задание, включающее класс RAF(RandomAccessFile), и я должен использовать его в следующей программе. Я понимаю, что лучше использовать ArrayList и сериализацию программы в файл, но это будет на моем экзамене, и в результате я должен изучить это. Это моя третья попытка понять эту концепцию, и она сводит меня с ума.

Цель этой программы - заполнить файл.dat записями одинакового размера с разными полями. В конце концов, программа должна представлять собой графический интерфейс с различными отображаемыми полями, и она должна позволять пользователю добавлять записи, а также искать, сортировать, редактировать и удалять записи.

GUI, который я создал в NetBeans, выглядит следующим образом:

введите описание изображения здесь

И так как мне нужно создавать записи на основе размера байта каждого поля, я разработал следующее изображение, которое содержит максимальный размер каждого поля в количестве символов, а также пример изображения для проверки моих рассуждений: введите описание изображения здесь

Поняв, что размер байта каждой записи равен 102, я использовал эти знания для дальнейшего развития программы, создав метод записи записей в двоичный файл. Затем я создал один, который предназначен для возвращения записей в файл. Тем не менее, здесь все идет не так, как надо. Если я введу только одну запись, это почти нормально. Я могу ввести эту единственную запись...

введите описание изображения здесь введите описание изображения здесь

Но если я закрою программу, а затем снова открою ее, возраст лошади изменится:

введите описание изображения здесь

и если я попытаюсь получить более одной записи одновременно, программа не получит их все:

введите описание изображения здесь Конечно, здесь я просто использовал 'smashes клавиатуры' для быстрого заполнения большего количества записей, но, как вы можете видеть, он объединяет разные записи и помещает их все в один столбец таблицы. Этого не должно случиться.

Наконец, я получаю это исключение каждый раз:

Apr 12, 2016 10:18:17 PM horsemanager.HorseManager <init>
SEVERE: null
java.io.EOFException
    at java.io.RandomAccessFile.readChar(RandomAccessFile.java:773)
    at horsemanager.BinaryFile.getString(BinaryFile.java:118)
    at horsemanager.BinaryFile.readNextRecord(BinaryFile.java:99)
    at horsemanager.HorseManager.<init>(HorseManager.java:38)
    at horsemanager.HorseManager$7.run(HorseManager.java:453)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Это исключение происходит независимо от количества записей в файле.

BinaryFile.getString ():

    public static String getString(int maxLength) throws IOException{
//maxLength indicates the maximum length of the particular field(eg. the horses name is maximum 25 characters so the maxLength in that case would be 25)
            String concat = ""; //to pull the entire string from the file
            int length = raf.readShort(); //to get the length of the string
            for(int j = 0 ; j<length; j++){ //to make sure to get the whole word
                    concat += raf.readChar();
//gets the word character by character. also, this is the line that has the error
            }
            for(int i=length; i<maxLength; i++){ //to skip forward if there is any blank space following the String
                raf.readChar();
            }
            return concat; //returns the full string
        }

BinaryFile.readNextRecord ():

public static Object[] readNextRecord(int recordNumber) throws IOException {
        ID++;
        raf.seek(recordNumber * RecordLength);
        Object[] horse = {ID,
                getString((int)ShowNameLength),
                getString((int)BarnNameLength), //this line is the one that garners the error
                getString((int)CoatColorLength),
                getShort()} ;
                return horse;
    }

Я чувствую, что мои исключения происходят из-за способа записи записей в файл, но я не уверен, что любые изменения, которые я внес в файл, ничего не изменили.

Если нужна дополнительная информация, спросите меня! В противном случае это полный класс BinaryFile.java: http://pastebin.com/FWzmL2Aa

и это полный класс HorseManager.java: http://pastebin.com/hsHVmQFT

1 ответ

Вы используете это, чтобы написать возраст. Это в основном записывает возраст в виде последовательности 16-битных символов в файл.

public static void writeShort(int maxLength, short a) throws IOException {
    int length;
    String A = a + ""; // changing short to String
    if (A.length() < maxLength) {
        length = A.length();
    } else {
        length = maxLength;
        A = A.substring(0, maxLength);
    }

    int toBlanc = maxLength - length;
    char pointer;

    // writing the age as a sequence of 16 bit characters.
    for (int j = 0; j < A.length(); j++) {
        pointer = A.charAt(j);
        raf.writeChar(pointer);
    }

    for (int j = 0; j < (maxLength - A.length()); j++) {
        raf.writeChar(' ');
    }
} 

Вы используете это, чтобы прочитать возраст. Это читает возраст как короткий.

public static short getShort() throws IOException{
    return raf.readShort();
}

https://docs.oracle.com/javase/7/docs/api/java/io/RandomAccessFile.html

Ваш пример: возраст меняется с 12 до 49

Когда вы пишете 12 лет, вы пишете 16 битов символа "1", за которыми следуют 16 битов символа "2". Когда вы читаете возраст, ваш readShort() будет читать только первые 16 битов и считать их двоичным представлением короткого замыкания. Двоичный код для '1' - 0000 0000 0011 0001 readShort() интерпретирует это как 49. Теперь второй набор из 16 битов интерпретируется как что-то еще, и все последующие записи перемешиваются.

Решение

Сделайте ваши readShort и writeShort согласованными.

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