Объекты в Java ArrayList не обновляются - PullRequest
0 голосов
/ 24 марта 2010

РЕШИТЬ:

Вот что было не так:

    current.addFolder(folder); (in the final else clause of the if statement)

Добавлена ​​новая папка, но не гарантируется, что переданная папка является папкой, добавленной, она может просто ничего не делать, если папка уже существует, поэтому для преодоления этого я изменила addFolder, чтобы она возвращала фактическую папку (например, если она уже есть) существовал), и я назначил папку для этого возвращаемого значения. И это сработало, так что теперь у меня есть:

    folder = current.addFolder(folder);
    current = folder;

Большое спасибо людям, ваша помощь была высоко оценена :)


Это будет очень длинный пост, надеюсь, вы понимаете, о чем я говорю, и я ценю любую помощь. Спасибо


По сути, я создал личный некоммерческий проект (который я не планирую выпускать), который может читать файлы ZIP и RAR. Он может только читать содержимое архива, папки внутри, файлы внутри папок и его свойства (такие как дата последнего изменения, время последнего изменения, контрольная сумма CRC, несжатый размер, сжатый размер и имя файла). Он также не может извлекать файлы, так что это действительно программа просмотра ZIP / RAR, если вы можете.

В любом случае, это немного не имеет отношения к моей проблеме, но я подумал, что дам вам некоторую справочную информацию.

Теперь по моей проблеме:

Я могу успешно перечислить все папки и файлы в ZIP-архиве, так что теперь я хочу взять этот необработанный ввод и связать его вместе некоторым полезным способом. Я сделал 2 класса: ArchiveFile (представляет файл внутри ZIP) и ArchiveFolder (представляет папку внутри ZIP). У них обоих есть несколько полезных методов, таких как getLastModifiedDate, getName, getPath и так далее. Но разница в том, что ArchiveFolder может содержать ArrayList ArchiveFile и дополнительные ArchiveFolder (представьте, что это файлы и папки внутри папки).

Теперь я хочу заполнить свой необработанный ввод одним root ArchiveFolder, в котором будут все файлы в корневом каталоге ZIP в ArrayList ArchiveFile и любые дополнительные папки в корневом каталоге ZIP. в ArrayList ArchiveFolder (и этот процесс может продолжаться так же, как цепная реакция (больше файлов / папок в этом ArchiveFolder и т. д. и т. д.).

Итак, я придумал следующий код:

while (archive.hasMore()) {
    String path = ""; 
    ArchiveFolder current = root; 
    String[] contents = archive.getName().split("/");

    for (int x = 0; x < contents.length; ++x) {
        if (x == (contents.length - 1) && !archive.getName().endsWith("/")) { // If on last item and item is a file 
            path += contents[x]; // Update final path ArchiveFile 
            file = new ArchiveFile(path, contents[x], archive.getUncompressedSize(), archive.getCompressedSize(), archive.getModifiedTime(), archive.getModifiedDate(), archive.getCRC());

            current.addFile(file); // Create and add the file to the current ArchiveFolder
        }
        else if (x == (contents.length - 1)) { // Else if we are on last item and it is a folder
            path += contents[x] + "/"; // Update final path
            ArchiveFolder folder = new ArchiveFolder(path, contents[x], archive.getModifiedTime(), archive.getModifiedDate());

            current.addFolder(folder); // Create and add this folder to the current ArchiveFile
        }
        else { // Else if we are still traversing through the path
            path += contents[x] + "/"; // Update path
            ArchiveFolder folder = new ArchiveFolder(path, contents[x]);

            current.addFolder(folder); // Create and add folder (remember we do not know the modified date/time as all we know is the path, so we can deduce the name only)
            current = folder; // Update current ArchiveFolder to the newly created one for the next iteration of the for loop
        }
    }

    archive.getNext();
}

Предположим, что root является корневым ArchiveFolder (изначально пустым). И этот archive.getName () возвращает имя текущей папки ИЛИ файла следующим образом: file.txt или folder1 / file2.txt или folder4 / folder2 / (это пустая папка) и т. Д. Таким образом, в основном относительный путь от корень ZIP-архива.

Пожалуйста, прочитайте комментарии в приведенном выше коде, чтобы ознакомиться с ним. Также предположим, что метод addFolder в ArchiveFile добавляет папку только в том случае, если она еще не существует (поэтому нет нескольких папок), а также обновляет время и дату существующей папки, если она пуста (т. Е. Она была промежуточную папку мы знали только по названию, но теперь мы знаем ее детали). Код для addFolder (довольно понятный):

public void addFolder(ArchiveFolder folder) {
    int loc = folders.indexOf(folder); // folders is the ArrayList containing ArchiveFolder's

    if (loc == -1) {
        folders.add(folder);
    }
    else {
        ArchiveFolder real = folders.get(loc);

        if (real.getTime() == null) {
            real.setTime(folder.getTime());
            real.setDate(folder.getDate());
        }
    }
}

Так что я не вижу ничего плохого в коде, он работает, и после его завершения корневой ArchiveFolder содержит все файлы в корне ZIP, как я хочу, и содержит все директории в корневой папке. как я хочу. Таким образом, вы могли бы подумать, что он работает как положено, но никакие ArchiveFolder в корневой папке не содержат данных внутри этих «дочерних» папок, это просто пустая папка без дополнительных файлов и папок (хотя она действительно содержит еще несколько файлы / папки при просмотре в WinZip).

После отладки с использованием Eclipse цикл for выполняет итерацию по всем файлам (даже тем, которые не включены выше), так что это заставило меня поверить, что есть проблема с этой строкой кода:

            current = folder;

Что он делает, он обновляет текущую папку (используемую в качестве промежуточного звена в цикле) для вновь добавленной папки.

Я думал, что Java передается по ссылке, и, таким образом, все новые операции и новые добавления в будущих ArchiveFile и ArchiveFolder будут автоматически обновляться, и родительский ArchiveFolder будет обновляться соответствующим образом. Но это не похоже на случай?

Я знаю, что это длинная задница, и я очень надеюсь, что кто-нибудь может помочь мне с этим.

Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 24 марта 2010

Поскольку вы используете eclipse, устанавливаете точку останова и шагаете по методу, это может занять некоторое время, но это помогает находить ошибки. (проверьте идентификаторы объекта, например, чтобы увидеть, изменилась ли ссылка).

1 голос
/ 24 марта 2010

Java на самом деле не передает ссылки так, как вы понимаете это, например, в C ++.Он проходит по значению, но все переменные не примитивных типов на самом деле являются указателями на объекты.Таким образом, всякий раз, когда вы передаете переменную методу, вы даете или копируете указатель, то есть обе переменные указывают на один и тот же объект (измените объект с одного, а другой «увидит» изменение. указатель на стороне вызывающего или вызываемого абонента не изменит указателя на другой стороне.

Надеюсь, я свободен?

0 голосов
/ 24 марта 2010

Я подозреваю, что вы неправильно перегрузили equals () и hashCode () в вашем классе ArchiveFolder, и, следовательно,

folders.indexOf(folder)

в addFolder () всегда возвращает -1.

...