admin管理员组

文章数量:1397800

I'm working on a function to process some data and output the results as a csv file. I am using a 'use' block to wrap the function and ensure all the resources are closed. the problem I am running into is that I want the function to return the newly created File to the caller. The use block has the ability to return a value, however since it is being called with a bufferedWriter, there is no ability to actually return the File object from inside the block. Can anyone offer suggestions on how to solve this?

I want to do something like:

fun List<Contact>.buildCsv():File
{
    return File("people.csv").bufferedWriter(Charsets.ISO_8859_1).use { out ->

            out.write("a,b,c,d\n")
            this.forEach {
                out.write(it.toString())
            }
        }

}

but that code does not compile.

I'm working on a function to process some data and output the results as a csv file. I am using a 'use' block to wrap the function and ensure all the resources are closed. the problem I am running into is that I want the function to return the newly created File to the caller. The use block has the ability to return a value, however since it is being called with a bufferedWriter, there is no ability to actually return the File object from inside the block. Can anyone offer suggestions on how to solve this?

I want to do something like:

fun List<Contact>.buildCsv():File
{
    return File("people.csv").bufferedWriter(Charsets.ISO_8859_1).use { out ->

            out.write("a,b,c,d\n")
            this.forEach {
                out.write(it.toString())
            }
        }

}

but that code does not compile.

Share Improve this question edited Mar 28 at 6:08 David Soroko 9,1713 gold badges44 silver badges58 bronze badges asked Mar 26 at 20:33 pbuchheitpbuchheit 1,7012 gold badges28 silver badges63 bronze badges 3
  • 2 You can't return a File in Java. It's not what you think. The functionality of that class is really to manipulate paths and the like. It really has little to do with the actual content of a file system. If you really want to return a 'file' you would do well to think of it as returning a stream to the actual content (and all that entails) – g00se Commented Mar 26 at 20:44
  • I am not very familiar with Kotlin, but I would use a library over just trying to create CSV content the way you are doing it. If things get complicated, your output will pay the price. – SedJ601 Commented Mar 26 at 21:12
  • I'd recommend you don't tie yourself to Files and hence the file system. It gets messy when unit testing. (You do write unit tests, right?) Instead of a File, pass an OutputStream or a StreamWriter. In a test you can pass one that collects what gets written in a byte array or string. In real life, you can still pass a stream that writes to a file. But this decouples I/O from the logic in your buildCsv function. – Robert Commented Mar 26 at 22:44
Add a comment  | 

2 Answers 2

Reset to default 3

You can use some builtin scope functions such as apply, also, etc.

An example:

fun List<Contact>.buildCsv() = File("people.csv").apply {
    bufferedWriter(Charsets.ISO_8859_1).use { out ->
        out.write("a,b,c,d\n")
        forEach { out.write("$it") }
    }
}

How about:

fun List<Contact>.buildCsv(): File {
    val file = File("people.csv")

    file.bufferedWriter(Charsets.ISO_8859_1).use { out ->
        out.write("a,b,c,d\n")
        this.forEach {
            out.write(it.toString())
        }
    }

    return file
}

本文标签: javaWriting and returning a File in Kotlin using a bufferStack Overflow