Copy File from res


#1

hi,

i can now copy files from external storage to external storage,
i wonder how to copy one file in the app/main/res folder to external storage …

i’ve tried many thing like :

var inStream: InputStream? = null
var outStream: OutputStream? = null

    val bfile = File(Environment.getExternalStorageDirectory().toString() + "/Rivescript/Bots/Bfile.txt")
    val afile = File("/app/main/src/res/assets/scripts/truite.rive")

    inStream = FileInputStream(afile)
    outStream = FileOutputStream(bfile)

    val buffer = ByteArray(1024)


    var length = inStream.read(buffer)

    while (length    > 0 )

    {
        outStream.write(buffer, 0, length)
        length = inStream.read(buffer)
    }

    inStream.close()
    outStream.close()

java.io.FileNotFoundException: /app/main/src/res/assets/scripts/truite.rive: open failed: ENOENT (No such file or directory)

changed to

val afile= assets.open("/scripts/truite.rive")

instead of

val afile = File("/app/main/src/res/assets/scripts/truite.rive")

but i can’t use it with

inStream = FileInputStream(afile)

if you have an idea…


#2

While I do not know much about Android, I do know it is Linux-based and in Linux this:
/app/main/src/res/assets/scripts/truite.rive
is an absolute path starting from system’s root directory.

Have you tried a relative path:
app/main/src/res/assets/scripts/truite.rive
or an absolute path:
app_installation_dir/app/main/src/res/assets/scripts/truite.rive
?


#3

assets.open returns a stream already. No need to create a new one.


#4

ok i have corrected this
but where am i when using assets.open ? in the assets folder ?
i still have the FileNotFoundException with =>
val afile = assets.open( “/scripts/truite.rive” )

my file is in /res/assets/scripts/"


#5

I think your assets folder is suppose to be in “src/main/assets” and not “src/main/res/assets”


#6

that’s totally true !! …when you have created the assets folder with android good pratics !

i had created it manually … bad idea, so once created with alt+ins add assets folder , the path is ok

so here is the working code :

    val afile = assets.open( "truite.rive" )
    val bfile = File(Environment.getExternalStorageDirectory().toString() + "/Rivescript/Bots/Bfile.rive")

    
    var inStream: InputStream? = null
    var outStream: OutputStream? = null


    inStream = afile
    outStream = FileOutputStream(bfile)

    val buffer = ByteArray(1024)
    var length = inStream.read(buffer)


    while (length    > 0 )

    {
        outStream.write(buffer, 0, length)
        length = inStream.read(buffer)
    }

    inStream.close()
    outStream.close()

many thanks to both Eliote & forinil2


#7

:wink:


#8

Why don’t u use https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-input-stream/copy-to.html


#9

This might seem out of place, but have you set up any if statements to see if the file exists?


#10

The path is relative to the “assets” folder, so you have to leave off the initial slash. In other words, to access this file…

"/app/main/src/res/assets/scripts/truite.rive"

…you would use…

assets.open("scripts/truite.rive")

However, you should be aware that if you use the external storage directory on Android, you will have to request permission to access it from the user, otherwise on recent Android versions, your app will crash when it tries to access it.

A better way, if you need to put the file somewhere you can get an actual path to it, would be to use your app’s cache directory. That way Android OS can delete it if the phone is low on space, but your app can recreate it when necessary when it runs. For example…

val tmpPath = cacheDir.resolve("truite.rive")
if( !tmpPath.exists() ) {
    assets.open("scripts/truite.rive").use { inStream ->
        tmpPath.outputStream().use{ outStream -> 
            inStream.copyTo(outStream)
        }
    }
}

It should go without saying, of course, but if it’s a production app, make sure you don’t do this from the UI thread.