在目录中搜索文件并根据公共子字符串将它们配对

Searching files in a directory and pairing them based on a common sub-string

我一直在尝试为 ImageJ 编写一个解决方案来处理我的图像。

我知道如何获取一个目录,运行 上面的命令等等。但是我 运行 现在需要开始使用某种类型的搜索功能为了在一个充满图像对的目录中将两个图像配对在一起。

我希望你们能确认我的方向是正确的,我的想法是正确的。到目前为止,事实证明我很难理解,因为我在 Java 上的经验还不到一个月。因为这个项目直接用于我的研究,所以我确实有足够的动力来完成它,我只需要一些方向来了解哪些功能对我有用。

我最初想到使用正则表达式,但我看到当你开始处理大量图像时(尤其是使用 imagej,它似乎不能很好地转储数据使用,如果这是正确的说法的话)regex is very slow.

这些图片的一般格式是:

它们按字母顺序排列,因此应该可以转到列表中的下一张图片。我只是有点迷失了我应该使用什么功能来完成这个,但我认为我的整体 while 结构是正确的。感谢 Java 论坛的一些帮助。但是我仍然不知道下一步该去哪里。

到目前为止,这是我的代码:感谢 this SO 对部分代码的回答

int count = 0;
getFile("C:\");

string DAPI;
string GFP;


private void getFile(String dirPath) {
    File f = new File(dirPath);
    File[] files = f.listFiles();

    while (files.length > 0) {
        if (/* File name contains "DAPI"*/){
            DAPI = File f;
            string substitute to get 'GFP' filename
            store GFP file name into variable
            do something(DAPI, GFP);
        }
        advance to next filename in list
    }
}

截至目前,我真的不知道如何在字符串中搜索字符串。我见过正则表达式捕获组和其他解决方案,但我不知道 "best" 用于处理数百张图像的解决方案。

我也不知道用什么函数来替换子字符串。

如果你们能指出最适合这种情况的功能,我将不胜感激。我喜欢自己弄清楚如何制作它我只需要帮助获得正确的信息。还要确保我没有在这里犯重大逻辑错误。

如果您的文件名遵循您提到的简单模式,您似乎不需要正则表达式。您可以简单地遍历文件并根据文件名是否包含 DAPI 进行过滤,例如见下文。此代码可能过于简化了您的要求,但根据您提供的详细信息我无法判断。

import java.io.*;


public class Temp {

  int count = 0;

  private void getFile(String dirPath) {
    File f = new File(dirPath);
    File[] files = f.listFiles();

    if (files != null) {
      for (File file : files) {
        if (file.getName().contains("DAPI")) {
          String dapiFile = file.getName();
          String gfpFile = dapiFile.replace("DAPI", "GFP");
          doSomething(dapiFile, gfpFile);
        }
      }
    }
  }

  //Do Something does nothing right now, expand on it.
  private void doSomething(String dapiFile, String gfpFile) {
    System.out.println(new File(dapiFile).getAbsolutePath());
    System.out.println(new File(gfpFile).getAbsolutePath());
  }

  public static void main(String[] args) {
    Temp app = new Temp();
    app.getFile("C:\tmp\");
  }

}

注意:根据 Vogel612 的回答,如果您有 Java 8 并且喜欢功能性解决方案,您可以:

private void getFile(String dirPath) {
  try {
    Files.find(Paths.get(dirPath), 1, (path, basicFileAttributes) -> (path.toFile().getName().contains("DAPI"))).forEach(
      dapiPath -> {
        Path gfpPath = dapiPath.resolveSibling(dapiPath.getFileName().toString().replace("DAPI", "GFP"));
        doSomething(dapiPath, gfpPath);
      });
  } catch (IOException e) {
    e.printStackTrace();
  }
}

//Dummy method does nothing yet.
private void doSomething(Path dapiPath, Path gfpPath) {
  System.out.println(dapiPath.toAbsolutePath().toString());
  System.out.println(gfpPath.toAbsolutePath().toString());
}

使用 java.io.File 是解决此问题的错误方法。您正在寻找的是使用 Files.find 的基于流的解决方案,它看起来像这样:

 Files.find(dirPath, 1, (path, attributes) -> {
     return path.getFileName().toString().contains("DAPI");
 }).forEach(path -> {
    Path gfpFile = path.resolveSibling(/*build GFP name*/);
    doSomething(path, gfpFile);
 });

它的作用是:

  • 遍历 dirPath 1 级深(可能会调整)
  • 以下的所有 Path
  • 检查文件名是否包含 "DAPI"
  • 使用这些文件找到相关的"GFP"-文件
  • 送给他们 doSomething

这比文件解决方案更可取,原因有很多:

  1. 失败时提供更多信息
  2. 它比基于文件的解决方案更清晰、更简洁,而且不必检查 null
  3. 它向前兼容,因此优于基于 File 的解决方案

Files.find 从 Java 8 开始可用