0
# I/O and File Processing
1
2
Enhanced file system operations, stream processing, and I/O utilities through Groovy extensions to Java's I/O classes. Provides simplified file manipulation, automatic resource management, and powerful text processing capabilities.
3
4
## Capabilities
5
6
### File Operations and Manipulation
7
8
Enhanced file operations with automatic resource management and Groovy-specific convenience methods.
9
10
```java { .api }
11
/**
12
* Extension methods added to java.io.File class
13
*/
14
class File {
15
/**
16
* Read entire file content as String with default encoding
17
*/
18
String getText();
19
String getText(String charset);
20
21
/**
22
* Write text content to file, creating parent directories if needed
23
*/
24
void setText(String text);
25
void setText(String text, String charset);
26
27
/**
28
* Append text to file
29
*/
30
void append(String text);
31
void append(String text, String charset);
32
33
/**
34
* Read file as byte array
35
*/
36
byte[] getBytes();
37
38
/**
39
* Write byte array to file
40
*/
41
void setBytes(byte[] bytes);
42
43
/**
44
* Iterate over each line in file
45
*/
46
File eachLine(Closure closure);
47
File eachLine(String charset, Closure closure);
48
File eachLine(int firstLine, Closure closure);
49
50
/**
51
* Process file with Reader/Writer
52
*/
53
Object withReader(Closure closure);
54
Object withReader(String charset, Closure closure);
55
Object withWriter(Closure closure);
56
Object withWriter(String charset, Closure closure);
57
58
/**
59
* Process file with streams
60
*/
61
Object withInputStream(Closure closure);
62
Object withOutputStream(Closure closure);
63
64
/**
65
* Copy file operations
66
*/
67
void copyTo(File target);
68
void copyTo(OutputStream target);
69
70
/**
71
* File filtering and traversal
72
*/
73
void eachFile(Closure closure);
74
void eachFileRecurse(Closure closure);
75
void eachDir(Closure closure);
76
void eachDirRecurse(Closure closure);
77
78
/**
79
* File filtering with patterns
80
*/
81
void eachFileMatch(Object nameFilter, Closure closure);
82
void eachDirMatch(Object nameFilter, Closure closure);
83
84
/**
85
* Directory operations
86
*/
87
boolean deleteDir();
88
File[] listFiles(Closure filter);
89
90
/**
91
* Create directory structure
92
*/
93
boolean mkdirs();
94
95
/**
96
* File size in human readable format
97
*/
98
String size();
99
}
100
```
101
102
**Usage Examples:**
103
104
```groovy
105
import java.io.File
106
107
// Reading files
108
def configFile = new File('config.properties')
109
def configText = configFile.getText()
110
println "Config content: $configText"
111
112
// Reading with specific encoding
113
def utf8Content = new File('data.txt').getText('UTF-8')
114
115
// Writing files
116
def outputFile = new File('output.txt')
117
outputFile.setText("Hello World\nFrom Groovy!")
118
119
// Appending to files
120
outputFile.append("\nAppended line")
121
outputFile.append("\nAnother line", 'UTF-8')
122
123
// Processing large files line by line
124
def logFile = new File('application.log')
125
logFile.eachLine { line, lineNumber ->
126
if (line.contains('ERROR')) {
127
println "Error on line $lineNumber: $line"
128
}
129
}
130
131
// Skip first line (header)
132
def csvFile = new File('data.csv')
133
csvFile.eachLine(2) { line ->
134
def columns = line.split(',')
135
println "Processing: ${columns[0]}"
136
}
137
138
// Safe file processing with automatic resource cleanup
139
def dataFile = new File('large-data.txt')
140
def wordCount = dataFile.withReader { reader ->
141
def count = 0
142
reader.eachLine { line ->
143
count += line.split(/\s+/).size()
144
}
145
return count
146
}
147
println "Total words: $wordCount"
148
149
// Binary file operations
150
def imageFile = new File('photo.jpg')
151
def imageBytes = imageFile.getBytes()
152
def backupFile = new File('photo-backup.jpg')
153
backupFile.setBytes(imageBytes)
154
155
// File copying
156
def sourceFile = new File('source.txt')
157
def targetFile = new File('target.txt')
158
sourceFile.copyTo(targetFile)
159
160
// Copy to stream
161
new FileOutputStream('output.dat').withStream { stream ->
162
sourceFile.copyTo(stream)
163
}
164
```
165
166
### Directory Traversal and File Filtering
167
168
Navigate directory structures and filter files based on various criteria.
169
170
**Usage Examples:**
171
172
```groovy
173
import java.io.File
174
175
def projectDir = new File('src/main/groovy')
176
177
// Process all files in directory
178
projectDir.eachFile { file ->
179
if (file.isFile()) {
180
println "File: ${file.name} (${file.length()} bytes)"
181
} else {
182
println "Directory: ${file.name}"
183
}
184
}
185
186
// Recursive file processing
187
projectDir.eachFileRecurse { file ->
188
if (file.name.endsWith('.groovy')) {
189
println "Groovy file: ${file.relativePath}"
190
}
191
}
192
193
// Process only directories
194
projectDir.eachDir { dir ->
195
println "Package: ${dir.name}"
196
197
// Count files in each package
198
def fileCount = dir.listFiles({ it.isFile() } as FileFilter).length
199
println " Contains $fileCount files"
200
}
201
202
// Recursive directory processing
203
def rootDir = new File('.')
204
rootDir.eachDirRecurse { dir ->
205
if (dir.name == '.git') {
206
println "Found git repository at: ${dir.absolutePath}"
207
}
208
}
209
210
// File filtering with patterns
211
def sourceDir = new File('src')
212
sourceDir.eachFileMatch(~/.*\.java$/) { file ->
213
println "Java source: ${file.name}"
214
}
215
216
// Multiple patterns
217
sourceDir.eachFileMatch([~/.*\.groovy$/, ~/.*\.java$/]) { file ->
218
println "Source file: ${file.name}"
219
}
220
221
// Directory filtering
222
def buildDir = new File('.')
223
buildDir.eachDirMatch(~/test.*/) { dir ->
224
println "Test directory: ${dir.name}"
225
}
226
227
// Complex filtering with closures
228
projectDir.eachFileRecurse { file ->
229
if (file.isFile() && file.name.endsWith('.groovy')) {
230
def lines = file.readLines()
231
if (lines.any { it.contains('class ') && it.contains('Test') }) {
232
println "Test class: ${file.name}"
233
}
234
}
235
}
236
237
// Custom file filtering
238
def largeFiles = []
239
new File('.').eachFileRecurse { file ->
240
if (file.isFile() && file.length() > 1024 * 1024) { // > 1MB
241
largeFiles << file
242
}
243
}
244
largeFiles.sort { it.length() }.each { file ->
245
println "${file.name}: ${file.length()} bytes"
246
}
247
```
248
249
### Stream Processing and I/O Operations
250
251
Work with streams, readers, and writers using Groovy's enhanced I/O operations.
252
253
```java { .api }
254
/**
255
* Extension methods for stream processing
256
*/
257
class InputStream {
258
/**
259
* Read entire stream as text
260
*/
261
String getText();
262
String getText(String charset);
263
264
/**
265
* Read stream as byte array
266
*/
267
byte[] getBytes();
268
269
/**
270
* Copy stream to OutputStream
271
*/
272
void copyTo(OutputStream target);
273
274
/**
275
* Process stream with closure
276
*/
277
Object withStream(Closure closure);
278
279
/**
280
* Iterate over lines
281
*/
282
void eachLine(Closure closure);
283
void eachLine(String charset, Closure closure);
284
}
285
286
class OutputStream {
287
/**
288
* Write text to stream
289
*/
290
void leftShift(String text);
291
void leftShift(byte[] bytes);
292
293
/**
294
* Process stream with closure
295
*/
296
Object withStream(Closure closure);
297
}
298
299
class Reader {
300
/**
301
* Read entire content
302
*/
303
String getText();
304
305
/**
306
* Iterate over lines
307
*/
308
void eachLine(Closure closure);
309
310
/**
311
* Copy to Writer
312
*/
313
void copyTo(Writer writer);
314
315
/**
316
* Filter lines
317
*/
318
void filterLines(Writer writer, Closure filter);
319
}
320
321
class Writer {
322
/**
323
* Write content using left shift operator
324
*/
325
Writer leftShift(String text);
326
Writer leftShift(Object object);
327
328
/**
329
* Write line
330
*/
331
void println(String text);
332
void println(Object object);
333
334
/**
335
* Write formatted text
336
*/
337
void printf(String format, Object... args);
338
}
339
```
340
341
**Usage Examples:**
342
343
```groovy
344
import java.io.*
345
346
// Reading from URLs
347
def url = new URL('http://example.com/data.txt')
348
def content = url.openStream().getText()
349
println content
350
351
// Stream copying
352
def sourceFile = new File('source.dat')
353
def targetFile = new File('target.dat')
354
sourceFile.withInputStream { input ->
355
targetFile.withOutputStream { output ->
356
input.copyTo(output)
357
}
358
}
359
360
// Processing compressed streams
361
def gzipFile = new File('data.gz')
362
gzipFile.withInputStream { fileStream ->
363
new GZIPInputStream(fileStream).withStream { gzipStream ->
364
gzipStream.eachLine { line ->
365
if (line.contains('ERROR')) {
366
println "Found error: $line"
367
}
368
}
369
}
370
}
371
372
// Writing to streams with operators
373
def outputFile = new File('output.txt')
374
outputFile.withWriter { writer ->
375
writer << "Header line\n"
376
writer << "Data: ${new Date()}\n"
377
writer.println("Another line")
378
writer.printf("Formatted: %d items processed\n", 42)
379
}
380
381
// Stream filtering and transformation
382
def logFile = new File('app.log')
383
def errorFile = new File('errors.log')
384
logFile.withReader { reader ->
385
errorFile.withWriter { writer ->
386
reader.filterLines(writer) { line ->
387
line.contains('ERROR') || line.contains('FATAL')
388
}
389
}
390
}
391
392
// Processing large files efficiently
393
def largeFile = new File('huge-dataset.txt')
394
def summary = [:]
395
largeFile.withReader { reader ->
396
reader.eachLine { line ->
397
def parts = line.split('\t')
398
if (parts.length > 2) {
399
def category = parts[1]
400
summary[category] = (summary[category] ?: 0) + 1
401
}
402
}
403
}
404
summary.each { category, count ->
405
println "$category: $count occurrences"
406
}
407
408
// Binary stream processing
409
def imageStream = new FileInputStream('input.jpg')
410
def processedStream = new FileOutputStream('processed.jpg')
411
imageStream.withStream { input ->
412
processedStream.withStream { output ->
413
def buffer = new byte[8192]
414
int bytesRead
415
while ((bytesRead = input.read(buffer)) != -1) {
416
// Process binary data
417
output.write(buffer, 0, bytesRead)
418
}
419
}
420
}
421
```
422
423
### Text Processing and Encoding
424
425
Advanced text processing with encoding support and character manipulation.
426
427
```java { .api }
428
/**
429
* Text processing utilities
430
*/
431
class StringWriter {
432
/**
433
* Get accumulated string content
434
*/
435
String toString();
436
437
/**
438
* Clear content
439
*/
440
void reset();
441
}
442
443
class CharsetToolkit {
444
/**
445
* Detect file encoding
446
*/
447
static Charset guessEncoding(File file);
448
static Charset guessEncoding(byte[] bytes);
449
450
/**
451
* Convert between encodings
452
*/
453
static String convertEncoding(String text, String fromCharset, String toCharset);
454
static byte[] convertEncoding(byte[] bytes, String fromCharset, String toCharset);
455
}
456
```
457
458
**Usage Examples:**
459
460
```groovy
461
import java.io.*
462
import java.nio.charset.Charset
463
464
// String building with StringWriter
465
def content = new StringWriter()
466
content << "Line 1\n"
467
content << "Line 2\n"
468
content.println("Line 3")
469
def result = content.toString()
470
471
// Processing files with different encodings
472
def latinFile = new File('latin1-data.txt')
473
def utf8File = new File('utf8-data.txt')
474
475
// Convert encoding
476
latinFile.withReader('ISO-8859-1') { reader ->
477
utf8File.withWriter('UTF-8') { writer ->
478
reader.copyTo(writer)
479
}
480
}
481
482
// Detect file encoding (requires external library)
483
def unknownFile = new File('unknown-encoding.txt')
484
// def detectedCharset = CharsetToolkit.guessEncoding(unknownFile)
485
// println "Detected encoding: $detectedCharset"
486
487
// Process multilingual text
488
def multilingualData = new File('multilingual.txt')
489
multilingualData.eachLine('UTF-8') { line ->
490
// Process Unicode text correctly
491
println "Line length: ${line.codePointCount(0, line.length())} characters"
492
}
493
494
// Text transformation pipeline
495
def inputFile = new File('input.txt')
496
def outputFile = new File('processed.txt')
497
498
inputFile.withReader('UTF-8') { reader ->
499
outputFile.withWriter('UTF-8') { writer ->
500
reader.eachLine { line ->
501
// Transform text: uppercase, trim, filter
502
def processed = line.trim().toUpperCase()
503
if (processed.length() > 0 && !processed.startsWith('#')) {
504
writer.println(processed)
505
}
506
}
507
}
508
}
509
```
510
511
### URL and Network I/O
512
513
Handle network resources and URL-based I/O operations.
514
515
**Usage Examples:**
516
517
```groovy
518
import java.net.URL
519
import java.net.URLConnection
520
521
// Read from URL
522
def url = new URL('https://api.example.com/data.json')
523
def jsonData = url.getText()
524
println "API Response: $jsonData"
525
526
// URL with custom headers
527
def connection = url.openConnection()
528
connection.setRequestProperty('User-Agent', 'Groovy Script')
529
connection.setRequestProperty('Accept', 'application/json')
530
def response = connection.inputStream.getText('UTF-8')
531
532
// Download file from URL
533
def fileUrl = new URL('https://example.com/document.pdf')
534
def localFile = new File('downloaded-document.pdf')
535
fileUrl.withInputStream { input ->
536
localFile.withOutputStream { output ->
537
input.copyTo(output)
538
}
539
}
540
541
// POST data to URL
542
def postUrl = new URL('https://api.example.com/submit')
543
def postConnection = postUrl.openConnection()
544
postConnection.doOutput = true
545
postConnection.requestMethod = 'POST'
546
postConnection.setRequestProperty('Content-Type', 'application/json')
547
548
def jsonPayload = '{"name": "John", "age": 30}'
549
postConnection.outputStream.withWriter('UTF-8') { writer ->
550
writer << jsonPayload
551
}
552
553
def statusCode = postConnection.responseCode
554
def responseText = postConnection.inputStream.getText('UTF-8')
555
println "Status: $statusCode, Response: $responseText"
556
557
// Error handling for network operations
558
try {
559
def unreliableUrl = new URL('https://unreliable-api.com/data')
560
def data = unreliableUrl.getText()
561
println "Success: $data"
562
} catch (IOException e) {
563
println "Network error: ${e.message}"
564
// Fallback to cached data or default values
565
}
566
```
567
568
### File Watching and Monitoring
569
570
Monitor file system changes and respond to file modifications.
571
572
**Usage Examples:**
573
574
```groovy
575
import java.nio.file.*
576
import java.nio.file.attribute.BasicFileAttributes
577
import static java.nio.file.StandardWatchEventKinds.*
578
579
// Simple file modification checking
580
def configFile = new File('config.properties')
581
def lastModified = configFile.lastModified()
582
583
// Periodically check for changes
584
def timer = new Timer()
585
timer.scheduleAtFixedRate(new TimerTask() {
586
void run() {
587
if (configFile.lastModified() > lastModified) {
588
println "Config file changed, reloading..."
589
// Reload configuration
590
lastModified = configFile.lastModified()
591
}
592
}
593
}, 0, 5000) // Check every 5 seconds
594
595
// Using Java NIO WatchService for real-time monitoring
596
def watchDir = Paths.get('.')
597
def watchService = FileSystems.getDefault().newWatchService()
598
watchDir.register(watchService, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY)
599
600
// Monitor in separate thread
601
Thread.start {
602
while (true) {
603
def key = watchService.take()
604
for (event in key.pollEvents()) {
605
def kind = event.kind()
606
def filename = event.context()
607
608
println "File event: $kind - $filename"
609
610
if (kind == ENTRY_MODIFY && filename.toString().endsWith('.groovy')) {
611
println "Groovy file modified: $filename"
612
// Trigger recompilation or reload
613
}
614
}
615
616
if (!key.reset()) {
617
break
618
}
619
}
620
}
621
622
// File tree walking
623
def sourceDir = Paths.get('src')
624
Files.walkFileTree(sourceDir, new SimpleFileVisitor<Path>() {
625
FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
626
if (file.toString().endsWith('.groovy')) {
627
println "Found Groovy file: $file"
628
// Analyze or process file
629
}
630
return FileVisitResult.CONTINUE
631
}
632
633
FileVisitResult visitFileFailed(Path file, IOException exc) {
634
println "Failed to access: $file - ${exc.message}"
635
return FileVisitResult.CONTINUE
636
}
637
})
638
```
639
640
## Types
641
642
### File Extension Types
643
644
```java { .api }
645
/**
646
* Enhanced File operations (extension methods)
647
*/
648
interface FileExtensions {
649
/**
650
* Get file content as text with encoding
651
*/
652
String getText(String charset);
653
654
/**
655
* Set file content with encoding
656
*/
657
void setText(String text, String charset);
658
659
/**
660
* Process file lines with closure
661
*/
662
File eachLine(Closure closure);
663
File eachLine(String charset, Closure closure);
664
665
/**
666
* Safe resource processing
667
*/
668
Object withReader(Closure closure);
669
Object withWriter(Closure closure);
670
Object withInputStream(Closure closure);
671
Object withOutputStream(Closure closure);
672
673
/**
674
* Directory traversal methods
675
*/
676
void eachFile(Closure closure);
677
void eachFileRecurse(Closure closure);
678
void eachDir(Closure closure);
679
void eachDirRecurse(Closure closure);
680
681
/**
682
* Pattern-based file filtering
683
*/
684
void eachFileMatch(Object nameFilter, Closure closure);
685
void eachDirMatch(Object nameFilter, Closure closure);
686
}
687
```
688
689
### Stream Extension Types
690
691
```java { .api }
692
/**
693
* Enhanced stream operations (extension methods)
694
*/
695
interface StreamExtensions {
696
/**
697
* Get stream content as text
698
*/
699
String getText();
700
String getText(String charset);
701
702
/**
703
* Get stream content as bytes
704
*/
705
byte[] getBytes();
706
707
/**
708
* Copy stream content
709
*/
710
void copyTo(OutputStream target);
711
void copyTo(Writer target);
712
713
/**
714
* Process stream with closure
715
*/
716
Object withStream(Closure closure);
717
718
/**
719
* Line processing
720
*/
721
void eachLine(Closure closure);
722
void eachLine(String charset, Closure closure);
723
724
/**
725
* Line filtering
726
*/
727
void filterLines(Writer writer, Closure filter);
728
}
729
730
/**
731
* Writer extensions
732
*/
733
interface WriterExtensions {
734
/**
735
* Left shift operator for writing
736
*/
737
Writer leftShift(String text);
738
Writer leftShift(Object object);
739
740
/**
741
* Print methods
742
*/
743
void println(String text);
744
void println(Object object);
745
void printf(String format, Object... args);
746
}
747
```