Program napisany na szybko z lenistwa. Przechodzi rekurencyjnie przez katalogi i wypisuje do pliku tekstowego pliki o podanych rozszerzeniach (lub wszystkie jeśli nie podano rozszerzeń).
Jeśli pojawią się problemy ze znakiem końca linii trzeba podać jako argument jaki znak ma być użyty. Dla unix'a to będzie LF, dla windowsa CRLF a dla mac'a CR. standardowo użyty jest LF.
Czyli na przykład:
java -jar Listowanie.jar CRLF
Pobierz
Program testowany tylko na Win7 x64.
sobota, 22 października 2011
środa, 31 sierpnia 2011
Dziennik Ustaw v0.1
Wstępna wersja aplikacji pobierającej informacje o najnowszych numerach dziennika ustaw. Wyświetla numery i daty wydania ostatnich 10 numerów dziennika ustaw. Informacje aktualizowane są co 5 minut.
DOWNLOAD
Wymagana Java 7
DOWNLOAD
Wymagana Java 7
Zabawa z regexem - wyrażenia regularne
Śledzę czasem Dziennik Ustaw czekając na interesujące mnie rozporządzenie. Jednak Rządowe Centrum Legislacji nie udostępnia kanału RSS (przynajmniej o takowym nie wiem).
Prostym rozwiązaniem tego problemu jest napisanie aplikacji co kilka minut sprawdzającej czy nie pojawił się nowy DU. Do tego celu użyjemy Regex'a czyli wyrażeń regularnych.
Obsługa wyrażeń regularnych w javie składa się z klas Pattern oraz Matcher. Klasa Pattern, metodą static Pattern compile(String regex), tworzy wzorzec na podstawie podanego w argumencie wyrażenia regularnego. Instancję klasy Matcher tworzymy przy użyciu metody klasy Pattern Matcher matcher(CharSequence input).
Następnie używamy metod boolean find() oraz String group() klasy Matcher aby, odpowiednio, odnaleźć następną pasującą subsekwencję oraz uzyskać ją w formie String'a.
Na przykładzie strony http://www.dziennikustaw.gov.pl/ wypisujemy na ekran numery oraz daty ukazania się ostatnich 10 numerów dziennka ustaw.
EDIT: Poprawione, wydobywanie danych przy użyciu group() zamiast replaceAll().
Prostym rozwiązaniem tego problemu jest napisanie aplikacji co kilka minut sprawdzającej czy nie pojawił się nowy DU. Do tego celu użyjemy Regex'a czyli wyrażeń regularnych.
Obsługa wyrażeń regularnych w javie składa się z klas Pattern oraz Matcher. Klasa Pattern, metodą static Pattern compile(String regex), tworzy wzorzec na podstawie podanego w argumencie wyrażenia regularnego. Instancję klasy Matcher tworzymy przy użyciu metody klasy Pattern Matcher matcher(CharSequence input).
Następnie używamy metod boolean find() oraz String group() klasy Matcher aby, odpowiednio, odnaleźć następną pasującą subsekwencję oraz uzyskać ją w formie String'a.
Na przykładzie strony http://www.dziennikustaw.gov.pl/ wypisujemy na ekran numery oraz daty ukazania się ostatnich 10 numerów dziennka ustaw.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { public static void main(String[] args) throws MalformedURLException, IOException { /* POBRANIE ŹRÓDŁA STRONY*/ URL url = new URL("http://dziennikustaw.gov.pl/"); BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream())); StringBuilder buff = new StringBuilder(); String line; while((line = in.readLine())!=null) { buff.append(line); buff.append("\n"); } String str = buff.toString(); in.close(); /* PARSOWANIE ŹRÓDŁA */ Pattern pattNumer = Pattern.compile("<td class=\"c\">([0-9]{1,3})</td>"); Matcher matchNumer = pattNumer.matcher(str); Pattern pattData = Pattern.compile("<td class=\"c\">([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}:[0-9]{2}:[0-9]{2})<br />"); //br bez spacji Matcher matchData = pattData.matcher(str); int i=0; while(matchNumer.find() && matchData.find() && i<10) { System.out.println(matchNumer.group(1)+" "+matchData.group(1)+" "+matchData.group(2)); i++; } } }W wyniku działania programu otrzymamy:
run: 179 2011-08-30 16:56:35 178 2011-08-29 18:44:54 177 2011-08-26 19:57:05 176 2011-08-26 19:43:00 175 2011-08-25 18:21:44 174 2011-08-23 17:42:06 173 2011-08-22 17:21:39 172 2011-08-19 17:10:41 171 2011-08-18 18:36:57 170 2011-08-18 18:31:47 BUILD SUCCESSFUL (total time: 0 seconds)A więc mamy wszystkie potrzebne dane. Jest to dobry zalążek do pisania większej aplikacji.
EDIT: Poprawione, wydobywanie danych przy użyciu group() zamiast replaceAll().
czwartek, 7 lipca 2011
MySQL - Połączenie JAVA (JDBC) i PHP (mysqli)
Połączenie z bazą MySQL przy użyciu JDBC (java) i mysqli (php). Oba programy wypisują na standardowe wyjście ciąg "Hello World" po wcześniejszym zapisaniu go i odczytaniu z bazy danych.
JAVA
PHP
JAVA
import java.sql.Statement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; public class Main { public static void main(String[] args) { try { Connection sql = DriverManager.getConnection("jdbc:mysql://localhost:3306", "user", "pass"); //ustanowienie połączenia Statement stat = sql.createStatement(); //utworzenie obiektu statement stat.execute("USE db"); //wybór bazy stat.execute("INSERT INTO someTable (txt) VALUES ('Hello World')"); //dodanie rekordu do tabeli ResultSet rs = stat.executeQuery("SELECT * FROM someTable"); //pobranie danych z bazy rs.first(); System.out.println(rs.getString("txt")); //wypisanie rekordu na standardowe wyjście stat.execute("DELETE FROM someTable"); //usunięcie danych z tabeli stat.close(); //zamknięcie strumieni sql.close(); } catch(Exception e) { e.printStackTrace(); } } }
PHP
wtorek, 21 czerwca 2011
Socket - Połączenie klient-serwer
Dzisiaj zajmiemy się połączeniem pomiędzy klientem i serwerem przy użyciu klasy Socket. Klasa Socket pozwala na połączenie sieciowe na podanym porcie pomiędzy dwoma maszynami.
Socket (Java Platform SE 6)
Krótko o działaniu aplikacji. Po uruchomieniu serwer oczekuje na połączenie. Po połączeniu serwer wysyła do klienta komunikat "Ping" i oczekuje na odpowiedź. Jeśli klient odpowie "Pong" to serwer po 5 sekundach ponownie wysyła "Ping". W przypadku otrzymania złej odpowiedzi serwer się wyłącza.
Klient sprawdza nadchodzące komunikaty, jeśli otrzyma "Ping" to odpowiada "Pong". Dla celów testowych klient po 30 sekundach działania wyśle komunikat "Pon g" zamiast "Pong" i się wyłączy.
Linijki potrzebne do działania po stronie serwera:
Linijki potrzebne do działania po stronie klienta:
Kod źródłowy:
Output serwera:
Output klienta:
Socket (Java Platform SE 6)
Krótko o działaniu aplikacji. Po uruchomieniu serwer oczekuje na połączenie. Po połączeniu serwer wysyła do klienta komunikat "Ping" i oczekuje na odpowiedź. Jeśli klient odpowie "Pong" to serwer po 5 sekundach ponownie wysyła "Ping". W przypadku otrzymania złej odpowiedzi serwer się wyłącza.
Klient sprawdza nadchodzące komunikaty, jeśli otrzyma "Ping" to odpowiada "Pong". Dla celów testowych klient po 30 sekundach działania wyśle komunikat "Pon g" zamiast "Pong" i się wyłączy.
Linijki potrzebne do działania po stronie serwera:
/*Utworzenie na podanym porcie socketa serwera.*/ ServerSocket serverSocket = new ServerSocket(PORT); /*Oczekiwanie na połączenie i zaakceptowanie*/ Socket clientSocket = serverSocket.accept(); /*Utworzenie strumieni wejściowego i wyjściowego*/ PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),true); BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); /*Wysłanie komunikatu*/ out.println(KOMUNIKAT); /*Oczekiwanie i odebranie komunikatu*/ String input = in.readLine(); /*Zamknięcie strumieniu i socketów*/ out.close(); in.close(); clientSocket.close(); serverSocket.close();
Linijki potrzebne do działania po stronie klienta:
/*Połączenie z serwerem*/ Socket socket = new Socket(HOST, PORT); /*Reszta analogicznie jak w serwerze*/
Kod źródłowy:
/* Server.java */ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; public class Server { private static final int PORT = 50000; static boolean flaga = true; private static ServerSocket serverSocket; private static Socket clientSocket; public static void main(String[] args) throws IOException { serverSocket = null; try { serverSocket = new ServerSocket(PORT); } catch(IOException e) { System.err.println("Could not listen on port: "+PORT); System.exit(1); } System.out.print("Wating for connection..."); Thread t = new Thread(new Runnable() { public void run() { try { while(flaga) { System.out.print("."); Thread.sleep(1000); } } catch(InterruptedException ie) { // } System.out.println("\nClient connected on port "+PORT); } }); t.start(); clientSocket = null; try { clientSocket = serverSocket.accept(); flaga = false; } catch(IOException e) { System.err.println("Accept failed."); t.interrupt(); System.exit(1); } final PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),true); final BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); t = new Thread(new Runnable() { public void run() { try { Thread.sleep(5000); while(true) { out.println("Ping"); System.out.println(System.currentTimeMillis()+" Ping sent"); String input = in.readLine(); if(input.equals("Pong")) { System.out.println(System.currentTimeMillis()+" Pong received"); } else { System.out.println(System.currentTimeMillis()+" Wrong answer"); out.close(); in.close(); clientSocket.close(); serverSocket.close(); break; } Thread.sleep(5000); } } catch(Exception e) { System.err.println(System.currentTimeMillis()+" Unexpected Error"); } } }); t.start(); } }
/* Client.java */ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; public class Client { private static final int PORT = 50000; private static final String HOST = "localhost"; public static void main(String[] args) throws IOException { Socket socket = null; try { socket = new Socket(HOST, PORT); } catch(Exception e) { System.err.println("Could not connect to "+HOST+":"+PORT); System.exit(1); } final PrintWriter out = new PrintWriter(socket.getOutputStream(),true); final BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); Thread t = new Thread(new Runnable() { public void run() { long start = System.currentTimeMillis(); while (true) { try { String input = in.readLine(); if (input != null) { System.out.println(System.currentTimeMillis() + " Server: " + input); } if (input.equals("Ping")) { if(System.currentTimeMillis()-start>30000) { out.println("Pon g"); System.out.println(System.currentTimeMillis() + " Client: Pon g"); break; } out.println("Pong"); System.out.println(System.currentTimeMillis() + " Client: Pong"); } } catch (IOException ioe) { // } } } }); t.start(); out.close(); in.close(); socket.close(); } }
Output serwera:
Wating for connection.......... Client connected on port 50000 1308645130778 Ping sent 1308645130779 Pong received 1308645135779 Ping sent 1308645135779 Pong received 1308645140780 Ping sent 1308645140780 Pong received 1308645145780 Ping sent 1308645145780 Pong received 1308645150780 Ping sent 1308645150780 Pong received 1308645155781 Ping sent 1308645155781 Wrong answer
Output klienta:
1308645130778 Server: Ping 1308645130779 Client: Pong 1308645135779 Server: Ping 1308645135779 Client: Pong 1308645140780 Server: Ping 1308645140780 Client: Pong 1308645145780 Server: Ping 1308645145780 Client: Pong 1308645150780 Server: Ping 1308645150780 Client: Pong 1308645155781 Server: Ping 1308645155781 Client: Pon g
niedziela, 5 czerwca 2011
db4o - Prosta baza danych dla aplikacji java!
Ostatnio zastanawiałem się jak przechowywać dane pomiędzy uruchomieniami aplikacji. Szukając rozwiązań w internecie trafiłem na db4objects http://db4o.com/.
db4o jest bazą embedded przechowującą całe obiekty. Całość działa szybko i jest bardzo prosta w implementacji.
Potrzebne biblioteki pobieramy z tej strony:
http://db4o.com/DownloadNow.aspx -> db4o 8.0 for Java (zip, 40.9 mb).
Rejestracja jest opcjonalna.
Wg pliku \db4o-8.0-java\db4o-8.0\lib\readme.html wystarczy nam biblioteka db4o-8.0.184.15484-core-java5.jar ale do projektu dodajemy również db4o-8.0.184.15484-cs-java5.jar ponieważ wg API (dołączone do paczki) potrzebna nam metoda w klasie Db4o jest zdeprecjonowana.
Oto krótki przykład zastosowania:
Wynik 3-krotnego uruchomienia aplikacji, widać że dane są zachowywane:
Jak widać potrzebne obsługa bazy jest banalnie prosta, potrzebne linie to:
Metoda openServer() w razie potrzeby utworzy nowy serwer pod podaną nazwą, a jeśli chcemy aby był to serwer TCP zamiast 0 podajemy numer portu pod jakim ma działać.
Pokazane tutaj zastosowanie jest najprostszym z możliwych ale baza ta jest o wiele bardziej rozbudowana.
db4o jest bazą embedded przechowującą całe obiekty. Całość działa szybko i jest bardzo prosta w implementacji.
Potrzebne biblioteki pobieramy z tej strony:
http://db4o.com/DownloadNow.aspx -> db4o 8.0 for Java (zip, 40.9 mb).
Rejestracja jest opcjonalna.
Wg pliku \db4o-8.0-java\db4o-8.0\lib\readme.html wystarczy nam biblioteka db4o-8.0.184.15484-core-java5.jar ale do projektu dodajemy również db4o-8.0.184.15484-cs-java5.jar ponieważ wg API (dołączone do paczki) potrzebna nam metoda w klasie Db4o jest zdeprecjonowana.
Oto krótki przykład zastosowania:
/* Main.java */ import com.db4o.ObjectContainer; import com.db4o.ObjectServer; import com.db4o.cs.Db4oClientServer; import com.db4o.query.Predicate; import java.util.List; public class Main { static ObjectServer os; public static void main(String[] args) { os = Db4oClientServer.openServer("TestDB", 0); saveToDB(); loadFromDB(); os.close(); } public static void saveToDB() { ObjectContainer oc = os.openClient(); oc.store(new SomeObject()); oc.close(); } public static void loadFromDB() { ObjectContainer oc = os.openClient(); Listlist = oc.query(new Predicate () { public boolean match(SomeObject so) { return so.getClass().getName().equals("SomeObject"); } }); for(SomeObject so : list) { System.out.println(so.x+" "+so.y); } oc.close(); } }
/* SomeObject.java */ import java.util.Random; public class SomeObject { public int x; public int y; public SomeObject() { Random r = new Random(); x = r.nextInt(10); y = r.nextInt(100); } }
Wynik 3-krotnego uruchomienia aplikacji, widać że dane są zachowywane:
run: 6 58 3 42 6 22 BUILD SUCCESSFUL (total time: 1 second)
Jak widać potrzebne obsługa bazy jest banalnie prosta, potrzebne linie to:
ObjectServer os = Db4oClientServer.openServer("TestDB", 0); //otworzenie serwera ObjectContainer oc = os.openClient(); //otworzenie klienta oc.store(new SomeObject()); //zapisanie obiektu do bazy //pobranie obiektów SomeObject z bazy Listlist = oc.query(new Predicate () { public boolean match(SomeObject so) { return so.getClass().getName().equals("SomeObject"); } }); oc.close(); //zamknięcie klienta os.close(); //zamknięcie serwera
Metoda openServer() w razie potrzeby utworzy nowy serwer pod podaną nazwą, a jeśli chcemy aby był to serwer TCP zamiast 0 podajemy numer portu pod jakim ma działać.
Pokazane tutaj zastosowanie jest najprostszym z możliwych ale baza ta jest o wiele bardziej rozbudowana.
sobota, 28 maja 2011
Java - Po prostu wątki
Często pisząc aplikację natrafiamy na sytuację w której chcemy wykonać dwie (albo i więcej) rzeczy jednocześnie. Na przykład, chcemy jednocześnie rysować JPanel, obliczać w czasie rzeczywistym nowe dane do wyświetlenia i dodatkowo obsługiwać zdarzenia użytkownika.
Dzisiaj napiszemy prostą aplikacje z zastosowaniem wielowątkowości.
Na początek przygotujmy okno z panelem i przyciskiem. Panel będzie wyświetlał koło wielkości 10x10px o środku w miejscu wskazywanym przez zmienną location. Po naciśnięciu przycisku koło będzie zmieniało kolor.
Dzisiaj napiszemy prostą aplikacje z zastosowaniem wielowątkowości.
Na początek przygotujmy okno z panelem i przyciskiem. Panel będzie wyświetlał koło wielkości 10x10px o środku w miejscu wskazywanym przez zmienną location. Po naciśnięciu przycisku koło będzie zmieniało kolor.
/* Main.java */ public class Main { public static void main(String[] args) { Frame f = new Frame("Java - Multithreading"); f.budujOkno(); } }
/* Frame.java */ import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.border.LineBorder; public class Frame extends JFrame { JButton button; Panel p; public final static int X = 400; public final static int Y = 400; public Frame(String title) { super(title); } public void budujOkno() { addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); setSize(435,487); setLayout(null); setVisible(true); button = new JButton("Przycisk"); button.setLocation(100,420); button.setSize(200,20); button.setVisible(true); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { p.changeColor(); } }); add(button); p = new Panel(); p.setLocation(10,10); p.setSize(X,Y); p.setVisible(true); p.setBorder(new LineBorder(Color.BLACK)); p.setBackground(Color.white); add(p); } }
/* Panel.java */ import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import javax.swing.JPanel; public class Panel extends JPanel { public int[] location = null; private int color = 0; private Color[] colors = {Color.red, Color.yellow, Color.blue, Color.green}; public Panel() { super(null); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D)g; if(location != null) { g2d.setColor(colors[color]); g2d.fillOval(location[0]-5, location[1]-5, 10, 10); g2d.setColor(Color.black); g2d.drawOval(location[0]-5, location[1]-5, 10, 10); } } public void changeColor() { if(color+1 < colors.length) color++; else color = 0; } public void setLoc(int x, int y) { if(location == null) location = new int[2]; location[0] = x; location[1] = y; } }Wszystko ok, program się uruchamia, ale jest coś nie tak. Koło się nie wyświetla bo zmienna location jest null'em. Trzeba obliczyć pozycję koła. Do tego celu użyjemy pierwszego dziś wątku. Tworzymy klasę anonimową implementującą interface Runnable. Chcemy aby obliczenia wykonywały się do zamknięcia programu więc w metodzie run znajdzie się nieskończona pętla. Do klasy Frame dodajemy import klasy Random potrzebnej do wylosowania pozycji początkowej, zmienną dla wątku obliczającego, przerwanie wątku w przypadku zamknięcia aplikacji oraz utworzenie nowego wątku.
/* Frame.java */ import java.util.Random; ... Thread obliczenia; ... if(obliczenia != null) obliczenia.interrupt(); ... obliczenia = new Thread(new Runnable() { public void run() { int kX = 1; int kY = 1; int x = (new Random().nextInt((Frame.X - 10) / 10) + 10) * 10; int y = (new Random().nextInt((Frame.Y - 10) / 10) + 10) * 10; try { while (true) { if (kX * 10 + x >= Frame.X) { x = Frame.X; kX *= -1; } else if(kX*10 + x <= 0) { x = 0; kX *= -1; } else { x = kX * 10 + x; } if (kY * 10 + y >= Frame.Y) { y = Frame.Y; kY *= -1; } else if(kY*10 + y <= 0) { y = 0; kY *= -1; } else { y = kY * 10 + y; } p.setLoc(x, y); Thread.sleep(10); } } catch (InterruptedException e) { e.printStackTrace(); } } }); obliczenia.start(); ...W tej chwili pozycja jest już obliczana 100 razy na sekundę, natomiast nadal się nie wyświetla. Z tego powodu potrzebny jest wątek odświeżający panel, powiedzmy, 50 razy na sekundę. Ponownie wykorzystamy do tego celu klasę anonimową. Oto ostateczna wygląd klasy Frame:
/* Frame.java */ import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Random; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.border.LineBorder; public class Frame extends JFrame { JButton button; Panel p; public final static int X = 400; public final static int Y = 400; Thread obliczenia; Thread obraz; public Frame(String title) { super(title); } public void budujOkno() { addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { if(obliczenia != null) obliczenia.interrupt(); if(obraz != null) obraz.interrupt(); System.exit(0); } }); setSize(435,487); setLayout(null); setVisible(true); button = new JButton("Przycisk"); button.setLocation(100,420); button.setSize(200,20); button.setVisible(true); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { p.changeColor(); } }); add(button); p = new Panel(); p.setLocation(10,10); p.setSize(X,Y); p.setVisible(true); p.setBorder(new LineBorder(Color.BLACK)); p.setBackground(Color.white); add(p); obliczenia = new Thread(new Runnable() { @Override public void run() { int kX = 1; int kY = 1; int x = (new Random().nextInt((Frame.X - 10) / 10) + 10) * 10; int y = (new Random().nextInt((Frame.Y - 10) / 10) + 10) * 10; try { while (true) { if (kX * 10 + x >= Frame.X) { x = Frame.X; kX *= -1; } else if(kX*10 + x <= 0) { x = 0; kX *= -1; } else { x = kX * 10 + x; } if (kY * 10 + y >= Frame.Y) { y = Frame.Y; kY *= -1; } else if(kY*10 + y <= 0) { y = 0; kY *= -1; } else { y = kY * 10 + y; } p.setLoc(x, y); Thread.sleep(10); } } catch (InterruptedException e) { // } } }); obliczenia.start(); obraz = new Thread(new Runnable() { @Override public void run() { try { while(true) { p.repaint(); Thread.sleep(20); } } catch(InterruptedException e) { // } } }); obraz.start(); } }A oto efekt końcowy:
Subskrybuj:
Posty (Atom)