You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Kotlin+Gradle文件读取逻辑在Android Studio失效但IntelliJ IDEA可用?

问题描述

我使用Windows操作系统,在Android Studio中把${project_name}\app\src\main\res标记为resources root,两个类使用同一包名,代码如下:

import java.nio.charset.Charset
import java.nio.file.Files
import java.nio.file.Paths

class Parser(fileName:String){
     val fileName=fileName
     val fileContent=getContent()

fun getContent():String{
    val encoded= Files.readAllBytes(Paths.get(".",fileName))
    // 预期相对路径指向Android Studio里的res文件夹
    return String(encoded, Charset.defaultCharset())
    }
}
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val parser=Parser("default.vert")
    findViewById<TextView>(R.id.tv_test).also {
        it.text=parser.fileContent
        }
    }
}

运行时报错:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.test/com.example.test.MainActivity}: java.nio.file.NoSuchFileException: ./default.vert

但在IntelliJ IDEA社区版中,使用几乎相同的代码(仅路径不同,将某文件夹标记为默认resources root)可正常运行:

import java.nio.charset.Charset
import java.nio.file.Files
import java.nio.file.Paths

class Parser(fileName:String){
    val fileName=fileName
    val fileContent=getContent()
    fun getContent():String{
        val encoded= Files.readAllBytes(Paths.get(".","src","main","resources",fileName))
        // 此处使用项目最顶层目录(项目名为Test)
        return String(encoded, Charset.defaultCharset())
        }
    }

fun main(){
    val parser=Parser("test.vert")
    print(parser.fileContent)
}

正常输出文件内容:

layout (location=0) in vec4 vPosition;

void main(){
    gl_Position=vPosition;
}

如何让该代码在Android Studio中也能正常运行?(使用Kotlin实现)
我尝试过使用绝对路径如c:\users\${user_name}\..until_the_file\default.vert,但仍抛出fileNotFoundException异常。


解决方案

Android项目的资源访问逻辑和Java SE项目完全不同,不能直接用java.nio.file读取本地路径,需使用Android官方提供的资源读取API,以下是两种可行方案:

方案1:使用assets目录读取

  1. 在app/src/main下创建assets文件夹(无则新建),将default.vert放入该目录。
  2. 修改Parser类,通过AssetManager读取文件:
import android.content.Context
import java.nio.charset.Charset

class Parser(private val context: Context, fileName: String) {
    val fileName = fileName
    val fileContent = getContent()

    private fun getContent(): String {
        return context.assets.open(fileName).use { inputStream ->
            val bytes = inputStream.readBytes()
            String(bytes, Charset.defaultCharset())
        }
    }
}
  1. 在MainActivity中传入上下文初始化Parser:
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val parser = Parser(this, "default.vert")
        findViewById<TextView>(R.id.tv_test).also {
            it.text = parser.fileContent
        }
    }
}

方案2:使用res/raw目录读取

  1. 在app/src/main/res下创建raw文件夹(无则新建),将default.vert放入此处(注意文件名只能用小写字母、数字、下划线,不能有大写或特殊字符)。
  2. 修改Parser类,通过资源ID读取文件:
import android.content.Context
import java.nio.charset.Charset

class Parser(private val context: Context, private val resId: Int) {
    val fileContent = getContent()

    private fun getContent(): String {
        return context.resources.openRawResource(resId).use { inputStream ->
            val bytes = inputStream.readBytes()
            String(bytes, Charset.defaultCharset())
        }
    }
}
  1. 在MainActivity中使用资源ID初始化Parser:
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val parser = Parser(this, R.raw.default_vert)
        findViewById<TextView>(R.id.tv_test).also {
            it.text = parser.fileContent
        }
    }
}

原方法失效原因

  • Android项目打包成APK后,res目录下的文件会被编译或重命名,不存在本地开发时的相对路径。
  • APP运行时的工作目录是设备上的沙盒目录,不是电脑上的项目根目录,./default.vert这类路径无法定位到文件。
  • 绝对路径不可行是因为APP没有访问电脑本地文件系统的权限,且打包到设备后路径完全不同。

内容的提问来源于stack exchange,提问作者beginner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 07:27:39