Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > RandomAccessFile и ошибка записи объекта в файл


Автор: Leledinn 28.11.2008, 15:19
Добрый день.

Есть непонятная проблема, которая ставит меня в тупик. 

Я запускаю тест-класс пакета JUnit в среде Netbeans в режиме Run и получаю IOException при записи второго элемента массива ArrayList<Element> (соответственно, остальные элементы массива тоже не записываются). В тоже время запуск этого же теста в режиме Debug по шагам и просто прогоном нормально проходит и все объекты массива записываются в файл. Также нормально проходит запись, если объект единственный - в любом случае: в debug или run.

Понять не могу ,то ли это Нетбинс тупит, то ли я. Скорее всего - я, поэтому прошу помощи.
 
Код:
Код

//

public class DiskReaderWriter {

//...

private RandomAccessFile file; 
private Cursors cursors;
//....
private FileImageOutputStream fios;

private void writeToCursor(Element element, CursorObject cursor) throws CacheException {        
        Long pointer = cursor.getAddress(); //получаем стартовый адрес для записи
        try {
            fios = new FileImageOutputStream(file); //открываем поток записи
            fios.seek(pointer); //устанавливаем курсор
            fios.write(Element.getBytes(element)); //сериализуем элемент для записи, формируем массив байтов и пишем в поток[color=red][font=tahoma]<<<<< Ошибка[/font][/color]  
            fios.flush(); 
        } catch (IOException ex) {
            throw new DiskCacheException(ex, CacheException.E_SOURCE_DISK_IOERROR);       [color=red][font=tahoma]<<<<< Ошибка[/font][/color]
        } finally {
        }
    }

private CursorObject validateWrite(Element element) throws CursorCacheException { //метод для получения курсора (адрес, длина) - 
        CursorObject cursor = null;

        try {
            cursor = cursors.setCursor(element.getObjectKey(), ((Long) element.getSerializedSize()).intValue());
        } catch (CursorCacheException CCE) {
            throw CCE;
        }

        return cursor;
    }

public boolean putElement(Element element) throws CacheException { //public метод записи элемента в файл
        CursorObject cursor;
        try {
            cursor = validateWrite(element); //получаем курсор (за это отвечает класс, работоспособность которого проверена другими тестами)
            if (cursor != null) {
                this.writeToCursor(element, cursor); // пишем на диск элемент в указанное курсором место в файле
                return true;
            }
        } catch (CursorCacheException CCE) {
            return false;
        }
        return false;
    }

public boolean createTMPFile(String fileName) {
        try {
            file = new RandomAccessFile(fileName, "rw");
            file.seek(0);
            //current = file.getFilePointer();
        } catch (FileNotFoundException fnfex) {
            logger.severe("File not found: " + fnfex);
            return false;
        } catch (IOException ioex) {
            logger.log(Level.SEVERE, null, ioex);
        }
        this.fileName = fileName;
        return true;
    }

}


Код

[color=red]// код, где происходит формирование объектов и попытка записи в файл (часть метода, вызываемого JUnit TestCase): [/color]

private DiskReaderWriter drw = null; //объект класса для работы с диском

{
// инициализация объектов 
}

ArrayList<Element> elements = new ArrayList<Element>();

        for (int i = 0; i < 5; i++) {  //создаем массив объектов для записи
            elements.add(new Element(
                    new String("KEY" + i),
                    new String("VALUE" + i),
                    System.currentTimeMillis()));
        }

        if (drw.createTMPFile("TMP" + System.currentTimeMillis() + ".TMP")) { //открываем файл для записи 
            boolean success = true;
            for (int j = 0; j < elements.size(); j++) {
                success = success && drw.putElement(elements.get(j)); //пытаемся писать элементы массива

                //Element readElement = drw.getElement("KEY" + j);
                logger.info("Object written: " + elements.get(j).toString());
                //logger.info("Object read: " + readElement.toString());
            }
            return success && drw/*.deleteTMPFile();/*/.closeTMPFile();
        } else {
            return false;
        }


CursorObject представляет собой объект, в котором хранится текущий адрес записываемого объекта и длина  сериализованного объекта в байтах.  Адрес и длина используется для установки курсора для РандомАксесс файла.
Cursors - это хранилище объектов типа CursorObject. Карта размещения объектов в РандомАксесс файле. Используется для хранения  структуры файла ,в который ведется запись.
Element - это класс, который представляет собой описание объекта, записываемого на диск. Конкретный экземпляр класса сериализуется и побайтно пересылается в буфер записи. 

Данные, поступающие на запись проверены другими тестами и 100% правильные. 

Таки, в чем проблема? Во мне или в Netbeans и JUnit? Сижу полдня уже и понять не могу, где ошибка. Глаз замылен. Помогите, пожалуйста.

Добавлено @ 15:28
Да, забыл сказать: объекты, записываемые в файл имеют произвольную длину.  Т.е. Element   является оберткой для объектов любого типа. Поэтому используется такой дикий механизм записи в файл. 

Автор: ivg 29.11.2008, 01:49
Код

    private void writeToCursor(Element element, CursorObject cursor) throws CacheException {        
        Long pointer = cursor.getAddress(); //получаем стартовый адрес для записи
        try {
            this.file.seek(pointer); //устанавливаем курсор
            this.file.write(Element.getBytes(element));
        } catch (IOException ex) {
            throw new DiskCacheException(ex, CacheException.E_SOURCE_DISK_IOERROR);
        }
    }
...
    public boolean createTMPFile(String fileName) {
        try {
            this.file = new RandomAccessFile(fileName, "rwd");
        } catch (FileNotFoundException fnfex) {
            logger.severe("File not found: " + fnfex);
            return false;
        } catch (IOException ioex) {
            logger.log(Level.SEVERE, null, ioex);
            return false;
        }
        this.fileName = fileName;
        return true;
    }

Автор: Leledinn 11.12.2008, 10:19
Проблема решена.

Спасибо ))

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)