java - "java.io.FileNotFoundException: No files matched spec"虽然文件已成功写入

标签 java file google-cloud-dataflow filenotfoundexception apache-beam

Edit -- the error seems to come not from the write block but from the output block, which is even stranger. Modified to reflect my investigations.

Edit2 -- solved - the issue is due to an improperly closed writer, for some reason only triggered in the DataflowRunner but not in the DirectRunner. Will add an answer later today when I find the time. If anyone has an insight on why the writer is closed in the DirectRunner but not in the DataflowRunner, I am very interested.


考虑以下 Java 2.5.0 数据流代码:

BlobId blobTranscriptId = BlobId.of(tempBucket, fileName);
BlobInfo blobTranscriptInfo = BlobInfo.newBuilder(blobTranscriptId).build();
try (WriteChannel writer = storageClient.writer(blobTranscriptInfo)) {
    LOG.info("Writing file");
    writer.write(ByteBuffer.wrap(currentString.toString().getBytes(UTF_8)));
    processContext.output("gs://" + tempBucket + "/" + fileName)
    LOG.info("Wrote " + fileName);
} catch (Exception e) {
    LOG.warn("Error caught while writing content : " + ExceptionUtils.getStackTrace(e));
}

当在本地(在 DirectPipeline 中)运行时,这段代码工作正常并且没有错误。

然而,当在 Dataflow 中运行时(在 DataflowRunner 中),我们注意到一个奇怪的行为:

  • 文件是在请求的存储桶上创建的,具有请求的内容和文件名
  • 一个UserCodeException: java.io.FileNotFoundException: No files matched spec被抓到 processContext.output行。

在 google gcp“No files matched spec” 上搜索没有返回单个结果。查看 org.apache.beam.sdk.io.FileSystems.java 中的源代码(在第 173 行声明的错误)并没有多大帮助。

使用调试器执行后显示使用 DirectRunner,代码从不调用 FileIO.MatchAll , 错误的来源。但是,对于 DataflowRunner,错误会以某种方式触发。没有理由将输出字符串解释为文件路径,因为堆栈跟踪表明错误发生在这个阶段,它被声明为输出 PCollection<String>。 .

为什么是FileNotFoundException即使文件已明确创建并包含正确的内容,仍会启动?


一些可能有帮助的附加信息:

  • 文件名是通过一个UUID4生成的UUID.randomUUID() ,这意味着它包含“-”字符以及长文件名。然而,这应该不是问题,因为 1) 它在 DirectRunner 中工作 2) 文件是实际创建的
  • 接下来的阶段是TextIO.readAll()
  • 堆栈跟踪(为保护隐私而略微修改):https://pastebin.com/wumha4ZZ

补充调查:

  • 将输出更改为指向现有文件的固定字符串 processContext.output("gs://" + tempBucket + "/" + alreadyExistingFileName);不会触发错误。然后我怀疑这可能(以某种方式)是由于写入操作和存储桶确认文件的时间之间的延迟错误造成的。
  • 添加 Thread.sleep(15000)write 之间和 output不能解决问题。延迟似乎不是这里的问题。

最佳答案

查看堆栈跟踪的更多细节表明错误是通过 FileIO 发生的,它本身是通过此之后的 TextIO 阶段调用的。

发生的事情是,在我上面的代码中,我没有关闭编写器 writer.close() before 将字符串输出到 TextIO,但是之后(通过 try(Writer writer){} block )。由于存储桶在其编写器关闭之前不会注册文件,因此 TextIO 无法找到文件并启动 FileNotFoundException。这反过来会关闭 try block 并启动 writer.close(),这就是为什么文件最后仍然出现在存储桶中的原因。

出于某种我不知道的原因,通过本地 DirectLauncher 启动时不会发生这种情况。

关于java - "java.io.FileNotFoundException: No files matched spec"虽然文件已成功写入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51415426/

相关文章:

c# - 以编程方式获取或设置文件详细信息

java - 如何通过java nio writer追加文件?

python - 我可以将本地依赖项与 Dataflow for Python SDK 一起使用吗

google-app-engine - 从 Dataflow api 在 Datastore 中保存长度超过 1500 字节的字符串时出错

java - 使用 Java 访问深层 XML 结构

Java Swing MVC问题

java - Java中过滤目录中的文件

Java执行文件相对于jar

java - Cloudera Manage 5.7.0,cloudera-scm-agent无法启动,无法创建pidfile

java - android比较2个日期来找出差异