Apache Beam TextIO.read().from()不识别文件模式转义特殊字符如何解决
环境
- Java SDK 2.33.0
前置操作
$ mkdir -p /tmp/beam $ echo "test" >> "/tmp/beam/test*.txt"
测试流水线
public class PipelineTest { @Test public void test() { Pipeline p = TestPipeline.create().enableAbandonedNodeEnforcement(false); String filename = "/tmp/beam/test\\*.txt"; PCollection<String> input = p.apply(TextIO.read().from(filename)); PAssert.that(input).containsInAnyOrder("test"); p.run(); } }
测试运行失败,报错信息如下:
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 10.66 s <<< FAILURE! - in PipelineTest [ERROR] test Time elapsed: 10.645 s <<< ERROR! org.apache.beam.sdk.Pipeline$PipelineExecutionException: java.io.FileNotFoundException: No files matched spec: /tmp/beam/test\*.txt at PipelineTest.test(PipelineTest.java:28) Caused by: java.io.FileNotFoundException: No files matched spec: /tmp/beam/test\*.txt
问题
如何正确读取文件名中包含星号或其他特殊字符的文件?
解决方案
错误原因
Apache Beam的TextIO.read()默认开启通配符匹配逻辑,会将路径中的*、?、[]等字符识别为通配符做模糊匹配,不会将其当作文件名的普通字符处理。你代码中额外添加的反斜杠转义,只会让实际查找的路径多了一个反斜杠字符,和实际文件名test*.txt不匹配,因此抛出文件找不到的错误。
正确修改方式
调用withAllowWildcards(false)方法关闭通配符匹配功能,直接传入原始文件名即可,不需要额外对特殊字符做转义。
修改后的代码如下:
public class PipelineTest { @Test public void test() { Pipeline p = TestPipeline.create().enableAbandonedNodeEnforcement(false); // 直接写原始文件名,无需转义星号 String filename = "/tmp/beam/test*.txt"; // 关闭通配符匹配,将路径作为字面量精确匹配 PCollection<String> input = p.apply(TextIO.read().from(filename).withAllowWildcards(false)); PAssert.that(input).containsInAnyOrder("test"); p.run(); } }
如果需要处理同时包含特殊字符和通配符的场景,可以将路径中需要当作普通字符处理的特殊字符用\转义,注意Java字符串中需要写两个反斜杠表示一个转义符,同时保持通配符匹配功能开启即可。
内容的提问来源于stack exchange,提问作者Hideyuki Okada
相关产品推荐
相关产品推荐

