Groovy Guide — File I/O: Reading and Writing Files
In this tutorial, you will learn about Groovy Guide. We cover key concepts, practical examples, and best practices to help you master this topic.
Groovy file I/O extends Java's file APIs with convenience methods like eachLine, text, withReader, and withWriter for common file operations.
What You'll Learn
- Reading files with text, eachLine, readLines
- Writing files with withWriter, append, text
- Binary file operations
- Directory traversal
- Temporary files
Why It Matters
File operations are common in scripting. Groovy's compact syntax makes file processing concise. Durga Antivirus Pro uses file I/O for log analysis.
Real-World Use
Log file processing, configuration reading, data export, and build scripts.
flowchart LR
A["File I/O"] --> B["Reading"]
B --> C["Writing"]
C --> D["Binary"]
D --> E["Directories"]
A:::current --> B
style A fill:#2563eb,stroke:#2563eb,color:#fff
style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
style E fill:#f1f5f9,stroke:#94a3b8,color:#64748b
Reading Files
// Read entire file
def content = new File("data.txt").text
// Read lines lazily
def lineCount = 0
new File("data.txt").eachLine { line ->
lineCount++
}
// Read all lines as list
def lines = new File("data.txt").readLines()
// With reader (auto-close)
new File("data.txt").withReader { reader ->
println reader.readLine()
}
Writing Files
// Write entire file
new File("output.txt").text = "Hello, Groovy!"
// Append
new File("log.txt") << "New log entry\n"
// With writer (auto-close)
new File("output.txt").withWriter { writer ->
writer.writeLine("Line 1")
writer.writeLine("Line 2")
}
// Append with writer
new File("log.txt").withWriterAppend { writer ->
writer.writeLine("Appended line")
}
Binary Files
// Read bytes
def bytes = new File("image.jpg").bytes
// Write bytes
new File("copy.jpg").bytes = bytes
// Stream processing
new File("large.bin").withInputStream { stream ->
byte[] buffer = new byte[8192]
int read
while ((read = stream.read(buffer)) != -1) {
// Process buffer
}
}
Directory Operations
// List files
new File(".").eachFile { file ->
println file.name
}
// List by extension
new File(".").eachFileMatch(~/.*\.groovy/) { file ->
println file.name
}
// Recursive traversal
new File("src").eachFileRecurse { file ->
if (file.isFile()) {
println file.path
}
}
// Filter by type
new File("src").eachFile { file ->
if (file.isDirectory()) {
println "DIR: $file.name"
}
}
File Utilities
// Create directories
new File("path/to/dir").mkdirs()
// Delete
new File("temp.txt").delete()
// Copy
new File("source.txt") >> new File("dest.txt")
// Rename
new File("old.txt").renameTo("new.txt")
// Temp files
def temp = File.createTempFile("prefix", ".txt")
temp.deleteOnExit()
// Size
def size = new File("data.txt").size()
Filtering and Searching
// Filter lines
new File("log.txt").filterLine { line ->
line.contains("ERROR")
}.writeTo(new File("errors.txt"))
// Search text
def matches = new File("data.txt").findAll { it =~ /pattern/ }
// Replace in-place
def text = new File("data.txt").text
text = text.replaceAll("old", "new")
new File("data.txt").text = text
Common Mistakes
1. Not closing resources
Use .withReader/.withWriter or .text for auto-closing. Manual streams need explicit close().
2. Large file memory
.text loads entire file. Use .eachLine for large files.
3. File encoding
Specify encoding: new File("data.txt").getText("UTF-8"). Default is platform encoding.
4. Path separators
Use forward slashes in paths. Groovy normalizes them across platforms.
5. Relative paths
Relative paths depend on working directory. Use absolute paths in scripts.
Practice Questions
1. How do you read a file line by line?
Use new File("path").eachLine { line -> ... } for memory-efficient processing.
2. How do you write without closing manually?
Use .withWriter { writer -> ... } which auto-closes the writer after the closure.
3. How do you append to a file?
Use the << operator: new File("log.txt") << "new data".
Challenge: Write a Groovy script that recursively finds all .groovy files and counts their lines.
FAQ
{{< faq question="Is Groovy file I/O faster than Java?" >} Same performance under the hood. Groovy adds convenience methods that delegate to Java NIO. {{< /faq >}}
{{< faq question="Can Groovy read GZip files?" >}
Yes. Wrap FileInputStream with GZipInputStream: new GZipInputStream(new FileInputStream("file.gz")).
{{< /faq >}}
{{< faq question="How do I watch a file for changes?" >} Use Java's WatchService API. Groovy doesn't add specific file watching features. {{< /faq >}}
{{< faq question="What is the << operator on File?" >} The leftShift operator appends content to the file. Internally calls append(). {{< /faq >}}
{{< faq question="Can I read from URLs?" >}
Yes. new URL("http://example.com").text reads the URL content directly.
{{< /faq >}}
Mini Project
Build a log file analyzer with Groovy file I/O:
class LogAnalyzer {
def analyze(String logPath) {
def results = [:]
new File(logPath).eachLine { line ->
def matcher = line =~ /(\w+)\s+\[(\w+)\]\s+(.+)/
if (matcher) {
def level = matcher[0][2]
results[level] = (results[level] ?: 0) + 1
}
}
return results
}
def extractErrors(String logPath, String outputPath) {
new File(outputPath).withWriter { writer ->
new File(logPath).eachLine { line ->
if (line.contains("ERROR") || line.contains("FATAL")) {
writer.writeLine(line)
}
}
}
}
}
def analyzer = new LogAnalyzer()
println analyzer.analyze("app.log")
What's Next
Now that you understand file I/O, explore SQL database access in Groovy.
| Topic | Description | Link |
|---|---|---|
| Groovy SQL | Database access | {{< ref "13-sql" >}} |
| Groovy Templates | Template engine | {{< ref "14-templates" >}} |
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro