0
# File I/O Utilities
1
2
The IOUtils object provides utilities for working with coverage data files, measurement files, and report output. It handles file operations, measurement data loading, and directory management for the scoverage ecosystem.
3
4
## Core API
5
6
### IOUtils Object
7
8
```scala { .api }
9
object IOUtils {
10
// File operations
11
def writeToFile(file: File, str: String, encoding: Option[String]): Unit
12
def readStreamAsString(in: InputStream): String
13
14
// Measurement file handling
15
def findMeasurementFiles(dataDir: File): Array[File]
16
def findMeasurementFiles(dataDir: String): Array[File]
17
def measurementFile(dataDir: File): File
18
def measurementFile(dataDir: String): File
19
def invoked(files: Seq[File], encoding: String = "UTF-8"): Set[(Int, String)]
20
21
// Report file utilities
22
def reportFile(outputDir: File, debug: Boolean = false): File
23
24
// Directory operations
25
def clean(dataDir: File): Unit
26
def clean(dataDir: String): Unit
27
def scoverageDataDirsSearch(baseDir: File): Seq[File]
28
29
// Path utilities
30
def getName(path: String): String
31
32
// System utilities
33
def getTempDirectory: File
34
def getTempPath: String
35
}
36
```
37
38
## File Operations
39
40
### Writing Files with Encoding
41
42
```scala { .api }
43
def writeToFile(file: File, str: String, encoding: Option[String]): Unit
44
```
45
46
Writes string content to a file with specified encoding support.
47
48
**Usage Examples:**
49
50
```scala
51
import java.io.File
52
import scoverage.reporter.IOUtils
53
54
// Write with UTF-8 encoding
55
val reportFile = new File("target/report.html")
56
val htmlContent = "<html><body>Coverage Report</body></html>"
57
IOUtils.writeToFile(reportFile, htmlContent, Some("UTF-8"))
58
59
// Write with default encoding
60
IOUtils.writeToFile(reportFile, htmlContent, None)
61
62
// Write with specific encoding
63
IOUtils.writeToFile(reportFile, htmlContent, Some("ISO-8859-1"))
64
```
65
66
### Reading Input Streams
67
68
```scala { .api }
69
def readStreamAsString(in: InputStream): String
70
```
71
72
Reads an InputStream completely into a string.
73
74
**Usage Examples:**
75
76
```scala
77
import scoverage.reporter.IOUtils
78
79
// Read from resource stream
80
val cssStream = getClass.getResourceAsStream("/scoverage/pure-min.css")
81
val cssContent = IOUtils.readStreamAsString(cssStream)
82
cssStream.close()
83
84
// Read from file input stream
85
val fileStream = new FileInputStream("data.txt")
86
try {
87
val content = IOUtils.readStreamAsString(fileStream)
88
println(s"Read ${content.length} characters")
89
} finally {
90
fileStream.close()
91
}
92
```
93
94
## Measurement File Handling
95
96
### Finding Measurement Files
97
98
```scala { .api }
99
def findMeasurementFiles(dataDir: File): Array[File]
100
def findMeasurementFiles(dataDir: String): Array[File]
101
```
102
103
Locates all measurement files in a scoverage data directory.
104
105
**Usage Examples:**
106
107
```scala
108
import java.io.File
109
import scoverage.reporter.IOUtils
110
111
// Find measurement files in directory
112
val dataDir = new File("target/scoverage-data")
113
val measurementFiles = IOUtils.findMeasurementFiles(dataDir)
114
115
println(s"Found ${measurementFiles.length} measurement files:")
116
measurementFiles.foreach { file =>
117
println(s" ${file.getName}")
118
}
119
120
// Using string path
121
val measurementFiles2 = IOUtils.findMeasurementFiles("target/scoverage-data")
122
```
123
124
### Getting Current Thread's Measurement File
125
126
```scala { .api }
127
def measurementFile(dataDir: File): File
128
def measurementFile(dataDir: String): File
129
```
130
131
Returns the measurement file for the current thread.
132
133
**Usage Examples:**
134
135
```scala
136
import scoverage.reporter.IOUtils
137
138
// Get measurement file for current thread
139
val dataDir = new File("target/scoverage-data")
140
val currentThreadFile = IOUtils.measurementFile(dataDir)
141
println(s"Current thread measurement file: ${currentThreadFile.getName}")
142
143
// The file will be named like: scoverage.measurements.12345
144
// where 12345 is the current thread ID
145
```
146
147
### Loading Measurement Data
148
149
```scala { .api }
150
def invoked(files: Seq[File], encoding: String = "UTF-8"): Set[(Int, String)]
151
```
152
153
Loads invocation data from measurement files, returning statement IDs and test names.
154
155
**Usage Examples:**
156
157
```scala
158
import java.io.File
159
import scoverage.reporter.IOUtils
160
161
// Load measurement data from all files
162
val dataDir = new File("target/scoverage-data")
163
val measurementFiles = IOUtils.findMeasurementFiles(dataDir)
164
val measurements = IOUtils.invoked(measurementFiles.toSeq)
165
166
println(s"Loaded ${measurements.size} statement invocations")
167
measurements.take(5).foreach { case (id, testName) =>
168
if (testName.nonEmpty) {
169
println(s"Statement $id was invoked by test: $testName")
170
} else {
171
println(s"Statement $id was invoked (no test name recorded)")
172
}
173
}
174
175
// Load with specific encoding
176
val measurementsLatin1 = IOUtils.invoked(measurementFiles.toSeq, "ISO-8859-1")
177
```
178
179
### Applying Measurements to Coverage
180
181
```scala
182
import scoverage.domain.Coverage
183
import scoverage.reporter.IOUtils
184
185
// Complete workflow: load and apply measurements
186
val coverage: Coverage = loadCoverageData()
187
val dataDir = new File("target/scoverage-data")
188
val measurementFiles = IOUtils.findMeasurementFiles(dataDir)
189
val measurements = IOUtils.invoked(measurementFiles.toSeq)
190
191
// Apply measurements to coverage
192
coverage.apply(measurements)
193
194
println(s"Coverage after applying measurements:")
195
println(s" Statements: ${coverage.invokedStatementCount}/${coverage.statementCount}")
196
println(s" Coverage: ${coverage.statementCoverageFormatted}%")
197
```
198
199
## Report File Utilities
200
201
### Getting Report File Paths
202
203
```scala { .api }
204
def reportFile(outputDir: File, debug: Boolean = false): File
205
```
206
207
Returns the standard scoverage XML report file path.
208
209
**Usage Examples:**
210
211
```scala
212
import java.io.File
213
import scoverage.reporter.IOUtils
214
215
val outputDir = new File("target/scoverage-report")
216
217
// Standard report file
218
val standardReport = IOUtils.reportFile(outputDir, debug = false)
219
println(s"Standard report: ${standardReport.getName}") // scoverage.xml
220
221
// Debug report file
222
val debugReport = IOUtils.reportFile(outputDir, debug = true)
223
println(s"Debug report: ${debugReport.getName}") // scoverage-debug.xml
224
```
225
226
## Directory Operations
227
228
### Cleaning Data Directories
229
230
```scala { .api }
231
def clean(dataDir: File): Unit
232
def clean(dataDir: String): Unit
233
```
234
235
Removes all measurement files from a data directory.
236
237
**Usage Examples:**
238
239
```scala
240
import java.io.File
241
import scoverage.reporter.IOUtils
242
243
// Clean measurement files from directory
244
val dataDir = new File("target/scoverage-data")
245
println(s"Cleaning measurement files from: ${dataDir.getPath}")
246
IOUtils.clean(dataDir)
247
248
// Clean using string path
249
IOUtils.clean("target/scoverage-data")
250
251
// Clean after generating reports
252
def generateReportsAndClean(coverage: Coverage): Unit = {
253
// Generate reports...
254
generateHtmlReport(coverage)
255
generateXmlReport(coverage)
256
257
// Clean up measurement files
258
IOUtils.clean("target/scoverage-data")
259
println("Measurement files cleaned up")
260
}
261
```
262
263
### Searching for Scoverage Data Directories
264
265
```scala { .api }
266
def scoverageDataDirsSearch(baseDir: File): Seq[File]
267
```
268
269
Recursively searches for scoverage data directories within a base directory.
270
271
**Usage Examples:**
272
273
```scala
274
import java.io.File
275
import scoverage.reporter.IOUtils
276
277
// Search for all scoverage data directories in project
278
val projectRoot = new File(".")
279
val dataDirs = IOUtils.scoverageDataDirsSearch(projectRoot)
280
281
println(s"Found ${dataDirs.size} scoverage data directories:")
282
dataDirs.foreach { dir =>
283
println(s" ${dir.getPath}")
284
}
285
286
// Use found directories for aggregation
287
if (dataDirs.nonEmpty) {
288
val aggregatedCoverage = CoverageAggregator.aggregatedCoverage(dataDirs, projectRoot)
289
println(s"Aggregated coverage: ${aggregatedCoverage.statementCoverageFormatted}%")
290
}
291
```
292
293
## Path Utilities
294
295
### Extracting File Names from Paths
296
297
```scala { .api }
298
def getName(path: String): String
299
```
300
301
Extracts the filename from a path, handling both Unix and Windows separators.
302
303
**Usage Examples:**
304
305
```scala
306
import scoverage.reporter.IOUtils
307
308
// Unix-style paths
309
val unixPath = "/path/to/file.scala"
310
println(IOUtils.getName(unixPath)) // "file.scala"
311
312
// Windows-style paths
313
val windowsPath = "C:\\path\\to\\file.scala"
314
println(IOUtils.getName(windowsPath)) // "file.scala"
315
316
// Mixed separators
317
val mixedPath = "/path\\to/file.scala"
318
println(IOUtils.getName(mixedPath)) // "file.scala"
319
```
320
321
## System Utilities
322
323
### Working with Temporary Directories
324
325
```scala { .api }
326
def getTempDirectory: File
327
def getTempPath: String
328
```
329
330
Access to system temporary directory.
331
332
**Usage Examples:**
333
334
```scala
335
import scoverage.reporter.IOUtils
336
337
// Get temp directory as File
338
val tempDir = IOUtils.getTempDirectory
339
println(s"Temp directory: ${tempDir.getPath}")
340
341
// Get temp path as String
342
val tempPath = IOUtils.getTempPath
343
println(s"Temp path: $tempPath")
344
345
// Use for temporary coverage data
346
val tempCoverageDir = new File(tempDir, "scoverage-temp")
347
tempCoverageDir.mkdirs()
348
349
// ... perform coverage operations ...
350
351
// Clean up
352
tempCoverageDir.delete()
353
```
354
355
## Advanced Usage Patterns
356
357
### Batch File Processing
358
359
```scala
360
import java.io.File
361
import scoverage.reporter.IOUtils
362
363
def processCoverageFiles(rootDir: File): Unit = {
364
// Find all data directories
365
val dataDirs = IOUtils.scoverageDataDirsSearch(rootDir)
366
367
dataDirs.foreach { dataDir =>
368
println(s"Processing directory: ${dataDir.getPath}")
369
370
// Find and process measurement files
371
val measurementFiles = IOUtils.findMeasurementFiles(dataDir)
372
if (measurementFiles.nonEmpty) {
373
val measurements = IOUtils.invoked(measurementFiles.toSeq)
374
println(s" Found ${measurements.size} measurement records")
375
376
// Process measurements...
377
} else {
378
println(s" No measurement files found")
379
}
380
}
381
}
382
```
383
384
### Multi-Encoding File Handling
385
386
```scala
387
import java.io.File
388
import scoverage.reporter.IOUtils
389
390
def writeReportWithFallback(file: File, content: String, preferredEncoding: String): Unit = {
391
try {
392
IOUtils.writeToFile(file, content, Some(preferredEncoding))
393
println(s"Written with $preferredEncoding encoding")
394
} catch {
395
case _: java.nio.charset.UnsupportedCharsetException =>
396
println(s"$preferredEncoding not supported, falling back to UTF-8")
397
IOUtils.writeToFile(file, content, Some("UTF-8"))
398
}
399
}
400
```
401
402
### Resource Management
403
404
```scala
405
import scoverage.reporter.IOUtils
406
407
def readResourceSafely(resourcePath: String): Option[String] = {
408
Option(getClass.getResourceAsStream(resourcePath)) match {
409
case Some(stream) =>
410
try {
411
Some(IOUtils.readStreamAsString(stream))
412
} finally {
413
stream.close()
414
}
415
case None =>
416
println(s"Resource not found: $resourcePath")
417
None
418
}
419
}
420
421
// Usage
422
val cssContent = readResourceSafely("/scoverage/pure-min.css")
423
cssContent.foreach { css =>
424
IOUtils.writeToFile(new File("target/pure-min.css"), css, Some("UTF-8"))
425
}
426
```
427
428
## Error Handling
429
430
### Common Issues and Solutions
431
432
**File Permission Errors:**
433
```scala
434
import java.io.IOException
435
436
try {
437
IOUtils.writeToFile(reportFile, content, Some("UTF-8"))
438
} catch {
439
case ex: IOException =>
440
println(s"Failed to write file: ${ex.getMessage}")
441
// Check directory permissions, create parent directories, etc.
442
}
443
```
444
445
**Encoding Issues:**
446
```scala
447
import java.nio.charset.UnsupportedCharsetException
448
449
try {
450
val measurements = IOUtils.invoked(measurementFiles, "CUSTOM-ENCODING")
451
} catch {
452
case ex: UnsupportedCharsetException =>
453
println(s"Unsupported encoding, using UTF-8: ${ex.getMessage}")
454
val measurements = IOUtils.invoked(measurementFiles, "UTF-8")
455
}
456
```
457
458
**Missing Directories:**
459
```scala
460
val dataDir = new File("target/scoverage-data")
461
if (!dataDir.exists()) {
462
println(s"Data directory does not exist: ${dataDir.getPath}")
463
} else {
464
val measurementFiles = IOUtils.findMeasurementFiles(dataDir)
465
if (measurementFiles.isEmpty) {
466
println("No measurement files found in directory")
467
}
468
}
469
```
470
471
### Best Practices
472
473
1. **Always Close Streams**: Use try-finally or resource management when working with streams
474
2. **Handle Encoding**: Specify encoding explicitly when reading/writing files
475
3. **Validate Paths**: Check that directories exist before attempting file operations
476
4. **Error Recovery**: Provide fallback mechanisms for common failures
477
5. **Clean Up**: Use the clean() method to remove temporary measurement files when appropriate