Java 处理100万个文件大小介于kbs到100 GB之间的文本文件

Java 处理100万个文件大小介于kbs到100 GB之间的文本文件,java,multithreading,Java,Multithreading,我想处理大量的文件,从一个顶级目录路径开始,并在目录中的每个文件上应用转换(将字符a转换为字符b) 目录和任何子目录中的任何文件。如果顶级目录路径为“/path/to/directory”,则输出结果将写入路径“/path/to/directory converted”处的目录。 目录的深度和文件的数量可以任意大,1000级深度和1000000个文件。每个输入文件可以任意大,例如100GB大小 我从编写一个递归函数开始,该函数从顶部目录开始,使用new java.io.file(pathToDi

我想处理大量的文件,从一个顶级目录路径开始,并在目录中的每个文件上应用转换(将字符a转换为字符b) 目录和任何子目录中的任何文件。如果顶级目录路径为“/path/to/directory”,则输出结果将写入路径“/path/to/directory converted”处的目录。 目录的深度和文件的数量可以任意大,1000级深度和1000000个文件。每个输入文件可以任意大,例如100GB大小

我从编写一个递归函数开始,该函数从顶部目录开始,使用new java.io.file(pathToDirectory)创建一个新文件,检查文件是文件还是目录,并进行转换

private void applyTransform(文件parentFile){
对于(文件项:parentFile.listFiles()){
if(fileEntry.isDirectory()){
应用转换(文件输入);
}否则{
//转换文件
}
}
}
由于递归方法可能导致堆栈溢出,我将其更改为使用队列并获取要处理的文件列表

public List<String> getAllFilesToTransform(String pathToDir) {
    List<String> result = new ArrayList<>();
    Queue<String> queue = new LinkedList<>();
    queue.add(pathToDir);

    while (!queue.isEmpty()) {
      String currentPath = queue.poll();
      File currentFile = new File(currentPath);
      for (File file : currentFile.listFiles()) {
        if (file.isDirectory()) {
          queue.add(currentPath + "/" + file.getName());
        } else {
          result.add(currentPath + "/" + file.getName());
        }
      }
    }
    return result;
}
我不熟悉多线程以及使用它的潜在影响。 有两个问题我想解决,但不确定或有经验,什么是最好的方式和方法来做到这一点

  • 我必须处理1000万个文件
  • 每个文件可以是100 GB
  • 要处理第一个问题,我是否在实现Runnable接口的单独类中迭代列表中的每个文件,从
    getAllFilesToTransform
    ? 要处理第二个问题,我是否可以在单独的工作线程中读取x个字符,然后对它们运行转换并继续写入目标文件

    处理这两个问题的最佳方法是什么


    更新-这不是我试图在工作中实现的实际要求,而是作为一个模拟,我正在学习处理缩放问题并使用多线程解决这些问题。

    关于文件数量:假设您停留在整体设计中(即一个进程):

  • 实现将文件插入阻塞队列的
  • 与该文件访问者一起使用
  • 使用该队列生成一个队列

  • 对于文件大小-如果您不知道哪些文件是100GB,哪些是1k(即,就您而言,这是随机的),那么只需在一个输入文件和一个输出文件上执行一个任务即可。缓冲流针对大文件进行了优化,系统不会在内存中保留100GB。

    您在这里使用Java的动机是什么?这是我对Web应用程序的目标,但在这种情况下,shell脚本+Ruby可能是一个更简单(且易于并行化)的解决方案。这听起来像是一个庞大的项目,如果你真的要处理数百万个100GB的文件,那么答案是单台机器是不合理的。我将研究Hadoop、spark等框架,。。。能够让多台机器并行工作的东西。当然,驱动您设计的真正问题是:什么样的存储基础结构可以容纳所有这些文件?!注意:不要使用空的挡块!在做您想做的事情时,准确理解运行时发生的事情是绝对重要的。忽略异常与良好实践正好相反!如果1000000个文件都有100 GB的数据,那么您所说的是100 EB的数据和市场上最大的7000到8000个驱动器。使用10千兆/秒的链路将如此多的数据上传到云端需要2.5年的时间。那么真正的总数是多少呢?@GhostCat谢谢你建议的方法。我认为使用Hadoop和Spark是满足这样一个需求的好方法。我肯定会用它来做一个项目,试着以较小的规模在AWS这样的基础设施上并行运行,然后像一个实例一样运行,比如说在5个不同的实例上运行t2.large(4Gb ram和2 CPU)实例大小,并计算处理时间。(这只是我正在考虑的一个开始规范。我将更新我实际使用和尝试的规范)。谢谢很好的建议。我将理解步骤中列出的javadoc,并尝试一下。非常感谢。
    private void processFile(String filePath) {
        try {
          BufferedReader bufferedReader = Files.newBufferedReader(Paths.get(filePath));
          char[] chars = new char[4096];
          while (bufferedReader.read(chars) != -1) {
            transformChars(chars, filePath);
            BufferedWriter writer = new BufferedWriter(new FileWriter(pathToDir));
          writer.write(fileText);
          writer.close();
          }
        } catch (IOException e) {
    
        }
      }
    
    private void transformChars(char[] chars, String filePath) {
      try {
        BufferedWriter writer = new BufferedWriter(new FileWriter(pathToDir, true));
          //transform char array and append to file
          writer.write(fileText);
          writer.close();
    }