Guide til I / O i Groovy

1. Introduktion

Selvom vi i Groovy kan arbejde med I / O, ligesom vi gør i Java, Groovy udvider Java's I / O-funktionalitet med en række hjælpemetoder.

I denne vejledning ser vi på læsning og skrivning af filer, gennemkørsel af filsystemer og serialisering af data og objekter via Groovy's Fil udvidelsesmetoder.

Hvor det er relevant, vil vi linke til vores relevante Java-artikler for nem sammenligning med Java-ækvivalenten.

2. Læsning af filer

Groovy tilføjer praktisk funktionalitet til læsning af filer i form af hver linie metoder, metoder til at få BufferedReaders og InputStreams og måder at få alle fildataene med en linje kode.

Java 7 og Java 8 har lignende support til læsning af filer i Java.

2.1. Læser med hver linie

Når vi beskæftiger os med tekstfiler, er vi ofte nødt til at læse hver linje og behandle den. Groovy giver en praktisk udvidelse til java.io-fil med hver linie metode:

def lines = [] ny fil ('src / main / resources / ioInput.txt'). eachLine {line -> lines.add (line)}

Lukningen til hver linie har også et nyttigt valgfrit linjenummer. Lad os bruge linjenummeret til kun at få specifikke linjer fra en fil:

def lineNoRange = 2..4 def lines = [] ny fil ('src / main / resources / ioInput.txt'). eachLine {line, lineNo -> if (lineNoRange.contains (lineNo)) {lines.add (line )}}

Linjenummereringen starter som standard ved en. Vi kan give en værdi, der skal bruges som første linjenummer, ved at sende den som den første parameter til hver linie metode.

Lad os starte vores linjenumre på nul:

ny fil ('src / main / resources / ioInput.txt'). eachLine (0, {line, lineNo -> if (lineNoRange.contains (lineNo)) {lines.add (line)}})

Hvis en undtagelse kastes ind hver linie, Groovy sørger for, at filressourcen lukkes. Meget som en prøv med ressourcer eller a prøv endelig i Java.

2.2. Læsning med læser

Vi kan også let få en BufferedReader fra en Groovy Fil objekt. Vi kan bruge withReader at få en BufferedReader til filobjektet og overføre det til en lukning:

def actualCount = 0 ny fil ('src / main / resources / ioInput.txt'). withReader {reader -> while (reader.readLine ()) {actualCount ++}}

Som med hver linie, det withReader metode lukker automatisk ressourcen, når en undtagelse kastes.

Nogle gange vil vi måske have BufferedReader objekt til rådighed. For eksempel planlægger vi måske at kalde en metode, der tager en som parameter. Vi kan bruge newReader metode til dette:

def outputPath = 'src / main / resources / ioOut.txt' def reader = new File ('src / main / resources / ioInput.txt'). newReader () new File (outputPath). append (reader) reader.close ( )

I modsætning til de andre metoder, vi har set på hidtil, vi er ansvarlige for at lukke BufferedReader ressource, når vi erhverver en BufferLæser denne måde.

2.3. Læser med InputStreams

Svarende til withReader og newReader, Groovy giver også metoder til let at arbejde med InputStreams. Selvom vi kan læse tekst med InputStreams og Groovy tilføjer endda funktionalitet til det, InputStreams bruges mest til binære data.

Lad os bruge medInputStream at bestå en InputStream til en lukning og læs i byte:

byte [] data = [] ny fil ("src / main / resources / binaryExample.jpg"). medInputStream {stream -> data = stream.getBytes ()}

Hvis vi har brug for InputStream objekt, kan vi få en med newInputStream:

def outputPath = 'src / main / resources / binaryOut.jpg' def is = new File ('src / main / resources / binaryExample.jpg'). newInputStream () new File (outputPath) .append (is) is.close ( )

Som med BufferedReader, vi er nødt til at lukke vores InputStream ressource os selv, når vi bruger newInputStream, men ikke ved brug medInputStream.

2.4. Læsning af andre måder

Lad os afslutte emnet læsning ved at se på et par metoder, Groovy har til at få fat i alle fildataene i en erklæring.

Hvis vi vil have linjerne i vores fil i en Liste, vi kan bruge indsamle med en iterator det videregivet til lukningen:

def actualList = ny fil ('src / main / resources / ioInput.txt'). indsaml {it}

For at få linjerne i vores fil i en række Strenge, vi kan bruge som streng []:

def actualArray = ny fil ('src / main / resources / ioInput.txt') som streng []

For korte filer kan vi få hele indholdet i en Snor ved brug af tekst:

def actualString = ny fil ('src / main / resources / ioInput.txt'). tekst

Og når du arbejder med binære filer, er der bytes metode:

def indhold = ny fil ('src / main / resources / binaryExample.jpg'). bytes

3. Skrivning af filer

Før vi begynder at skrive til filer, lad os opsætte den tekst, vi vil udsende:

def outputLines = ['Linje en af ​​outputeksemplet', 'Linje to af outputeksemplet', 'Linje tre af outputeksemplet']

3.1. Skrivning med Writer

Som ved læsning af en fil, vi kan også let få en BufferedWriter ud af en Fil objekt.

Lad os bruge medWriter at få en BufferedWriter og send det til en lukning:

def outputFileName = 'src / main / resources / ioOutput.txt' new File (outputFileName). withWriter {writer -> outputLines.each {line -> writer.writeLine line}}

Ved brug af withReader lukker ressourcen, hvis der opstår en undtagelse.

Groovy har også en metode til at få BufferedWriter objekt. Lad os få en BufferedWriter ved brug af newWriter:

def outputFileName = 'src / main / resources / ioOutput.txt' def writer = new File (outputFileName) .newWriter () outputLines.forEach {line -> writer.writeLine line} writer.flush () writer.close ()

Vi er ansvarlige for at skylle og lukke vores BufferedWriter objekt, når vi bruger newWriter.

3.2. Skrivning med outputstrømme

Hvis vi skriver binære data ud, vi kan få en OutputStream ved hjælp af en af ​​dem medOutputStream eller newOutputStream.

Lad os skrive nogle bytes til en fil ved hjælp af medOutputStream:

byte [] outBytes = [44, 88, 22] ny fil (outputFileName). medOutputStream {stream -> stream.write (outBytes)}

Lad os få en OutputStream objekt med newOutputStream og brug den til at skrive nogle byte:

byte [] outBytes = [44, 88, 22] def os = ny fil (outputFileName) .newOutputStream () os.write (outBytes) os.close ()

På samme måde som InputStream, BufferedReaderog BufferedWriter, vi er ansvarlige for at lukke OutputStream os selv, når vi bruger newOutputStream.

3.3. Skrivning med << operatøren

Da det er så almindeligt at skrive tekst til filer, er << operatøren tilbyder denne funktion direkte.

Lad os bruge << operatør til at skrive nogle enkle tekstlinjer:

def ln = System.getProperty ('line.separator') def outputFileName = 'src / main / resources / ioOutput.txt' new File (outputFileName) << "Linje en af ​​outputeksemplet $ {ln}" + "Linje to af outputeksempel $ {ln} Linje tre i outputeksempel "

3.4. Skrivning af binære data med byte

Vi så tidligere i artiklen, at vi kan få alle byte ud af en binær fil ved blot at få adgang til bytes Mark.

Lad os skrive binære data på samme måde:

def outputFileName = 'src / main / resources / ioBinaryOutput.bin' def outputFile = ny fil (outputFileName) byte [] outBytes = [44, 88, 22] outputFile.bytes = outBytes

4. Traversering af filetræer

Groovy giver os også nemme måder at arbejde med filtræer på. I dette afsnit vil vi gøre det med hver fil, hverDir og deres varianter og krydse metode.

4.1. Notering af filer med hver fil

Lad os liste alle filerne og katalogerne i et bibliotek ved hjælp af hver fil:

ny fil ('src / main / resources'). hver fil {fil -> println fil.navn}

Et andet almindeligt scenarie, når du arbejder med filer, er behovet for at filtrere filerne baseret på filnavnet. Lad os kun liste de filer, der starter med "io" og slutter med ".txt" ved hjælp af eachFileMatch og et regulært udtryk:

ny fil ('src / main / resources'). eachFileMatch (~ / io. * \. txt /) {fil -> println fil.navn}

Det hver fil og eachFileMatch metoder viser kun indholdet i topniveaumappen. Groovy giver os også mulighed for at begrænse, hvad hver fil metoder vender tilbage ved at videregive en Filtype til metoderne. Indstillingerne er NOGEN, FILERog KORT.

Lad os rekursivt liste alle filerne ved hjælp af hverFilRecurse og give det en Filtype af FILER:

ny fil ('src / main'). eachFileRecurse (FileType.FILES) {fil -> println "$ file.parent $ file.name"}

Det hver fil metoder kaster en IllegalArgumentException hvis vi giver dem en sti til en fil i stedet for en mappe.

Groovy leverer også hverDir metoder til kun at arbejde med mapper. Vi kan bruge hverDir og dens varianter for at opnå det samme som at bruge hver fil med en Filtype af KORT.

Lad os rekursivt liste mapper med hverFilRecurse:

ny fil ('src / main'). eachFileRecurse (FileType.DIRECTORIES) {fil -> println "$ file.parent $ file.name"}

Lad os nu gøre det samme med hverDirRecurse:

ny fil ('src / main'). eachDirRecurse {dir -> println "$ dir.parent $ dir.name"}

4.2. Notering af filer med Traverse

For mere komplicerede tilfælde af bibliotekstransversation kan vi bruge krydse metode. Det fungerer på samme måde som hverFilRecurse men giver mulighed for at vende tilbage FileVisitResult objekter til at kontrollere behandlingen.

Lad os bruge krydse på vores src / main bibliotek og spring over behandling af træet under groovy vejviser:

ny fil ('src / main'). gennemgå {fil -> hvis (fil.directory && fil.navn == 'groovy') {FileVisitResult.SKIP_SUBTREE} andet {println "$ file.parent - $ file.name"} }

5. Arbejde med data og objekter

5.1. Serialisering af primitiver

I Java kan vi bruge DataInputStream og DataOutputStream for at serieisere primitive datafelter. Groovy tilføjer også nyttige udvidelser her.

Lad os oprette nogle primitive data:

String message = 'Dette er en seriel streng' int length = message.length () boolean valid = true

Lad os nu serialisere vores data til en fil ved hjælp af medDataOutputStream:

ny fil ('src / main / resources / ioData.txt'). medDataOutputStream {ud -> out.writeUTF (besked) out.writeInt (længde) out.writeBoolean (gyldig)}

Og læs det tilbage ved brug medDataInputStream:

String loadedMessage = "" int loadedLength boolean loadedValid new File ('src / main / resources / ioData.txt'). WithDataInputStream {is -> loadedMessage = is.readUTF () loadedLength = is.readInt () loadedValid = is.readBoolean ( )}

Svarende til den anden med* metoder, medDataOutputStream og medDataInputStream send strømmen til lukningen, og sørg for, at den er lukket ordentligt.

5.2. Serialisering af objekter

Groovy bygger også på Java'er ObjectInputStream og ObjectOutputStream for at give os mulighed for let at serieisere objekter, der implementeres Serialiserbar.

Lad os først definere en klasse, der implementeres Serialiserbar:

klasse Opgaveimplementeringer Serialiserbar {Stringbeskrivelse Dato startdato Dato forfaldsdato int-status}

Lad os nu oprette en forekomst af Opgave at vi kan serieisere til en fil:

Opgaveopgave = ny opgave (beskrivelse: 'Tag papirkurven ud', startdato: ny dato (), status: 0)

Med vores Opgave objekt i hånden, lad os serieisere det til en fil ved hjælp af medObjectOutputStream:

ny fil ('src / main / resources / ioSerializedObject.txt'). medObjectOutputStream {ud -> out.writeObject (opgave)}

Lad os endelig læse vores Opgave tilbage i brug medObjectInputStream:

Task taskLæs ny fil ('src / main / resources / ioSerializedObject.txt'). WithObjectInputStream {is -> taskRead = is.readObject ()}

De metoder, vi brugte, medObjectOutputStream og medObjectInputStream, send strømmen til en lukning og håndter at lukke ressourcerne korrekt, ligesom det ses med den anden med* metoder.

6. Konklusion

I denne artikel undersøgte vi funktionalitet, som Groovy tilføjer til eksisterende Java File I / O-klasser. Vi brugte denne funktionalitet til at læse og skrive filer, arbejde med bibliotekstrukturer og serialisere data og objekter.

Vi berørte kun et par af hjælpemetoderne, så det er værd at grave i Groovys dokumentation for at se, hvad der ellers tilføjer Java's I / O-funktionalitet.

Eksempelkoden er tilgængelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found