我正在使用一个Android应用程序,其中的一项功能是让用户选择要打开的文件(我想打开一个纯文本.txt文件)。在使用Java之前,我曾经从事过Android应用程序的工作,但是对于这个应用程序,我正在使用Kotlin,这是我第一次使用Kotlin。
我目前让该应用显示一个文件选择器,并让用户点击他们想要打开的文件。然后,我尝试使用File对象打开文件并执行forEachLine循环。但是由于某种原因,它会抛出一个java.io.FileNotFoundException(无此类文件或目录),其中包含从文件选择器中选择的文件。我不确定发生了什么问题,是否必须进行一些转换以转换文件路径?
我的“加载”按钮的代码:
val btn_load: Button = findViewById<Button>(R.id.btn_load_puzzle)
btn_load.setOnClickListener {
val intent = Intent()
.setType("*/*")
.setAction(Intent.ACTION_GET_CONTENT)
startActivityForResult(Intent.createChooser(intent, "Select a file"), 111)
}
我的响应文件选择的功能:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// Selected a file to load
if ((requestCode == 111) && (resultCode == RESULT_OK)) {
val selectedFilename = data?.data //The uri with the location of the file
if (selectedFilename != null) {
val filenameURIStr = selectedFilename.toString()
if (filenameURIStr.endsWith(".txt", true)) {
val msg = "Chosen file: " + filenameURIStr
val toast = Toast.makeText(applicationContext, msg, Toast.LENGTH_SHORT)
toast.show()
File(selectedFilename.getPath()).forEachLine {
val toast = Toast.makeText(applicationContext, it, Toast.LENGTH_SHORT)
toast.show()
}
}
else {
val msg = "The chosen file is not a .txt file!"
val toast = Toast.makeText(applicationContext, msg, Toast.LENGTH_LONG)
toast.show()
}
}
else {
val msg = "Null filename data received!"
val toast = Toast.makeText(applicationContext, msg, Toast.LENGTH_LONG)
toast.show()
}
}
}
FileNotFound异常在创建File对象以执行forEachLine循环的行上引发:
java.lang.RuntimeException:无法交付结果ResultInfo {who = null,request = 111,result = -1,data = Intent {dat = content://com.android.externalstorage.documents/document/0000-0000: Sudoku puzzles / hard001.txt flg = 0x1}}到活动{com.example.sudokusolver / com.example.sudokusolver.MainActivity}:java.io.FileNotFoundException:/ document / 0000-0000:Sudoku puzzles / hard001.txt(否这样的文件或目录)
您未收到文件路径,但收到了Uri
。您必须使用基于Uri
的API,例如ContentResolver.openInputStream()
来访问该ContentResolver.openInputStream()
处的内容,因为Android并未授予您的应用直接Uri
对基础文件的访问权限(也可以从Google云端硬盘中流式传输或下载)直接从互联网上获取,而您的应用程序不知道这种情况正在发生):
File
在这里,我们可以假定我们通过将正确的mime类型传递给我们的请求来获得正确格式的内容(因为不要求文本文件以override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// Selected a file to load
if ((requestCode == 111) && (resultCode == RESULT_OK)) {
val selectedFilename = data?.data //The uri with the location of the file
if (selectedFilename != null) {
contentResolver.openInputStream(selectedFilename)?.bufferedReader()?.forEachLine {
val toast = Toast.makeText(applicationContext, it, Toast.LENGTH_SHORT)
toast.show()
}
} else {
val msg = "Null filename data received!"
val toast = Toast.makeText(applicationContext, msg, Toast.LENGTH_LONG)
toast.show()
}
}
}
扩展名作为其路径的一部分结尾):
.txt
这将自动使任何非文本文件无法被选择。