解决:
这是错误的:
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存档中的所有文件夹和文件,所以现在我想采用原始输入并以一些有用的方式将它们链接在一起。我创建了两个类:ArchiveFile(表示ZIP中的文件)和ArchiveFolder(表示ZIP中的文件夹)。它们都有一些有用的方法,如getLastModifiedDate,getName,getPath等。 但区别在于ArchiveFolder可以保存ArchiveFile的ArrayList和其他ArchiveFolder的(将其视为文件夹中的文件和文件夹)。
现在我想将我的原始输入填充到一个 root ArchiveFolder中,它将包含ArchiveFile的ArrayList中ZIP的根目录中的所有文件以及根目录中的任何其他文件夹。在ArchiveFolder的ArrayList中压缩(这个过程可以继续像这样连锁反应(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()以下列方式返回当前文件OR文件夹的名称:file.txt或folder1 / file2.txt或folder4 / folder2 /(这是一个空文件夹)等。所以基本上相对路径来自ZIP档案的根目录。
请仔细阅读上述代码中的注释,以熟悉它。还假设ArchiveFile中的addFolder方法只添加了文件夹(如果它不存在)(因此没有多个文件夹),如果它是空白的,它还会更新现有文件夹的时间和日期(即它是中间文件夹我们只知道它的名字,但现在我们知道它的细节)。 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将相应更新。但情况似乎并非如此?
我知道这是一篇很长的帖子,我真的希望有人可以帮我解决这个问题。
提前致谢。
答案 0 :(得分:1)
例如,Java实际上并没有以你在C ++中理解它的方式传递引用。它按值传递,但非基本类型的所有变量实际上都是指向对象的指针。因此,无论何时将变量传递给方法,您都会给出指针的副本或副本,这意味着两个变量都指向同一个对象(从一个对象更改对象,另一个将“看到”更改。但是为其分配不同的值调用方或被调用方的指针不会改变另一方的指针。
希望我很清楚?
答案 1 :(得分:1)
由于您使用eclipse,设置断点并逐步执行该方法,可能需要一些时间,但它有助于查找错误。 (检查对象ID,例如查看引用是否已更改)。
答案 2 :(得分:0)
我怀疑你没有在ArchiveFolder类上正确重载equals()和hashCode(),因此
folders.indexOf(folder)
addFolder()中的始终返回-1。