I am new to Kotlin/Android development. I am trying to simply write text to a text file. I simply cannot figure out how to do this. I have tried doing:
File("filename.txt").printWriter().use { out ->
out.println("${it.key}, ${it.value}")
}
And I got the following. (Side note, "filename.txt" is located in the assets folder in my project)
Caused by: java.io.FileNotFoundException: prices.txt (Read-only file system)
So I figured out that I need to be writing to a spot where I have permission. To my knowledge this is internal private storage. I figured out which directory I have permissions to write to by using:
filesDir
That gave me:
/data/user/com.example.myname.appname/files
So from what I have seen so far I just need to create a file in this directory, write to said file, and read from it when I would like. The problem is I don't know how to do that. But I tried doing this:
// create file?
val file = File(applicationContext.filesDir, "test.txt")
//try to write to said file?
applicationContext.openFileOutput(file.toString(), Context.MODE_PRIVATE).use
{
it.write("test".toByteArray())
}
But then I get this error:
Caused by: java.lang.IllegalArgumentException: File
/data/user/0/com.example.pawlaczykm.dollarsense/files/test.txt contains
a path separator
I am at the point of maximum misunderstanding and confusion. Again, my goal is to write something to a text file, then access the file later throughout the application.
Update
Tried the following and didn't see back "comment":
File(applicationContext.filesDir, "test.txt").printWriter().use{ out ->
out.println("content")
}
File(applicationContext.filesDir, "test.txt").bufferedReader().use{ out ->
var text5 = out.toString()
Toast.makeText(this, text5.toString(), Toast.LENGTH_LONG).show()
}
openFileOutput() takes a filename, not a path. openFileOutput() returns an OutputStream on a file that is located in the directory identified by getFilesDir() (a.k.a., filesDir in Kotlin).
Try:
File(applicationContext.filesDir, "test.txt").printWriter().use { out ->
out.println("${it.key}, ${it.value}")
}
or:
applicationContext.openFileOutput("test.txt", Context.MODE_PRIVATE).use
{
it.write("test".toByteArray())
}
Related
I have a markdown file in my assets folder. I am using a markdown viewer which takes java.io.File Object as an argument to parse the file on screen.
But i don't know how to get a File Object from a file in assets folder.
Is there a way i can achieve this. I tried URI way but it failed.
This is my code snippet which may help
val markDown = File("file:///asset/GalacticAstronomy.md")
if (markDown.exists()) {
Toast.makeText(baseContext, "File exist", Toast.LENGTH_SHORT).show()
} else Toast
.makeText(baseContext, "File doesn't exist", Toast.LENGTH_SHORT).show()
setContent {
MaterialTheme {
MarkDown(
file = markDown,
modifier = Modifier.fillMaxSize()
)
}
}
I am not trying to read the file, So using assets.open("file") isn't going to work
But i don't know how to get a File Object from a file in assets folder
That is not possible, as it is not a file.
I am not trying to read the file, So using assets.open("file") isn't going to work
You do not have a choice. Either:
Use a better markdown library, one that accepts an InputStream, or
Copy the asset to a file yourself (e.g., in getCacheDir()) using assets.open()), then use the resulting file with your existing library
I have placed a file in my Tablet\Tablet\Android\data\my.app.package\files\data called test.txt with a few lines of text. This is reported by Windows.
Kotlin is throwing an Exception (FileNotFound) and I have also tried specifying what I believe is the real path of the file, but cannot seem to get it using the following path:
"/0/Android/data/my.app.package/files/data/test.txt" (my app's data directory). This directory definitely exists as I can see it in device file managr.
This file contains 2 lines of text, which I am trying to read in to run specific tasks based on their values. I've tried with a BufferedReader, but I'm getting FileNotFound Exception...
This is my code:
fun readFile() {
val yourFilePath = "/0/Android/data/my.app.package/files/data/test.txt"
val yourFile = File(yourFilePath)
print(yourFile.name)
val file = File(yourFilePath)
file.bufferedReader().forEachLine {
println("value = $it")
}
}
Any help is highly appreciated. Thankyou!
filesDir for pointing to the internal storage files directory
use blocks are good when you want to close stream automatically.
try-catch block to handle any IO exceptions, e.g. FileNotFoundException.
try {
val file = File(filesDir, "test.txt")
if (file.exists()) {
file.bufferedReader().useLines {
...
}
}
} catch (e: IOException) {
...
}
Great article for a more in-depth look: Medium
Make sure your file exists by looking at your internal storage by:
AndroidStudio -> View -> Tools Windows -> Android Device Explorer
context.openFileInput(fileName).use { stream ->
stream.bufferedReader().use { it.readText() }
}
I have a file in the downloads directory. Let's call it OldFile, of the File class.
I seem to be move it anywhere I like using OldFile.renameTo(File(some new file path)) UNLESS the new file path is inside the application's private file directory as obtained from context.filesDir.
This Kotlin snippet works, for instance:
val newFileLocation = File(Environment.getExternalStorageDirectory().absolutePath + "/test.txt")
oldFile.renameTo(newFileLocation)
but this snippet fails silently, throwing no exception, leaving oldFile completely unchanged:
val newFileLocation = File(context?.filesDir?.absolutePath + "/test.txt")
oldFile.renameTo(newFileLocation)
Is there some rule against using File.renameTo to move a file into the filesDir path?
How am I supposed to go about it?
thanks
John
The renameTo() works only for files on the same 'partition'.
Apparently getFilesDir() is on a different partition.
I have a list of arrays of data in my app that I would now like to write to a file (csv) and use a 3rd party app (such as email) to share this csv file. I have had no luck finding any helpful resources for creating, finding the file path for, and appending to a file in Kotlin. Does anyone have experience with this or have examples to point to? Just to get started I'm trying to write the header and close the file so I can see that it is correctly writing.
This is what I have for now:
val HEADER = "ID, time, PSI1, PSI2, PSI3, speed1, speed2, temp1, temp2"
val filename = "export.csv"
var fileOutStream : FileOutputStream = openFileOutput(filename,Context.MODE_PRIVATE)
try {
fileOutStream.write(HEADER.toByteArray())
fileOutStream.close()
}catch(e: Exception){
Log.i("TAG", e.toString())
}
It doesn't throw the exception, but I cannot find the file in the file system. I'm using a physical tablet for testing/debug. I've checked the com.... folder for my app.
I cannot find the file in the file system
Use Android Studio's Device File Explorer and look in /data/data/.../files/, where ... is your application ID.
Also, you can write your code a bit more concisely as:
try {
PrintWriter(openFileOutput(filename,Context.MODE_PRIVATE)).use {
it.println(HEADER)
}
} catch(e: Exception) {
Log.e("TAG", e.toString())
}
use() will automatically close the PrintWriter, and PrintWriter gives you a more natural API for writing out text.
It appears there are many ways to create a file and append to it, depending on the minimum API version you are developing for. I am using minimum Android API 22. The code to create/append a file is below:
val HEADER = "DATE,NAME,AMOUNT_DUE,AMOUNT_PAID"
var filename = "export.csv"
var path = getExternalFilesDir(null) //get file directory for this package
//(Android/data/.../files | ... is your app package)
//create fileOut object
var fileOut = File(path, filename)
//delete any file object with path and filename that already exists
fileOut.delete()
//create a new file
fileOut.createNewFile()
//append the header and a newline
fileOut.appendText(HEADER)
fileOut.appendText("\n")
/*
write other data to file
*/
openFileOutput() creates a private file, likely inside of app storage. These files are not browsable by default. If you want to create a file that can be browsed to, you'll need the WRITE_EXTERNAL_STORAGE permission, and will want to create files into a directory such as is provided by getExternalFilesDir()
For an Android App, I'm trying to use the FilerReader function to read my csv file, but after trying everything I cannot get to find my file. I'm using Android studios on a Mac.
Below is my code inside OnCreate():
val filereader = BufferedReader(FileReader("sgsraagadata.csv"))
I have tried placing the csv file inside assets & all resource folders including a raw-type folder.
Similar posts on Stackoverflow suggests that I find the directory that is being searched so that I can put the csv file in that directory. But when I follow their instructions below is what I get.
When I use:
println(System.getProperty("user.dir"))
It prints "/". And when I use:
println(File(".").getAbsoluteFile())
It prints "/."
Given these printed outputs, where should I put the csv file?
*Also added an image showing csv file in assets folder as per suggestion in comments. Result is still an file not found error.
Put your file in assets folder and open it like this:
val file = context.assets.open("sgsraagadata.csv")
val isr = InputStreamReader(file)
val reader = BufferedReader(isr)
var line = reader.readLine()
while (line != null) {
// do something with the line
line = reader.readLine()
}
supply a valid Context or inside an activity you can omit it.