1

如何遍历目录中的所有 RAR 档案。我知道如何遍历目录中的文件,但我只对 RAR 档案感兴趣。如果它们是带有扩展名的简单 RAR 档案,.rar那将不是问题,但我的目录可以有多个跨区档案,我只想要集合中的第一个/主卷。我还想在目录中有其他文件:

以下是示例目录的内容:

  • file.txt
  • somefile.zip
  • hello.rar
  • test.part1.rar
  • test.part2.rar
  • example.rar
  • example.r00

结果:

  • file.txt
  • somefile.zip
  • hello.rar
  • test.part1.rar
  • example.rar

这就是我在目录上使用的迭代:

  import java.io.File;

  ...

  for (File child : (new File(myDirectoryPath)).listFiles()) {
    if (!child.isDirectory()) {
      //Do something with the file
    }
  }

我怎样才能做到这一点?我需要检测它是否是 RAR 存档。如果不是,请使用它。如果是,我需要检查它是否是档案的第一部分。如果是,请执行任何操作,否则忽略它。

谢谢

4

4 回答 4

2

寻找解决方案的困难在于,当 .rar 档案跨越多个文件时,没有固定的命名技术。此外,没有什么可以阻止用户创建一个随机文件,该文件被命名为好像它是一个跨越的 rar 部分之一。确定这一点的唯一正确方法是实际读取每个可疑文件的内容,并查看这是否是跨区 rar 文件的延续。除了复杂之外,这也将是令人无法接受的缓慢。

但是,在大多数情况下,拆分文件以file.rarfile.rXX恰好 2 位数字)作为延续或file.partXXX.rar以第一个文件命名file.part1.rar(XXX 从 1 开始,一直到最大数字)。因此,您可以尝试使用以下内容来捕捉这两种情况FilenameFilter

这种方法的缺点是,如果文件碰巧被随机命名,它会丢弃文件,例如,somefile.part2.rar或者otherfile.r03,但是,希望这在很大程度上对您有所帮助。

for (File child : (new File(myDirectoryPath)).listFiles(new FilenameFilter() {
    private Pattern p1 = null;
    private Pattern p2 = null;
    public boolean accept(File dir, String name) {

        name = name.toLowerCase();

        if(p1 == null) {
            p1 = Pattern.compile("\\.r\\d\\d");
            p2 = Pattern.compile("\\.part\\d+\\.rar");
        }

        if(name.endsWith(".part1.rar")) {
            return true;
        }
        else if(p2.matcher(name).matches()) {
            return false;
        }
        else {
            return !p1.matcher(name).matches();
        }
    }
}) {
    if (!child.isDirectory()) {
      //Do something with the file
    }
}
于 2012-07-03T15:20:02.213 回答
2

我编写了这段代码来识别 RAR 档案,我只考虑了跨区档案的第一卷而忽略了其他档案。

/**
 * Checks whether a file is an archive
 *
 * @param    filFile        the file to checks
 * @retuns                  a bollean value indicating the result
 */
 public static Boolean isArchive(File filFile) {  

     try {

         byte[] bytSignature = new byte[] {0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00};
         FileInputStream fisFileInputStream = new FileInputStream(filFile);

         byte[] bytHeader = new byte[20];
         fisFileInputStream.read(bytHeader);

         Short shoFlags = (short) (((bytHeader[10]&0xFF)<<8) | (bytHeader[11]&0xFF));

         //Check if is an archive
         if (Arrays.equals(Arrays.copyOfRange(bytHeader, 0, 7), bytSignature)) {
             //Check if is a spanned archive
             if ((shoFlags & 0x0100) != 0) {
                 //Check if it the first part of a spanned archive
                 if ((shoFlags & 0x0001) != 0) {
                     return true;
                 } else {
                     return false;
                 }
             } else {
                 return true;
             }
         } else {
             return true;
         }

     } catch (Exception e) {
         return false;
     }

 }

我使用了官方的 RAR 标头规范。为了实现这一点并解析字节,我在这里进行了讨论:

如何从二进制文件中读取十六进制值并破译一些包含位标志值的字节?.

于 2012-07-04T10:35:34.897 回答
0

检查您的文件名是否以(“.rar”)结尾并将其放入集合中以确保唯一性

Set<String> fileSet=new HashSet<String>();

if(fileName.endsWith(".rar")){
    set.add(fileName);
}
于 2012-07-03T15:02:54.250 回答
0

第1步:File.listFile(FileFilter)是你的朋友。正确实施,这将只为您提供 RAR 和跨越文件。

第 2 步:像上面建议的那样,在不同的集合中收集所有名称的前缀。

于 2012-07-03T15:18:55.327 回答