diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt
index c5d691eb8f1437726bcce22500ad995bc1b6e4da..96f32f634f1d0164b1e25b36fe44de2162c86bfe 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt
@@ -2,6 +2,7 @@ package theodolite.evaluation
 
 import mu.KotlinLogging
 import theodolite.benchmark.BenchmarkExecution
+import theodolite.util.IOHandler
 import theodolite.util.LoadDimension
 import theodolite.util.Resource
 import java.text.Normalizer
@@ -44,15 +45,14 @@ class AnalysisExecutor(
                 query = "sum by(group)(kafka_consumergroup_group_lag >= 0)"
             )
 
-            var resultsFolder: String = System.getenv("RESULTS_FOLDER")
-            if (resultsFolder.isNotEmpty()){
-                resultsFolder += "/"
-            }
+            val ioHandler = IOHandler()
+            val resultsFolder: String = ioHandler.getResultFolderURL()
+            val fileURL = "${resultsFolder}exp${executionId}_${load.get()}_${res.get()}_${slo.sloType.toSlug()}"
+            ioHandler.writeToCSVFile(
+                fileURL = fileURL,
+                data = prometheusData.getResultAsList(),
+                columns = listOf("group", "timestamp", "value"))
 
-            CsvExporter().toCsv(
-                name = "${resultsFolder}exp${executionId}_${load.get()}_${res.get()}_${slo.sloType.toSlug()}",
-                prom = prometheusData
-            )
             val sloChecker = SloCheckerFactory().create(
                 sloType = slo.sloType,
                 externalSlopeURL = slo.externalSloUrl,
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/CsvExporter.kt b/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/CsvExporter.kt
deleted file mode 100644
index 970d1487014bfbddf7391e381d27ad5dbb246a7d..0000000000000000000000000000000000000000
--- a/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/CsvExporter.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-package theodolite.evaluation
-
-import mu.KotlinLogging
-import theodolite.util.PrometheusResponse
-import java.io.File
-import java.io.PrintWriter
-import java.util.*
-
-private val logger = KotlinLogging.logger {}
-
-/**
- *  Used to document the data received from prometheus for additional offline analysis.
- */
-class CsvExporter {
-
-    /**
-     * Uses the [PrintWriter] to transform a [PrometheusResponse] to a CSV file.
-     * @param name of the file.
-     * @param prom Response that is documented.
-     *
-     */
-    fun toCsv(name: String, prom: PrometheusResponse) {
-        val responseArray = promResponseToList(prom)
-        val csvOutputFile = File("$name.csv")
-
-        PrintWriter(csvOutputFile).use { pw ->
-            pw.println(listOf("group", "timestamp", "value").joinToString(separator=","))
-            responseArray.forEach {
-                pw.println(it.joinToString(separator=","))
-            }
-        }
-        logger.info { "Wrote CSV file: $name to ${csvOutputFile.absolutePath}." }
-    }
-
-    /**
-     * Converts a [PrometheusResponse] into a [List] of [List]s of [String]s
-     */
-    private fun promResponseToList(prom: PrometheusResponse): List<List<String>> {
-        val name = prom.data?.result?.get(0)?.metric?.group.toString()
-        val values = prom.data?.result?.get(0)?.values
-        val dataList = mutableListOf<List<String>>()
-
-        if (values != null) {
-            for (maybeValuePair in values) {
-                val valuePair = maybeValuePair as List<*>
-                val timestamp = (valuePair[0] as Double).toLong().toString()
-                val value = valuePair[1].toString()
-                dataList.add(listOf(name, timestamp, value))
-            }
-        }
-        return Collections.unmodifiableList(dataList)
-    }
-}
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
index c297251e30c17e5824c2541365164d9824718073..c437dd3b1b1adefc3657b7c43c671512f5713858 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
@@ -7,10 +7,7 @@ import theodolite.benchmark.KubernetesBenchmark
 import theodolite.patcher.PatcherDefinitionFactory
 import theodolite.strategies.StrategyFactory
 import theodolite.strategies.searchstrategy.CompositeStrategy
-import theodolite.util.Config
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-import theodolite.util.Results
+import theodolite.util.*
 import java.io.File
 import java.io.PrintWriter
 import java.lang.IllegalArgumentException
@@ -102,34 +99,17 @@ class TheodoliteExecutor(
         return this.kubernetesBenchmark
     }
 
-    private fun getResultFolderString(): String {
-        var resultsFolder: String = System.getenv("RESULTS_FOLDER") ?: ""
-        val createResultsFolder = System.getenv("CREATE_RESULTS_FOLDER") ?: "false"
-
-        if (resultsFolder != ""){
-            logger.info { "RESULT_FOLDER: $resultsFolder" }
-            val directory = File(resultsFolder)
-            if (!directory.exists()) {
-                logger.error { "Folder $resultsFolder does not exist" }
-                if (createResultsFolder.toBoolean()) {
-                    directory.mkdirs()
-                } else {
-                    throw IllegalArgumentException("Result folder not found")
-                }
-            }
-            resultsFolder += "/"
-        }
-        return  resultsFolder
-    }
 
     /**
      * Run all experiments which are specified in the corresponding
      * execution and benchmark objects.
      */
     fun run() {
-        val resultsFolder = getResultFolderString()
-        storeAsFile(this.config, "$resultsFolder${this.config.executionId}-execution-configuration")
-        storeAsFile(kubernetesBenchmark, "$resultsFolder${this.config.executionId}-benchmark-configuration")
+        val ioHandler = IOHandler()
+        val resultsFolder = ioHandler.getResultFolderURL()
+        this.config.executionId = getAndIncrementExecutionID(resultsFolder+"expID.txt")
+        ioHandler.writeToJSONFile(this.config, "$resultsFolder${this.config.executionId}-execution-configuration")
+        ioHandler.writeToJSONFile(kubernetesBenchmark, "$resultsFolder${this.config.executionId}-benchmark-configuration")
 
         val config = buildConfig()
         // execute benchmarks for each load
@@ -138,14 +118,17 @@ class TheodoliteExecutor(
                 config.compositeStrategy.findSuitableResource(load, config.resources)
             }
         }
-        storeAsFile(config.compositeStrategy.benchmarkExecutor.results, "$resultsFolder${this.config.executionId}-result")
+        ioHandler.writeToJSONFile(config.compositeStrategy.benchmarkExecutor.results, "$resultsFolder${this.config.executionId}-result")
     }
 
-    private fun <T> storeAsFile(saveObject: T, filename: String) {
-        val gson = GsonBuilder().enableComplexMapKeySerialization().setPrettyPrinting().create()
-
-        PrintWriter(filename).use { pw ->
-            pw.println(gson.toJson(saveObject))
-        }
+   private fun getAndIncrementExecutionID(fileURL: String): Int {
+       val ioHandler = IOHandler()
+       var executionID = 0
+       if (File(fileURL).exists()) {
+           executionID = ioHandler.readFileAsString(fileURL).toInt() + 1
+       }
+       ioHandler.writeStringToTextFile(fileURL, (executionID).toString())
+       return executionID
     }
+
 }
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
index 0e889e0393e17fd65f4d8f12c5b95a3dbed7f593..5c8a225a7afa4dd8094ee283af50cbd4efea9f50 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
@@ -37,7 +37,6 @@ class TheodoliteController(
     val executionsQueue: ConcurrentLinkedDeque<BenchmarkExecution> = ConcurrentLinkedDeque()
     val benchmarks: ConcurrentHashMap<String, KubernetesBenchmark> = ConcurrentHashMap()
     var isUpdated = AtomicBoolean(false)
-    var executionID = AtomicInteger(0)
 
     /**
      * Runs the TheodoliteController forever.
@@ -91,7 +90,6 @@ class TheodoliteController(
      */
     @Synchronized
     fun runExecution(execution: BenchmarkExecution, benchmark: KubernetesBenchmark) {
-        execution.executionId = executionID.getAndSet(executionID.get() + 1)
         isUpdated.set(false)
         benchmark.path = path
         logger.info { "Start execution ${execution.name} with benchmark ${benchmark.name}." }
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/util/IOHandler.kt b/theodolite-quarkus/src/main/kotlin/theodolite/util/IOHandler.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e2679f048b98171089016fab13be7805ec7e6693
--- /dev/null
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/util/IOHandler.kt
@@ -0,0 +1,95 @@
+package theodolite.util
+
+import com.google.gson.GsonBuilder
+import mu.KotlinLogging
+import java.io.File
+import java.io.PrintWriter
+import java.lang.IllegalArgumentException
+
+private val logger = KotlinLogging.logger {}
+
+/**
+ * The IOHandler handles most common I/O operations within the Theodolite framework
+ */
+class IOHandler {
+
+    /**
+     * The location in which Theodolite store result and configuration file are depends on
+     * the values of the environment variables `RESULT_FOLDER` and `CREATE_RESULTS_FOLDER`
+     *
+     * @return the URL of the result folder
+     */
+    fun getResultFolderURL(): String {
+        var resultsFolder: String = System.getenv("RESULTS_FOLDER") ?: ""
+        val createResultsFolder = System.getenv("CREATE_RESULTS_FOLDER") ?: "false"
+
+        if (resultsFolder != ""){
+            logger.info { "RESULT_FOLDER: $resultsFolder" }
+            val directory = File(resultsFolder)
+            if (!directory.exists()) {
+                logger.error { "Folder $resultsFolder does not exist" }
+                if (createResultsFolder.toBoolean()) {
+                    directory.mkdirs()
+                } else {
+                    throw IllegalArgumentException("Result folder not found")
+                }
+            }
+            resultsFolder += "/"
+        }
+        return  resultsFolder
+    }
+
+    /**
+     * Read a file as String
+     *
+     * @param fileURL the URL of the file
+     * @return The content of the file as String
+     */
+    fun readFileAsString(fileURL: String): String {
+        return File(fileURL).inputStream().readBytes().toString(Charsets.UTF_8).trim()
+    }
+
+    /**
+     * Creates a JSON string of the given object and store them to file
+     *
+     * @param T class of the object to save
+     * @param objectToSave object which should be saved as file
+     * @param fileURL the URL of the file
+     */
+    fun <T> writeToJSONFile(objectToSave: T, fileURL: String) {
+        val gson = GsonBuilder().enableComplexMapKeySerialization().setPrettyPrinting().create()
+        writeStringToTextFile(fileURL, gson.toJson(objectToSave))
+    }
+
+    /**
+     * Write to CSV file
+     *
+     * @param fileURL the URL of the file
+     * @param data  the data to write in the file, as list of list, each subList corresponds to a row in the CSV file
+     * @param columns columns of the CSV file
+     */
+    fun writeToCSVFile(fileURL: String, data: List<List<String>>, columns: List<String>) {
+        val outputFile = File("$fileURL.csv")
+        PrintWriter(outputFile).use { pw ->
+            pw.println(columns.joinToString(separator=","))
+            data.forEach {
+                pw.println(it.joinToString(separator=","))
+            }
+        }
+        logger.info { "Wrote CSV file: $fileURL to ${outputFile.absolutePath}." }
+    }
+
+    /**
+     * Write to text file
+     *
+     * @param fileURL the URL of the file
+     * @param data the data to write in the file as String
+     */
+    fun writeStringToTextFile(fileURL: String, data: String) {
+        val outputFile = File("$fileURL")
+        outputFile.printWriter().use {
+                it.println(data)
+        }
+        logger.info { "Wrote txt file: $fileURL to ${outputFile.absolutePath}." }
+    }
+}
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/util/PrometheusResponse.kt b/theodolite-quarkus/src/main/kotlin/theodolite/util/PrometheusResponse.kt
index d1d59c482e64fd14c4744d8fcd606f286da24fb4..846577387c425e920da1c2fca1f972c880e1540a 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/util/PrometheusResponse.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/util/PrometheusResponse.kt
@@ -1,6 +1,7 @@
 package theodolite.util
 
 import io.quarkus.runtime.annotations.RegisterForReflection
+import java.util.*
 
 /**
  * This class corresponds to the JSON response format of a Prometheus
@@ -17,6 +18,27 @@ data class PrometheusResponse(
      */
     var data: PromData? = null
 )
+{
+    /**
+     * Return the data of the PrometheusResponse as [List] of [List]s of [String]s
+     * The format of the returned list is: `[[ group, timestamp, value ], [ group, timestamp, value ], ... ]`
+     */
+    fun getResultAsList(): List<List<String>> {
+        val group = data?.result?.get(0)?.metric?.group.toString()
+        val values = data?.result?.get(0)?.values
+        val result = mutableListOf<List<String>>()
+
+        if (values != null) {
+            for (value in values) {
+                val valueList = value as List<*>
+                val timestamp = (valueList[0] as Double).toLong().toString()
+                val value = valueList[1].toString()
+                result.add(listOf(group, timestamp, value))
+            }
+        }
+        return Collections.unmodifiableList(result)
+    }
+}
 
 /**
  * Description of Prometheus data.
@@ -56,4 +78,5 @@ data class PromResult(
 @RegisterForReflection
 data class PromMetric(
     var group: String? = null
-)
\ No newline at end of file
+)
+