Operacje odczytu i zapisu

Obsługa plików tekstowych


Przetwarzanie plików tekstowych i obsługa wyrażeń regularnych jest jednym z najczęstszych zastosowań języków skryptowych, dlatego zgłębianie możliwości grooviego rozpocząłem od obsługi operecji wejścia/wyjścia.

Odczyt pliku

W najprostszym przypadku odczyt pliku można wykonać w jednej linii kodu. Ma on następującą postać:

new File("source.txt").eachLine{linia -> print linia}

W powyższym przykładzie wykorzystałem powszechnie stosowany mechanizm domknięć (clousures). Polega on na tym że metoda przekazuje swój wynik do operacji które znajdują się w zasięgu nawiasów klamrowych. Dostęp do wartości zwróconej przez metodę uzyskuje się przy pomocy odczytu wartości parametru zdefiniowanego na samym początku domknięcia, przed znakiem "->" - w tym przypadku "linia". Powyższy kod po przeczytaniu każdej z linii pliku wyświetli ją na konsoli. Dokumentacja języka mówi, że nie musimy się martwić o to, że podczas odczytu takiego pliku może wystąpić wyjątek. Mechanizmy obsługi plików zadbają o to by został on właściwie obsłużony, a źródło prawidłowo zamknięte.

Często zdarza się, że nie istnieje konieczność przetwarzania kolejnych linii pliku. Wtedy można użyć metod wczytujących do zmiennych tekstowych całą tekstową zawartość pliku. Skrypt dokonujący tej czynności wygląda następująco:

content=new File("source.txt").text
print content

Wczytuje on do zmiennej "content" całą zawartość pliku source.txt, a potem wyświetla ją na ekranie.

W sytuacji, gdy zaistnieje potrzeba odczytu pliku o niestandardowym kodowaniu, wtedy można posłużyć się metodą getText(encoding).

content=new File("source.txt").getText("UTF-8")
print content

Zapis do pliku

W przypadku gdy chcemy jednokrokowo zapisać całą zawartość pliku tekstowego, mamy do dyspozycji metodę:

new File("output.txt").write("hello :)")

W przypadku, gdy zachodzi konieczność obsługi kodowania, można podać je jako dodatkowy parametr metody:

new File("output.txt").write("hello :)", "UTF-8")

Jeżeli chcielibyśmy zapisywać tekst całymi liniami można skorzystać z następującego sposobu:

writer = new File("myText.txt").newWriter("UTF-8", true)
writer.writeLine("pozdrowienia")
writer.close()

Dodatkowy parametr w metodzie pobierającej obiekt Writer decyduje o tym czy plik ma zostać założony lub wyczyszczony(false), czy też treść ma być do niego dopisana(true).


Należy pamiętać że otwarcie pliku do zapisu zakłada nowy plik, lub kasuje jego starą zawartość. Jeżeli zaistnieje konieczność dopisywnia tekstu do istniejącego pliku można skorzystać z metody append():

new File("output.txt").append("hello :) - po raz drugi")

tak samo jak w poprzednich sytuacjach, opcjonalnie można określić kodowanie pliku:

new File("output.txt").append("hello :) - po raz drugi","utf-8")

Obsługa plików binarnych

Sposoby obsługi plików binarnych, oraz inne metody stosowane przy zapisie i odczycie plików szczegółowo omówione zostały pod adresem http://groovy.codehaus.org/Streams,+Readers,+and+Writers

Domknięcia (closures)

Domknięcie jest to mechanizm, który w Groovym jest wyjątkowo często stosowany. Ma postać bloku kodu objętego nawiasami klamrowymi. Posiada on cechy nie tylko obiektu (można go stworzyć, przesyłać do niego referencje), ale też metody(może przyjmować parametry i zwracać wartości).

Najprostszy przykład domknięcia mógłby wyglądać następująco (być może nie jest zbyt finezyjny, ale póki co sam się tego uczę)

myclosure={textToPrint->print textToPrint}
myclosure("Witaj !")


Powyższy skrypt w pierwszej linii definiuje domknięcie o nazwie myclosure, które pobiera jeden parametr o nazwie "textToPrint". Parametr ten umieszcza się po nawiasie klamrowym, a przed znakiem "->". Jego wartość jest dostępna we wnętrzu domknięcia. Powyższy przykład odwołuje się do otrzymanego parametru i wyświetla jego wartość na konsoli.

W przypadku gdy nasze domknięcie pobiera tylko jeden parametr można skorzystać z oferowanej przez Grooviego skróconej formy definicji i odwołania się do domknięcia. Wartość parametru dostępna jest we wnętrzu domknięcia po odwołaniu się do słowa kluczowego "it".

shortClosure={print it}
shortClosure("Hello Mariusz !!!")

Należy pamiętać że kod domknięcia jest wykonywany dopiero przy odwołaniu się do niego.

Możliwe jest też definiowanie domknięć przyjmujących więcej niż jeden parametr. W takim przypadku przed znakiem -> należy umieścić ich listę:

sumArgClosure={arg1,arg2-> print "SUM="+(arg1+arg2)}
sumArgClosure(5,3)

Powyższy skrypt wyświetli na ekranie napis SUM=8

Bardzo ciekawą własnością domknięć jest to, że istnieje możliwość przesyłania do nich referencji. Jako przykład niech posłuży kod klasy Calculator.

public class Calculator{
def argList=[2,3,4]

public void applyOperation(String operation,c){
print "\nWykonywana operacja to:\n***"+operation+"***"

for (elem in argList){
print "\n"+c(elem)
}
print "\n******"
}


}

def calc=new Calculator()
calc.applyOperation("Mnozeniex3"){(it*3)}
calc.applyOperation("Potegowanie"){(it*it)}

W klasie zdefiniowana jest lista argumentów (
argList=[2,3,4]) na której będą wykonywane operacje, oraz jedna metoda, która jako swój parametr przyjmuje domknięcie i tekstową nazwę operacji którą ma wykonać(chociaż znaczenie tego parametru jest mało istotne - wykorzystywane jest tylko do wyświetlenia komentarza). We wnętrzu metody zdefiniowana została pętla która przechodzi po wszystkich elementach listy argumentów, a następnie dla każdego z nich wykonuje domknięcie, przysłane do metody w parametrze :

for (elem in argList){
print "\n"+ c(elem)
}
print "\n******"
}

Wywołanie w.w. metody ma postać:

calc.applyOperation("Mnozeniex3"){(it*3)}
calc.applyOperation("Potegowanie"){(it*it)}

Za każdym razem na argumentach kalkulatora zostanie wywołana operacja zdefiniowana w domknięciu. Należy zwrócić uwagę na pewne udogodnienie, mianowicie definiowanie domknięcia przesyłanego w parametrze może wystąpić poza argumentami funkcji (chociaż notacja tradycyjna, po przecinku też jest dopuszczalna).

Groovy - pierwsze kroki

Jestem przekonany że każdy(w sumie nie wiem czy każdy ale ja na pewno tak :) ), kto choć przez chwilę obcował z systemami linuxowo unixowymi i
doświadczył potężnych możliwości, które drzemią w mechanizmach skryptów powłoki ma trudności z dostosowaniem się do dramatycznej wręcz liczby ograniczeń jakie
w tym zakresie narzuca system Windows. Możliwości jego powłoki są żenująco mizerne. Na szczęście istnieje prosty sposób na uzyskanie potężnej funkjcjonalności.
Lekiem na całe zło może okazać się zastosowanie języków skryptowych, takich jak Ruby,Python czy Groovy.

Ze względu na wspólne korzenie Javy i Grooviego do mój wybór był prosty. Po krótkim już rozeznaniu wiem że okazał się słuszny. Prosta intuicyjna, javopodobna składnia i potężne możliwości - to w mojej subiektywnej ocenie najważniejsze cechy Grooviego, które sprawiają, że czas poświęcony na jego naukę naprawdę nie będzie stracony.

Nie chcę rozwodzić się nad sposobem instalacji, ani cechami podstawowej składni języka - te zagadnienia zostały szczegółowo opisane na stronie Groovy-ego. Chciałbym skupić
się na konkretnych problemach, do których rozwiązania przydały mi się potężne możliwości tego języka.