Guide til I / O i Groovy

1. Introduksjon

Selv om vi i Groovy kan jobbe med I / O akkurat som vi gjør i Java, Groovy utvider Java's I / O-funksjonalitet med en rekke hjelpemetoder.

I denne opplæringen vil vi se på lesing og skriving av filer, kryssing av filsystemer og serialisering av data og objekter via Groovy's Fil utvidelsesmetoder.

Der det er aktuelt, kobler vi til relevante Java-artikler for enkel sammenligning med Java-ekvivalenten.

2. Lese filer

Groovy legger til praktisk funksjonalitet for å lese filer i form av eachLine metoder, metoder for å få BufferedReaders og InputStreams, og måter å få alle fildataene med en linje med kode.

Java 7 og Java 8 har lignende støtte for å lese filer i Java.

2.1. Lese med eachLine

Når vi arbeider med tekstfiler, trenger vi ofte å lese hver linje og behandle den. Groovy gir en praktisk utvidelse til java.io. fil med eachLine metode:

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

Avslutningen gitt til eachLine har også et nyttig valgfritt linjenummer. La oss bruke linjenummeret for å få bare spesifikke linjer fra en fil:

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

Som standard starter linjenummereringen på en. Vi kan gi en verdi å bruke som første linjenummer ved å sende den som den første parameteren til eachLine metode.

La oss starte linjenumrene våre på null:

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

Hvis et unntak kastes inn eachLine, Groovy sørger for at filressursen blir lukket. Mye som en prøv-med-ressurser eller a prøv-endelig i Java.

2.2. Lesing med leser

Vi kan også enkelt få en BufferedReader fra en Groovy Fil gjenstand. Vi kan bruke withReader å få en BufferedReader til filobjektet og overføre det til en lukking:

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

Som med eachLine, den withReader metoden vil automatisk lukke ressursen når et unntak kastes.

Noen ganger vil vi kanskje ha BufferedReader objekt tilgjengelig. For eksempel kan vi planlegge å kalle en metode som tar en som parameter. Vi kan bruke newReader metode for 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 motsetning til de andre metodene vi har sett på så langt, vi er ansvarlige for å lukke BufferedReader ressurs når vi skaffer oss en BufretLeser denne måten.

2.3. Lese med InputStreams

Lik withReader og newReader, Groovy gir også metoder for lett å jobbe med InputStreams. Selv om vi kan lese tekst med InputStreams og Groovy legger til og med funksjonalitet for det, InputStreams brukes oftest til binære data.

La oss bruke medInputStream å passere en InputStream til en lukking og les i byte:

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

Hvis vi trenger å ha 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, må vi lukke InputStream ressurs oss selv når vi bruker newInputStream, men ikke når du bruker medInputStream.

2.4. Lese andre måter

La oss avslutte leseemnet ved å se på noen metoder Groovy har for å hente alle fildataene i en uttalelse.

Hvis vi vil at linjene i filen vår skal være i Liste, Vi kan bruke samle inn med en iterator den gått til avslutningen:

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

For å få linjene i filen vår til en rekke Strenger, Vi kan bruke som streng []:

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

For korte filer kan vi få hele innholdet i en String ved hjelp av tekst:

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

Og når du jobber med binære filer, er det byte metode:

def innhold = ny fil ('src / main / resources / binaryExample.jpg'). byte

3. Skrive filer

Før vi begynner å skrive til filer, la oss sette opp teksten vi skal sende ut:

def outputLines = ['Line one of output example', 'Line two of output example', 'Line three of output example']

3.1. Skrive med Writer

Som med å lese en fil, vi kan også enkelt få en BufferedWriter ut av en Fil gjenstand.

La oss bruke withWriter å få en BufferedWriter og send den til en lukking:

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

Ved hjelp av withReader lukker ressursen dersom et unntak skulle oppstå.

Groovy har også en metode for å få BufferedWriter gjenstand. La oss få en BufferedWriter ved hjelp av 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 å skylle og lukke BufferedWriter objekt når vi bruker newWriter.

3.2. Skrive med utgangsstrømmer

Hvis vi skriver ut binære data, vi kan få en OutputStream bruker enten medOutputStream eller newOutputStream.

La oss skrive noen byte til en fil ved hjelp av medOutputStream:

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

La oss få en OutputStream objekt med newOutputStream og bruk den til å skrive noen byte:

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

På samme måte som InputStream, BufferedReader, og BufferedWriter, vi er ansvarlige for å lukke OutputStream oss selv når vi bruker newOutputStream.

3.3. Skriver med << operatøren

Siden det er så vanlig å skrive tekst til filer, er << operatøren gir denne funksjonen direkte.

La oss bruke << operatør for å skrive noen enkle tekstlinjer:

def ln = System.getProperty ('line.separator') def outputFileName = 'src / main / resources / ioOutput.txt' new File (outputFileName) << "Linje en av utdataeksemplet $ {ln}" + "Linje to av utdataeksempel $ {ln} Linje tre i utdataeksempelet "

3.4. Skrive binære data med byte

Vi så tidligere i artikkelen at vi kan få alle byte ut av en binær fil ved å få tilgang til byte felt.

La oss skrive binære data på samme måte:

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

4. Kryssing av filetrær

Groovy gir oss også enkle måter å jobbe med filetrær på. I denne delen skal vi gjøre det med hver fil, hverDir og deres varianter og kryss metode.

4.1. Listing Files med hver fil

La oss liste opp alle filene og katalogene i en katalog som bruker hver fil:

ny fil ('src / main / resources'). eachFile {file -> println file.name}

Et annet vanlig scenario når du arbeider med filer er behovet for å filtrere filene basert på filnavnet. La oss bare liste opp filene som starter med "io" og slutter med ".txt" ved hjelp av eachFileMatch og et vanlig uttrykk:

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

De hver fil og eachFileMatch metoder viser bare innholdet i toppnivåkatalogen. Groovy lar oss også begrense hva hver fil metoder returnerer ved å passere en Filtype til metodene. Alternativene er NOEN, FILER, og Kataloger.

La oss rekursivt liste opp alle filene som brukes eachFileRecurse og gi den en Filtype av FILER:

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

De hver fil metoder kaster en IllegalArgumentException hvis vi gir dem en sti til en fil i stedet for en katalog.

Groovy gir også hverDir metoder for å jobbe med bare kataloger. Vi kan bruke hverDir og dens varianter for å oppnå det samme som å bruke hver fil med en Filtype av Kataloger.

La oss rekursivt liste opp kataloger med eachFileRecurse:

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

La oss gjøre det samme med eachDirRecurse:

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

4.2. Oppføring av filer med Traverse

For mer kompliserte katalogtilfeller kan vi bruke kryss metode. Den fungerer på samme måte som eachFileRecurse men gir muligheten til å komme tilbake FileVisitResult objekter for å kontrollere behandlingen.

La oss bruke kryss på vår src / main katalog og hopp over å behandle treet under groovy katalog:

ny fil ('src / main'). traverse {file -> if (file.directory && file.name == 'groovy') {FileVisitResult.SKIP_SUBTREE} annet {println "$ file.parent - $ file.name"} }

5. Arbeide med data og objekter

5.1. Serialisering av primitiver

I Java kan vi bruke DataInputStream og DataOutputStream for å serieisere primitive datafelter. Groovy legger til nyttige utvidelser også her.

La oss sette opp noen primitive data:

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

La oss nå serieisere dataene våre til en fil ved hjelp av medDataOutputStream:

ny fil ('src / main / resources / ioData.txt'). medDataOutputStream {ut -> out.writeUTF (melding) out.writeInt (lengde) out.writeBoolean (gyldig)}

Og les den tilbake i bruk withDataInputStream:

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

I likhet med den andre med* metoder, medDataOutputStream og withDataInputStream før strømmen til lukkingen og sørg for at den er ordentlig lukket.

5.2. Serialisere objekter

Groovy bygger også på Java ObjectInputStream og ObjectOutputStream slik at vi enkelt kan serieisere objekter som implementeres Serialiserbar.

La oss først definere en klasse som implementeres Serialiserbar:

klasse Oppgaveimplementerer Serialiserbar {Strengbeskrivelse Dato startdato Dato forfallsdato int status}

La oss nå lage en forekomst av Oppgave at vi kan serieisere til en fil:

Oppgaveoppgave = ny oppgave (beskrivelse: 'Ta ut søpla', startdato: ny dato (), status: 0)

Med vår Oppgave objekt i hånden, la oss serieisere det til en fil ved hjelp av withObjectOutputStream:

ny fil ('src / main / resources / ioSerializedObject.txt'). withObjectOutputStream {out -> out.writeObject (task)}

Til slutt, la oss lese vår Oppgave tilbake i bruk withObjectInputStream:

Oppgaveoppgave Les ny fil ('src / main / resources / ioSerializedObject.txt'). WithObjectInputStream {is -> taskRead = is.readObject ()}

Metodene vi brukte, withObjectOutputStream og withObjectInputStream, send strømmen til en lukking og håndter å lukke ressursene riktig, akkurat som sett med den andre med* metoder.

6. Konklusjon

I denne artikkelen undersøkte vi funksjonalitet som Groovy legger til eksisterende Java File I / O-klasser. Vi brukte denne funksjonaliteten til å lese og skrive filer, jobbe med katalogstrukturer og serialisere data og objekter.

Vi berørte bare noen få av hjelpermetodene, så det er verdt å grave i Groovys dokumentasjon for å se hva annet det legger til Java's I / O-funksjonalitet.

Eksempelkoden er tilgjengelig på GitHub.


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