繁体   English   中英

Java中文件处理的可重试模式

[英]Retryable pattern for file processing in java

我需要处理一个大文件(具有列和相同格式的行)。 由于我需要考虑程序在处理过程中崩溃的情况,因此我需要将此处理程序重试,这意味着在它崩溃并再次启动程序后,它可以继续处理文件,从失败的行开始。

有什么我可以遵循的模式或可以使用的图书馆吗? 谢谢!


更新:

关于崩溃的情况,不仅涉及OOM或一些内部问题。 也可能是由于其他零件超时或机器崩溃导致的。 因此,try / catch无法处理此问题。


另一个更新:

关于对文件进行分块,在我看来,这是可行的,但听起来并不那么简单。 就像我说的那样,文件是用几列格式化的,我可以根据其中一列将其拆分成数百个文件,然后逐个处理文件。 但是,除了这样做,我想了解有关处理大文件/数据支持重试的通用解决方案的更多信息。

我会怎么做(虽然不是专业人士)

  1. 在文件的每一行上创建一个LineProcessor调用

    类Processor实现LineProcessor> {

      private List<String> lines = Lists.newLinkedList(); private int startFrom = 0; private int lineNumber = 0; public Processor(int startFrom) { this.startFrom = startFrom; } @Override public List<String> getResult() { return lines; } @Override public boolean processLine(String arg0) throws IOException { lineNumber++; if (lineNumber < startFrom) { // do nothing } else { if (new Random().nextInt() % 50000 == 0) { throw new IOException("Randomly thrown Exception " + lineNumber); } //Do the hardwork here lines.add(arg0); startFrom++; } return true; } } 
  2. 创建一个使用我的LineProcessor可调用文件来读取

     class Reader implements Callable<List<String>> { private int startFrom; public Reader(int startFrom) { this.startFrom = startFrom; } @Override public List<String> call() throws Exception { return Files.readLines(new File("/etc/dictionaries-common/words"), Charsets.UTF_8, new Processor(startFrom)); } } 
  3. Callable包装在Retryer中,然后使用Executor调用它

     public static void main(String[] args) throws InterruptedException, ExecutionException { BasicConfigurator.configure(); ExecutorService executor = Executors.newSingleThreadExecutor(); Future<List<String>> lines = executor.submit(RetryerBuilder .<List<String>> newBuilder() .retryIfExceptionOfType(IOException.class) .withStopStrategy(StopStrategies.stopAfterAttempt(100)).build() .wrap(new Reader(100))); logger.debug(lines.get().size()); executor.shutdown(); logger.debug("Happily Ever After"); 

    }

您可以在代码中维护检查点/提交样式逻辑。 因此,当程序再次运行时,它将从同一检查点开始。

您可以使用RandomAccessFile读取文件,并使用getFilePointer()作为保存者的检查点。 当您再次执行程序时,可以通过调用seek(offset)从此检查点开始。

尝试从OOM错误中捕获获胜者。 您应该对文件进行分块处理,并在每次成功处理后将位置存储到文件系统/数据库/即使程序崩溃也可以保持持久性的任何位置。 然后,您可以在重新启动软件时从存储它的位置读取上一点。 在处理整个文件时,您还必须清除此信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM