Olio-ohjelmointi 2016 Tiedostot ja tietovirrat
Tietovirrat n Pysyvä tieto voi olla tiedostossa tai se voidaan hakea vaikka tietoverkon kautta n Yhteys tiedostoon tai verkkoon näkyy tietovirtana n Tietovirta täytyy avata ennen käyttöä n Käytön jälkeen tietovirta täytyy sulkea n Jos sulkeminen jää tekemättä, jää resurssi ohjelman käyttöön Käytä resurssit sulkevaa try-lausetta Javalla 2
Tietovirrat n Tiedot esitetään tavuina Kuvat, musiikki jne. Käsittelyyn tavuvirtoja (byte streams) n Tekstimuotoisen tavuvirran käsittelyyn tekstivirtoja (character streams) Automaattinen muunnos tekstiksi Helpottaa tekstin lukemista/kirjoittamista Javalla 3
Tekstimuotoinen tietovirta n Tekstivirtojen käsittelyyn valmiita luokkia FileReader, tekstin luku FileWriter, tekstin kirjoittaminen n Tekstitiedostoon kirjoittaminen n Puskuroitu kirjoittaminen Muistista varataan tilaa puskurialueelle, jonne kirjoittaminen ensin tapahtuu BufferedWriter-luokka Puskurin sisältö kirjoitetaan tiedostoon isompina palasina Javalla 4
Tekstimuotoinen tietovirta n FileWriter-luokka käyttää järjestelmän oletusmerkistöä merkkien muuntamiseksi tavuiksi n Tietovirran avaaminen kirjoitustilaan try ( BufferedWriter outfile = new BufferedWriter( new FileWriter("tekst1.txt"))){ //tekstin kirjoittaminen tiedostoon }catch( IOException ioe ){ System.out.println("Virhe tiedoston käsittelyssä"); } Javalla 5
Tekstimuotoinen tietovirta n Tiedosto tekst1.txt avataan oletushakemistoon n FileWriter- konstruktorille voi antaa tiedoston lisäksi parameteina Avataanko tiedosto lisäystilaan vai luodaanko aina uusi tiedosto new FileWriter( String filename, boolean append); Jos tiedostoa filename ei ole olemassa, niin se luodaan Javalla 6
Tiedostoon kirjoittaminen n n Jos tiedosto filename on olemassa, niin se joko hävitetään ja tehdään uusi samannimien tyhjä tiedosto tai tiedot lisätään jo olemassa olevaan tiedostoon (append = true) new FileWriter( File file ) tai n new FileWriter( File file, boolean append) n File on tiedostoa kuvaava olio n Tietovirtojen käsittelyssä saattaa syntyä IOExceptionpoikkeustilanne Javalla 7
Tiedostoon kirjoittaminen n Luokan File avulla saa tietoa tiedostoista ja hakemistoista String tiedostonnimi = "testi.txt"; File folio = new File( tiedostonnimi ); String polku = "c:\\javaohjelmat\\demot"; File tiedpolku = new File ( polku ); String polku = "c:\\javaohjelmat\\demot"; String tied = "tietoa.dat"; File tied_nimi2 = new File ( polku, tied ); n Voidaan esimerkiksi varmistaa onko tarvittava tiedosto olemassa
Tiedostoon kirjoittaminen n File-luokan metodeja boolean canread() boolean canwrite() boolean exists() boolean isfile() boolean isdirectory() String getabsolutepath() String getname() long length() long lastmodified() String [] list()
Tiedostoon kirjoittaminen n Tietovirtaan kirjoitetaan metodeilla write append try ( BufferedWriter outfile = new BufferedWriter( new FileWriter("tekst1.txt"))){ System.out.print("Anna tekstia > "); String mjono = sc.nextline(); outfile.write( mjono ); }catch( IOException ioe ){ System.out.println("Virhe tiedoston käsittelyssä"); } Javalla 10
Tiedostoon kirjoittaminen n Puskurin voi pakottaa kirjoittamaan puskurin sisällön tietovirtaan flush-komennolla n Tiedot lähetetään eteenpäin eikä tietovirtaa tarvitse sulkea n Ilman flush-komentoa osa puskurin sisällöstä lisätään virtaan vasta kun virta suljetaan n Turha flush-metodin käyttö vie puskuroinnin edut n BufferedWriter-luokan metodilla newline voi kirjoittaa järjestelmäkohtaisen rivinvaihtomerkin \n Unix, Linux, OsX (ASCII 10) \r\n Windows (ASCII 13 ASCII 10) Javalla 11
Tiedostoon kirjoittaminen System.out.print("Anna tekstia > "); String mjono = sc.nextline(); outfile.write( mjono ); outfile.newline(); System.out.print("Anna tekstia > "); mjono = sc.nextline(); outfile.write( mjono ); outfile.newline(); n Jos pitää käyttää tiettyä rivinvaihtomerkkiä, voi järjestelmältä kysyä käytettävän rivinvaihtomerkin System.out.println("OsX:n rivinvaihtomerkki on: " + (int)system.lineseparator().charat(0)); Javalla 12
Tiedostoon kirjoittaminen n FileWriter muuntaa merkit tavuiksi käyttäen järjestelmän oletusmerkistöä n OutputStreamWriter muuntaa tekstivirran tavuiksi annetun merkistön sääntöjen mukaisesti n Kaikki virtuaalikoneet tukevat ainakin seuraavia merkistöjä Koodi US-ASCII ISO-8859-1 UTF-8 UTF-16 UTF-16BE UTF-16LE Selitys 7-bittinen ASCII-merkistö ISO Latin 1-merkistö (ISO LATIN-1) 8-bittinern Unicode 16-bittinen Unicode 16-bittinen Unicode, big-endian 16-bittinen Unicode, little-endian Javalla 13
Tiedostoon kirjoittaminen n Virtuaalikoneet tukevat muitakin merkistöjä, käytetyn merkistön saa selville Charset.availableCharsetsmetodilla import java.nio.charset.charset; import java.util.iterator; import java.util.map; public class FileDemo_2 { public static void main(string [] args) { Map<String, Charset> charsets = Charset.availableCharsets(); Iterator<Charset> iterator = charsets.values().iterator(); while (iterator.hasnext()) { Charset cs = (Charset) iterator.next(); System.out.println(cs.displayName()); System.out.println(cs.toString()); } } }
Tiedostoon kirjoittaminen n Tiedot palautetaan avainnettuna kokoelmana Map Avaimena merkistön nimi ja arvona merkistöä kuvaava Charset-olio Javalla 15
Tiedostoon kirjoittaminen import java.nio.charset.charset; import java.io.*; public class FileDemo_3 { public static void main(string [] args) { Charset utf8 = Charset.forName("UTF-8"); try (BufferedWriter tied = new BufferedWriter( new OutputStreamWriter ( new FileOutputStream("testi2.txt"), utf8)) ){ tied.write("tässäpä rivi tekstiä."); tied.newline(); tied.write("tässäpä toinen rivi tekstiä."); }catch( IOException ioe ){ System.out.println("Virhe tiedostoon kirjoittamisessa"); ioe.printstacktrace(); } } } Javalla 16
Tiedostoon kirjoittaminen private static void writetofile( String fname, String... rows ) throws IOException { BufferedWriter file = null; try { file = new BufferedWriter( new FileWriter( fname)); for( String row: rows ){ file.append(row); file.newline(); } file.close(); } finally { if( file = null ){ try { file.close(); }catch ( IOException ioe ){ ; } } } } Javalla 17
Tiedostoon kirjoittaminen n Tiedoston nimeämisessä kannattaa olle tarkkana n Ei tehdä ohjelmaa, joka toimii vain esim. Windowskoneissa n Linux/Unix/OsX ei pysty tekemään tiedostoa, jossa on mukana levyasematunnus ja tai hakemistopolku '\'- erotinmerkkinä "c:\\temp\\tekstia.txt" n Toinen vaaranpaikka "c:\etunimet\nimet.txt" Javalla 18
Tiedostoon kirjoittaminen n Järjestelmän hakemistoerotinmerkki on File-luokassa luokkakohtaisena attribuuttina File.separator n Käyttöjärjestelmän tyypin saa selville System.getProperty-metodilla System.out.println( System.getProperty("os.name") + ":n käyttämä erotimerkki on: "+File.separator ); Mac OS X:n käyttämä erotimerkki on: / Javalla 19
Tiedostosta lukeminen n Tiedostosta luettaessa on avattava virta n Lukemisessa on huolehdittava milloin saavutetaan tietovirran esim. tiedoston loppu n Luettaessa on tarkkailtava lukumetodien palauttamien tavujen tai merkkien lukumäärää Metodit eivät välttämättä lue sitä määrää tavuja tai merkkejä kuin niitä pyydetään lukemaan Javalla 20
Tiedostosta lukeminen n Metodeja int read(), lukee yhden merkin virrasta int read(char [] cbuf), lukee merkit taulukkoon cbuf int read(char [] cbuf, int off, int len), lukee enintään len merkkiä taulukkoon cbuf alkaen kohdasta off n Metodit palauttavat luvun -1 kun saavutetaan tietovirran loppu Javalla 21
Tiedostosta lukeminen n Luettaville virroille on puskuriluokat BufferedReader ja BufferedInputStream n Tavuvirta muunnetaan tekstivirraksi käyttämällä luokkaa InputStreamReader n Tiedostoista luetaan käyttämällä FileInputStreamtai FileReader- luokkkia n FileReader käyttää järjestelmän oletusmerkistöä Javalla 22
Tiedostosta lukeminen import java.nio.charset.charset; import java.io.*; public class FileDemo_7 { public static void main(string [] args) { Charset utf8 = Charset.forName("UTF-8"); try (BufferedReader file = new BufferedReader( new InputStreamReader( new FileInputStream("testi2.txt"), utf8))) { String rivi; while( (rivi = file.readline()) = null ){ System.out.println("Luettiin: " + rivi); } }catch( IOException ioe ){ System.out.println("Virhe lukemisessa"); ioe.printstacktrace(); } } } Javalla 23
Binääritiedostot n Tekstiedostoja kirjoittaessa ohjelma muuntaa tietovirran merkit tietokoneen sisäiseen binääriesitysmuotoon ja luettaessa päinvastoin n Jos tiedosto on tarkoitettu syöttötiedostoksi toiselle ohjelmalle eikä tietoja tarvitse esitää ihmisille voidaan käyttää binääritiedostoja n Tiedot talletetaan tiedostoon suoraan koneen sisäisessä esitysmuodossa ilman muunnosta tekstimuotoon n Luokkaa DataOutputStream käyttämällä voidaan kirjoittaa Javan alkeistietotyyppejä binäärisenä Javalla 24
Binääritiedostot n Metodeja mm. writeboolean( boolean v ) writechar( int v ); writedouble( double v ) writeint( int v ) writeutf(string str ) boolean readboolean( ) char readchar( ); double readdouble( ) int readint( ) String readutf( ) Javalla 25
Binääritiedostot public static void main ( String [ ] args){ DataOutputStream outbinfile = null; try { outbinfile = new DataOutputStream ( new FileOutputStream("nums.bin")); for( int i = 2; i <= 500; i = i + 2 ) outbinfile.writeint( i ); }catch( IOException ioe ){ System.out.println("Virhe kirjoittamisessa"); ioe.printstacktrace(); }finally { try { if( outbinfile = null ) outbinfile.close(); }catch( IOException ioe ){ System.out.println("Virhe"); ioe.printstacktrace(); } } } Javalla 26
Binääritiedostot public static void main ( String [ ] args) { DataInputStream inbinfile = null; try { inbinfile = new DataInputStream ( new FileInputStream("nums.bin")); int luku; do { luku = inbinfile.readint(); System.out.println("Luettiin luku: " + luku); }while( true ); }catch( EOFException eofe ){ System.out.println("Tiedoston loppu tuli vastaan"); try { if( inbinfile = null ) inbinfile.close(); }catch(ioexception ioe ){;} }catch( IOException ioe ){ System.out.println("Virhe"); ioe.printstacktrace(); } } } Javalla 27
Suorasaantitiedostot n Luokkaa RandomAccessFile käytetään tietyn mittaisia tietueita sisältävien tiedostojen käsittelyyn n Suorasaantitiedostossa voidaan siirytä tiedoston sisällä eteen- ja taaksepäin metodilla seek n Tiedostosta voidaan poimia mikä tahansa tietue laskemalla sen sijainti tiedostossa n Kaikki tiedot talletetaan binäärisenä RandomAccessFile file = new RandomAccessFile( "tiedosto.dat", "rw"); file.seek(0); file.writedouble(56.7); file.close(); Javalla 28
Suorasaantitiedostot RandomAccessFile file = new RandomAccessFile( "tiedosto.dat", "r"); file.seek(0); double luku = file.readdouble() file.close(); System.out.println("Luetiin luku: "+ luku); Javalla 29
Olioiden tallettaminen ja lukeminen n Olioiden tila voidaan tallettaa tiedostoon ja lukea tiedostosta n Sarjallistaminen, olio talletetaan tietovirtaan sellaisessa muodossa, että olio voidaan myöhemmin lukea virrasta n Sarjallistamisessa kirjoitetaan oliolle metodit, joilla olio kirjoittaa itsensä virtaan ja lukee itsensä tietovirrasta n Olio voidaan sarjallistaa myös käyttämällä Javan valmiita sarjallistamismekanismeja n Olion on totetutettava littymä java.io.seralizable n Liittymä on tyhjä, ei vaadi mitää toimia ohjelmoijalta Javalla 30
Olioiden tallettaminen ja lukeminen n Sarjallistamista varten omat tietovirrat ObjectInputStream ja ObjectOutputStream n Käyttävät jotain tavuvirtaa public class Henkilo implements java.io.serializable { private String etunimi; private String sukunimi; private String hetu; public Henkilo(String enimi, String snimi, String hhetu){ etunimi = enimi; sukunimi = snimi; hetu = hhetu; } public String tostring(){ return "Etunimi:" + etunimi +"\nsukunimi: " + sukunimi + "\nhetu: " + hetu; } } Javalla 31
Olioiden tallettaminen ja lukeminen import java.io.ioexception; import java.io.objectoutputstream; import java.io.fileoutputstream; public class FileDemo_10 { public static void main(string [] args){ try ( ObjectOutputStream oout = new ObjectOutputStream( new FileOutputStream("henkilot.dat")) ){ Henkilo eka=new Henkilo("Matti","Meikeläinen","010101-0101"); oout.writeobject(eka); Henkilo toka=new Henkilo("Mikko","Hiironen","120456-789A"); oout.writeobject(toka); }catch( IOException ioe) { System.out.println("Sarjallistaminen ei onnistunut"); ioe.printstacktrace(); } } } Javalla 32
Olioiden tallettaminen ja lukeminen import java.io.ioexception; import java.io.objectinputstream; import java.io.fileinputstream; public class FileDemo_11 { public static void main(string [] args){ try ( ObjectInputStream oin = new ObjectInputStream( new FileInputStream("henkilot.dat")) ){ Henkilo eka = (Henkilo)oIn.readObject(); System.out.println("Luettiin:\n" + eka.tostring()); Henkilo toka = (Henkilo)oIn.readObject(); System.out.println("Luettiin:\n " + toka.tostring()); }catch( IOException ClassNotFoundException e) { System.out.println("Sarjallistaminen ei onnistunut"); e.printstacktrace(); } } } Javalla 33
Olioiden tallettaminen ja lukeminen n Oletussarjallistaminen kirjoittaa kaiken olion uudelleenluomiseen tarvittavan tiedon Olion luokan Luokan tunnisteen Kaikki muut attribuutit, mutta ei static- tai transient-avainsanalla merkittyjä Javalla 34