001package fi.jyu.mit.ohj2;
002import java.io.*;
003import java.util.ArrayList;
004import java.util.Collection;
005import java.util.List;
006import java.net.MalformedURLException;
007import java.net.URL;
008
009/**
010 * <p>Title: Tiedosto</p>
011 * <p>Description: Aliohjelmia tiedostojen käsittelyyn</p>
012 * <p>Copyright: Copyright (c) 2003</p>
013 * <p>Company: jyu </p>
014 * @author Vesa Lappalainen
015 * @version 1.0, 25.02.2003
016 * @version 1.1, 09.03.2002
017 * @version 1.2  12.08.2009 - netistä luku
018 * @version 1.3  06.11.2010 - lue, joka lukee netista tai tiedostosta
019 */
020
021public class Tiedosto {
022
023
024  /**
025   * Avaa tiedoston lukemista varten
026   * @param nimi avattavan tiedoston nimi
027   * @return avattu puskuroitu tiedostolukija tai null jos ei aukea
028   */
029  public static BufferedReader avaa_lukemista_varten(String nimi) { // NOPMD alleviiva ok hist. syistä
030    try {
031      return new BufferedReader(new FileReader(nimi));
032    } catch (FileNotFoundException ex) {
033      return null;
034    }
035  }
036
037
038  /**
039   * Avaa tiedoston kirjoittamista varten.
040   * @param nimi   avattavan tiedoston nimi
041   * @param jatka  jatketaanko edellisen tiedoston perään (true) vai ei (false)
042   * @return       avattu PrintWriter-olio tai null jos ei aukea
043   */
044  public static PrintWriter avaa_kirjoittamista_varten(String nimi,boolean jatka) {  // NOPMD alleviiva ok hist. syistä
045    PrintWriter f = null;
046      try {
047        f = new PrintWriter(new FileWriter(nimi,jatka));
048      } catch (IOException ex) {
049        return null;
050      }
051    return f;
052  }
053
054  /**
055   * Avaa tiedoston kirjoittamista varten.
056   * @param nimi   avattavan tiedoston nimi
057   * @return       avattu PrintWriter-olio tai null jos ei aukea
058   */
059  public static PrintWriter avaa_kirjoittamista_varten(String nimi) {  // NOPMD alleviiva ok hist. syistä
060    return avaa_kirjoittamista_varten(nimi,false);
061  }
062
063
064  /**
065   * Avaa tiedoston kirjoittamista varten.
066   * @param nimi   avattavan tiedoston nimi
067   * @param jatka  jatketaanko edellisen tiedoston perään (true) vai ei (false)
068   * @return       avattu PrintStream-olio tai null jos ei aukea
069   */
070  public static PrintStream avaa_kirjoittamista_varten_stream(String nimi,boolean jatka) {  // NOPMD alleviiva ok hist. syistä
071    PrintStream f = null;
072    try {
073      f = new PrintStream(new FileOutputStream(nimi,jatka));
074    }  catch (FileNotFoundException ex) {
075      return null;
076    }
077    return f;
078  }
079
080  /**
081   * Avaa tiedoston kirjoittamista varten.
082   * @param nimi   avattavan tiedoston nimi
083   * @return       avattu PrintStream-olio tai null jos ei aukea
084   */
085  public static PrintStream avaa_kirjoittamista_varten_stream(String nimi) {  // NOPMD alleviiva ok hist. syistä
086    return avaa_kirjoittamista_varten_stream(nimi,false);
087  }
088
089
090  /**
091   * Luo tarvittaessa uuden PrintStream-virran OutputStream virrasta.
092   * Jos os on valmiiksi PrintStream, niin tehdään vain tyypinmuunnos
093   * @param os virta josta luodaan PrintStream virta
094   * @return os muutettuna PrintStrean-virraksi
095   */
096  public static PrintStream getPrintStream(OutputStream os) {  // NOPMD alleviiva ok hist. syistä
097    return (os instanceof PrintStream)?(PrintStream)os : new PrintStream(os) ;
098  }
099
100
101  /**
102   * Tulostetaan tietovirtaan rivinvaihdolla erotettuna kaikki listan rivit
103   * @param out tietovirta johon tulostetaan
104   * @param rivit tulostettavat rivit
105   */
106  public static void println(PrintStream out, List<String> rivit) {
107      for (String s : rivit)
108          out.println(s);
109  }
110  
111  
112  /**
113   * Tulostetaan tietovirtaan rivinvaihdolla erotettuna kaikki taulukon rivit
114   * @param out tietovirta johon tulostetaan
115   * @param rivit tulostettavat rivit
116   */
117  public static void println(PrintStream out, String[] rivit) {
118      for (String s : rivit)
119          out.println(s);
120  }
121  
122  
123  /**
124   * Tulostetaan tietovirtaan erottimella erotettuna kaikki listan rivit
125   * @param out tietovirta johon tulostetaan
126   * @param rivit tulostettavat rivit
127   * @param erotin jolla rivit erotetaan
128   */
129  public static void print(PrintStream out, List<String> rivit, String erotin) {
130      String vali = "";
131      for (String s : rivit) {
132          out.println(vali+s);
133          vali = erotin;
134      }    
135  }
136  
137  
138  /**
139   * Tulostetaan tietovirtaan erottimella erotettuna kaikki taulukon rivit
140   * @param out tietovirta johon tulostetaan
141   * @param rivit tulostettavat rivit
142   * @param erotin jolla rivit erotetaan
143   */
144  public static void print(PrintWriter out, String[] rivit, String erotin) {
145      String vali = "";
146      for (String s : rivit) {
147          out.println(vali+s);
148          vali = erotin;
149      }    
150  }
151  
152  
153  /**
154   * Tulostetaan tietovirtaan rivinvaihdolla erotettuna kaikki listan rivit
155   * @param out tietovirta johon tulostetaan
156   * @param rivit tulostettavat rivit
157   */
158  public static void println(PrintWriter out, List<String> rivit) {
159      for (String s : rivit)
160          out.println(s);
161  }
162  
163  
164  /**
165   * Tulostetaan tietovirtaan rivinvaihdolla erotettuna kaikki taulukon rivit
166   * @param out tietovirta johon tulostetaan
167   * @param rivit tulostettavat rivit
168   */
169  public static void println(PrintWriter out, String[] rivit) {
170      for (String s : rivit)
171          out.println(s);
172  }
173  
174  
175  /**
176   * Tulostetaan tietovirtaan erottimella erotettuna kaikki listan rivit
177   * @param out tietovirta johon tulostetaan
178   * @param rivit tulostettavat rivit
179   * @param erotin jolla rivit erotetaan
180   */
181  public static void print(PrintWriter out, List<String> rivit, String erotin) {
182      String vali = "";
183      for (String s : rivit) {
184          out.println(vali+s);
185          vali = erotin;
186      }    
187  }
188  
189  
190  /**
191   * Tulostetaan tietovirtaan erottimella erotettuna kaikki taulukon rivit
192   * @param out tietovirta johon tulostetaan
193   * @param rivit tulostettavat rivit
194   * @param erotin jolla rivit erotetaan
195   */
196  public static void print(PrintStream out, String[] rivit, String erotin) {
197      String vali = "";
198      for (String s : rivit) {
199          out.println(vali+s);
200          vali = erotin;
201      }    
202  }
203  
204  
205  /**
206   * Funktiolla luetaan tekstitiedosto ja palautetaan se merkkijonolistana
207   * Ei saa käyttää isojen tiedostojen käsittelyyn! 
208   * @param f avattu luettava tietovirta
209   * @param rivit lista johon tiedoston rivit lisätään. 
210   * @return null jos tiedostoa ei saa luettua, muuten tiedoston sisältö
211   */
212  public static Collection<String> lueTiedosto(BufferedReader f, Collection<String> rivit) {
213    if ( f == null ) return null;
214    
215    String rivi;
216    
217    try {
218        while ( ( rivi = f.readLine() ) != null ) {
219            rivit.add(rivi);            
220        }
221    } catch (IOException e) {
222        return null;
223    } finally {
224        try {
225            f.close();
226        } catch (IOException e) {
227            return null;  // NOPMD
228        }        
229    }
230    return rivit;
231  }
232  
233  
234  /**
235   * Funktiolla luetaan tekstitiedosto ja palautetaan se merkkijonolistana
236   * Ei saa käyttää isojen tiedostojen käsittelyyn! 
237   * @param nimi luettavan tiedoston nimi
238   * @param rivit lista johon tiedoston rivit lisätään. 
239   * @return null jos tiedostoa ei saa luettua, muuten tiedoston sisältö
240   */
241  @SuppressWarnings("resource") // lueTiedosto sulkee
242  public static Collection<String> lueTiedosto(String nimi, Collection<String> rivit) {
243      BufferedReader f = avaa_lukemista_varten(nimi);
244      return lueTiedosto(f, rivit);
245  }
246  
247  
248  /**
249   * Funktiolla luetaan tekstitiedosto ja palautetaan se merkkijonolistana
250   * Ei saa käyttää isojen tiedostojen käsittelyyn! 
251   * @param nimi luettavan tiedoston nimi
252   * @return null jos tiedostoa ei saa luettua, muuten tiedoston sisältö
253   */
254  public static List<String> lueTiedostoListaan(String nimi) {
255    ArrayList<String> rivit = new ArrayList<String>();
256    return (List<String>)lueTiedosto(nimi, rivit);
257  }
258  
259
260  /**
261   * Funktiolla muutetaan tietorakenne merkkijonotaulukoksi
262   * Ei saa käyttää isojen tiedostojen käsittelyyn! 
263   * @param rivit muutettava tietorakenne
264   * @return null jos rakenne on null, muuten rakenteen sisältö
265   */
266  public static String[] toArray(Collection<String> rivit) {
267          if ( rivit == null ) return null;
268          String [] tulosrivit = new String[rivit.size()];
269          int i=0;
270          for (String rivi:rivit) tulosrivit[i++] = rivi;
271          return tulosrivit;
272  }
273  
274  
275  /**
276   * Funktiolla luetaan tekstitiedosto ja palautetaan se merkkijonotaulukkona.
277   * Ei saa käyttää isojen tiedostojen käsittelyyn! 
278   * @param nimi luettavan tiedoston nimi
279   * @return null jos tiedostoa ei saa luettua, muuten tiedoston sisältö
280   */
281  public static String[] lueTiedosto(String nimi) {
282      List<String> rivit = lueTiedostoListaan(nimi);
283      return toArray(rivit);
284  }
285  
286
287  /**
288   * Funktiolla luetaan nettisivun sisältö ja palautetaan se merkkijonolistana
289   * Ei saa käyttää isojen tiedostojen käsittelyyn! 
290   * @param url luettavan tiedoston nimi
291   * @param rivit lista johon sivun rivit lisätään. 
292   * @return null jos sivua ei saa luettua, muuten sivun sisältö
293   */
294  @SuppressWarnings("resource") // lueTiedosto sulkee
295  public static Collection<String> lueNetista(String url, Collection<String> rivit) {
296      try {
297                URL sivu = new URL(url);
298                  InputStream in = sivu.openStream();
299                  Reader reader = new InputStreamReader(in);
300                  BufferedReader f = new BufferedReader(reader);
301                  return lueTiedosto(f,rivit);
302        } catch (MalformedURLException e) {
303                return null;
304        } catch (IOException e) {
305                // TODO Auto-generated catch block
306                return null;
307        }
308  }
309  
310  
311  /**
312   * Funktiolla luetaan nettisivun sisältö ja palautetaan se merkkijonolistana
313   * Ei saa käyttää isojen tiedostojen käsittelyyn! 
314   * @param url luettavan tiedoston nimi
315   * @return null jos sivua ei saa luettua, muuten sivun sisältö
316   */
317  public static List<String> lueNetistaListaan(String url) {
318          List<String> rivit = new ArrayList<String>();
319          return (List<String>)lueNetista(url, rivit);
320  }
321  
322  
323  /**
324   * Funktiolla luetaan nettisivun sisältö ja palautetaan se merkkijonotaulukkona
325   * Ei saa käyttää isojen tiedostojen käsittelyyn! 
326   * @param url luettavan tiedoston nimi
327   * @return null jos sivua ei saa luettua, muuten sivun sisältö
328   */
329  public static String[] lueNetista(String url) {
330      List<String> rivit = lueNetistaListaan(url);
331      return toArray(rivit);
332  }
333
334  
335  /**
336   * Palauttaa onko nimi URL vai tavallinen tiedoston nimi
337   * @param nimi tutkittava nimi
338   * @return true jos URL, muuten false
339   * @example
340   * <pre name="test">
341   *   onkoURL("kissa.txt") === false;
342   *   onkoURL("http://i.jyu.fi") === true;
343   *   onkoURL("https://i.jyu.fi") === true;
344   *   onkoURL("httpko.txt") === false;
345   * </pre>
346   */
347  public static boolean onkoURL(String nimi) {
348      if ( nimi.startsWith("http:") ) return true;
349      if ( nimi.startsWith("https:") ) return true;
350      return false;
351  }
352  
353  
354  /**
355   * Lukee tiedosta tai netistä jos nimi alkaa http
356   * @param nimi tiedoston nimi tai URL
357   * @return taulukko luetuista merkkijonoista
358   */
359  public static String[] lue(String nimi) {
360     if ( onkoURL(nimi) )  return lueNetista(nimi);
361     return lueTiedosto(nimi);
362  }
363  
364  
365  /**
366   * Lukee tiedosta tai netistä jos nimi alkaa http
367   * @param nimi tiedoston nimi tai URL
368   * @return lista luetuista merkkijonoista
369   */
370  public static List<String> lueListaan(String nimi) {
371     if ( onkoURL(nimi) )  return lueNetistaListaan(nimi);
372     return lueTiedostoListaan(nimi);
373  }
374  
375  
376  /**
377   * Kirjoitetaan merkkijonotaulukko tiedostoon.
378   * @param nimi tiedoston nimi
379   * @param rivit kirjoitettavat rivit
380   * @param jatka jatketaanko vanhan tiedoston perään (true) vai ei (false) 
381   * @return false jos ei onnistu ja true jos onnistuu
382   */
383  public static boolean kirjoitaTiedosto(String nimi, String rivit[], boolean jatka) {
384      @SuppressWarnings("resource") // suljetaan finalyssä
385      PrintWriter f = avaa_kirjoittamista_varten(nimi, jatka);
386      if ( f == null ) return false;
387      try {
388          for (String rivi : rivit)
389              f.println(rivi);
390      } finally {  
391          f.close();
392      }  
393      return true;   
394  }
395  
396  
397  /**
398   * Kirjoitetaan merkkijonotaulukko tiedostoon.
399   * @param nimi tiedoston nimi
400   * @param rivit kirjoitettavat rivit
401   * @return false jos ei onnistu ja true jos onnistuu
402   */
403  public static boolean kirjoitaTiedosto(String nimi, String rivit[]) {
404      return kirjoitaTiedosto(nimi, rivit, false);
405  }
406  
407  
408  /**
409   * Kirjoitetaan merkkijonolista tiedostoon.
410   * @param nimi tiedoston nimi
411   * @param rivit kirjoitettavat rivit
412   * @param jatka jatketaanko vanhan tiedoston perään (true) vai ei (false) 
413   * @return false jos ei onnistu ja true jos onnistuu
414   */
415  public static boolean kirjoitaTiedosto(String nimi, Iterable<String> rivit, boolean jatka) {
416      @SuppressWarnings("resource") // suljetaan finalyssä
417      PrintWriter f = avaa_kirjoittamista_varten(nimi, jatka);
418      if ( f == null ) return false;
419      try {
420          for (String rivi : rivit)
421              f.println(rivi);
422      } finally {  
423          f.close();
424      }  
425      return true;   
426  }
427  
428  
429  /**
430   * Kirjoitetaan merkkijonolista tiedostoon.
431   * @param nimi tiedoston nimi
432   * @param rivit kirjoitettavat rivit
433   * @return false jos ei onnistu ja true jos onnistuu
434   */
435  public static boolean kirjoitaTiedosto(String nimi, Iterable<String> rivit) {
436      return kirjoitaTiedosto(nimi, rivit, false);
437  }
438  
439}