简体   繁体   English

如何使用注释处理器从 src/main/resources 读取文件?

[英]How to read file from src/main/resources with annotation processor?

I have a simple annotation processor that needs to read a configuration file from the same project as the annotated classes.我有一个简单的注释处理器,它需要从与注释类相同的项目中读取配置文件。 Example structure:示例结构:

- myproject 
  - src
    - main
      - java
        - my.package.SourceFile
      - resources
        - config.json

In the annotation processor, I try to read the file:在注释处理器中,我尝试读取文件:

FileObject resource = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", "config.json");

but it throws FileNotFoundException .但它抛出FileNotFoundException I also tried other paths, such as ../resources/config.json , (which throws Invalid relative name: ../resources/config.json ).我还尝试了其他路径,例如../resources/config.json ,(这会抛出Invalid relative name: ../resources/config.json )。 And I tried putting the config file in src/main/java (and even src/main/java/my/package ) instead, which I don't like, but that also still throws FileNotFoundException .我尝试将配置文件放在src/main/java (甚至是src/main/java/my/package )中,我不喜欢,但这仍然会抛出FileNotFoundException

It would already help if I could get filer.getResource() to tell me where it's looking.如果我能让filer.getResource()告诉我它在哪里,那已经filer.getResource() To find that out, I tried generating a file:为了找出答案,我尝试生成一个文件:

filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "dummy");

which generated in myproject/build/classes/main/dummy .myproject/build/classes/main/dummy Unfortunately, I can't generate in SOURCE_PATH , so that doesn't help with finding this out.不幸的是,我无法在SOURCE_PATH生成,因此这无助于发现这一点。

I'd expect that the stuff from src/main/resources gets copied to target/classes during the build (prior to annotation processing).我希望来自src/main/resources在构建期间(在注释处理之前)被复制到target/classes In that case you can open them like this:在这种情况下,您可以像这样打开它们:

ProcessingEnvironment pe = ...;
FileObject fileObject = pe.getFiler()
    .getResource( StandardLocation.CLASS_OUTPUT, "", "config.json" );
InputStream jsonStream = fileObject.openInputStream();

I've looked at this with one of the Project Lombok developers.我已经与 Project Lombok 的一位开发人员一起研究过这个问题。 If anyone knows annotation processing, it's them ;)如果有人知道注释处理,那就是他们;)

Our conclusion was, that the JavacFileManager that handles the request internally, does not have a path to resolve StandardLocation.SOURCE_PATH to.我们的结论是,在内部处理请求的JavacFileManager没有将StandardLocation.SOURCE_PATH解析为的路径。 We're not sure, but it might be related to building with Gradle.我们不确定,但这可能与使用 Gradle 构建有关。

I had the same problem and was searching for solution for a while and found this cool hack that does the trick for Android我遇到了同样的问题,正在寻找解决方案一段时间,发现这个很酷的 hack对 Android 有用

And below you can see my solution from pure Java/Kotlin project在下面你可以从纯 Java/Kotlin 项目中看到我的解决方案

fun ProcessingEnvironment.getResourcesDirectory(): File {
val dummySourceFile = filer.createSourceFile("dummy" + System.currentTimeMillis())
var dummySourceFilePath = dummySourceFile.toUri().toString()

if (dummySourceFilePath.startsWith("file:")) {
    if (!dummySourceFilePath.startsWith("file://")) {
        dummySourceFilePath = "file://" + dummySourceFilePath.substring("file:".length)
    }
} else {
    dummySourceFilePath = "file://$dummySourceFilePath"
}

val cleanURI = URI(dummySourceFilePath)

val dummyFile = File(cleanURI)

val projectRoot = dummyFile.parentFile.parentFile.parentFile.parentFile.parentFile

return File(projectRoot.absolutePath + "/resources")
}

Following function works for me with annotation processor being triggered by gradle, it's not the pretties one but works:以下功能适用于我,由 gradle 触发注释处理器,它不是漂亮的,但有效:

private fun resolveApplicationPropertiesFile(): File {
    val projectRoot = Path.of(processingEnv.filer.getResource(StandardLocation.CLASS_OUTPUT, "", "doesntmatter")
            .toUri())
            .parent
            .parent
            .parent
            .parent
            .parent
            .parent
    val properties = Path.of(projectRoot.toString(), "src", "main", "resources", "application.yml")
    return properties.toFile()
}

where processingEnv is a member of AbstractProcessor其中processingEnvAbstractProcessor的成员

  • If your element is instance of TypeElement ,then you can use these code to find your source code如果您的元素是TypeElement实例,那么您可以使用这些代码来查找源代码

    FileObject fileObject = processingEnv.getFiler().getResource( StandardLocation.SOURCE_PATH, element.getEnclosingElement().toString(), element.getSimpleName() + ".java");

    1. element.getEnclosingElement() is your class package, eg: com.fool element.getEnclosingElement()是你的类包,例如:com.fool
    2. element.getSimpleName() is your class name, eg: Person element.getSimpleName()是你的类名,例如:Person
  • then you can print them: CharSequence content = fileObject.getCharContent(true);然后你可以打印它们: CharSequence content = fileObject.getCharContent(true);

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

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