De presentatie wordt gedownload. Even geduld aub

De presentatie wordt gedownload. Even geduld aub

1 Hoofdstuk 17: FILES EN STREAMS. 2 H 17. FILES EN STREAMS 1. INLEIDING Files kan je enkel gebruiken in applicaties, NIET in applets Korte termijn geheugen.

Verwante presentaties


Presentatie over: "1 Hoofdstuk 17: FILES EN STREAMS. 2 H 17. FILES EN STREAMS 1. INLEIDING Files kan je enkel gebruiken in applicaties, NIET in applets Korte termijn geheugen."— Transcript van de presentatie:

1 1 Hoofdstuk 17: FILES EN STREAMS

2 2 H 17. FILES EN STREAMS 1. INLEIDING Files kan je enkel gebruiken in applicaties, NIET in applets Korte termijn geheugen versus lange termijn geheugen: Korte termijn geheugen: Variabelen, arrays Ogeslagen in het interne geheugen De inhoud verdwijnt bij einde van de scope Lange termijn geheugen: Files en databanken Opgeslagen op secundaire geheugenmedia Persistente (“blijvende”) gegevens

3 3 H 17. FILES EN STREAMS 1. INLEIDING Files Lange termijn opslag van grote hoeveelheden gegevens Persistente gegevens (blijven bestaan na beëindiging van een programma) Opgeslagen op secundaire geheugenmedia Magnetische schijven Optische schijven Magnetische tapes Sequentiële files en random access files

4 4 H 17. FILES EN STREAMS 1. INLEIDING Sequentiële file Je doorloopt de gegevens in een sequentiële file van voor naar achter Random access file Je krijgt op willekeurige manier toegang tot de gegevens in een random access file

5 5 H 17. FILES EN STREAMS 1. INLEIDING Java file verwerking is een onderdeel van Java stream verwerking. Een stream is een stroom van gegevens. Streams hebben niet alleen met files te maken, maar een stream is een manier om allerlei vormen van gegevenstransport in een computer te beschrijven: gegevens die via het toetsenbord binnenkomen, of via een netwerkkabel of gegevens die via twee programma’s worden uitgewisseld, kan je ook beschouwen als een stream. Mogelijkheden van streams: Bytes lezen uit en schrijven naar het geheugen Bytes lezen uit en schrijven naar files Bytes lezen en schrijven over netwerkverbindingen

6 6 H 17. FILES EN STREAMS 2.Data hierarchie Bit is de kleinste data item in een computer Bit is 0 of 1 Bit is een samentrekking van “binary digit” Programmeurs werken met hogere niveau data items Decimal digits: (0-9) Letters: (A-Z en a-z) Speciale symbolen zoals %, &, *, (, ), -, +, “, :, ?, /, … Java gebruikt Unicode karakters, opgebouwd uit 2 bytes Een byte bevat 8 bits Velden (Java attribuutvariabelen) Opgebouwd uit karakters of bytes

7 7 H 17. FILES EN STREAMS 2.Data hierarchie Data hierarchie Data items in a computer vormen een hierarchie Bits -> karakters -> velden ->... Records Samengesteld uit meerdere velden Geïmplementeerd als een class in Java File is a groep van gerelateerde records Elk record heeft een recordsleutel (record key) Een recordsleutel is een unieke identificatie voor elk record in de file Een recordsleutel vergemakkelijkt het opzoeken van een bepaald record uit een bestand Sequentiële file Records worden opgeslagen in volgorde van de recordsleutel

8 8 Fig Data hierarchy RandyRed J u d y NameColor SallyBlack TomBlue JudyGreen IrisOrange File Record Field Byte (ASCII character J) Bit

9 9 H 17. FILES EN STREAMS 3.Files en streams Java ziet elke file als een sequentiële stream van bytes n-1 end-of-file marker 67

10 10 H 17. FILES EN STREAMS 3.Files en streams Elk besturingssysteem kan het einde van een file bepalen door: end-of-file merkteken het totaal aantal bytes van de file bij te houden Een java programma krijgt een signaal van het besturingssysteem wanneer het programma het einde van een stream bereikt door middel van een exceptie of door middel van een specifieke returnwaarde van een methode

11 11 H 17. FILES EN STREAMS 3.Files en streams Een file wordt geassocieerd met een object Java associeert streams met devices: System.in: standaard input stream object, laat toe om bytes via het toetsenbord in te lezen System.out: standaard output stream object, laat toe om bytes weer te geven op het scherm System.err: standaard error stream object, laat toe om foutboodschappen weer te geven op het scherm Streams kan je omleiden door gebruik te maken van de methoden setIn, setOut en setErr van de klasse System Door System.in om te leiden, kan een programma bytes lezen van een andere bron zoals een file en door System.out en/of System.err om te leiden kan je bytes wegschrijven naar een file op schijf

12 12 H 17. FILES EN STREAMS 3.Files en streams File verwerking gebeurt in Java met klassen van de package java.io FileInputStream om bytes te lezen uit een file FileOutputStream om bytes te schrijven naar een file FileReader om karakters uit een file te lezen FileWriter om karakters naar een file te schrijven

13 13 H 17. FILES EN STREAMS 3.Files en streams Buffering Een buffer is een ruimte in het geheugen Verbetert de performantie van I/O Kopieert elke uitvoer naar een buffer. De volledige inhoud van de buffer wordt naar de schijf geschreven Eén grote toegang tot de schijf neemt minder tijd in beslag dan vele kleine BufferedOutputStream: file output met buffers BufferedInputStream: file input met buffers

14 14 H 17. FILES EN STREAMS 4.De klasse File De klasse File Levert bruikbare informatie over een file of een directory Opent of verwerkt de files NIET

15 15 Methoden van de klasse File

16 16 Voorbeeld 1: FileTest Grafische applicatie waarbij de gebruiker de naam van een file of directory in een instantie van JTextField typt en op enter drukt. Informatie over deze file of deze directory wordt opgehaald en getoond in een JTextArea.

17 17 Voorbeeld 1 Gegevens uit een file lezen: Met FileReader kan je een file openen om de karakters te lezen, maar hiermee kan je geen regels tekst lezen Met BufferedReader kan je regels tekst lezen maar kan je geen file openen om te lezen Oplossing:  Combineer FileReader en BufferedReader  Dit heet wrapping van stream objecten: de services van de ene stream worden toegevoegd aan de andere stream.

18 Hier typ je de naam van de file of de directory Bestaat die file of directory niet, dan krijg je daarvan melding

19 Informatie over een directory Informatie over een file

20 1 // Fig. 17.4: FileTest.java 2 // Demonstrating the File class. 3 import java.awt.*; 4 import java.awt.event.*; 5 import java.io.*; 6 import javax.swing.*; 7 8 public class FileTest extends JFrame 9 implements ActionListener { private JTextField enterField; 12 private JTextArea outputArea; // set up GUI 15 public FileTest() 16 { 17 super( "Testing class File" ); enterField = new JTextField( "Enter file or directory name here"); 20 enterField.addActionListener( this ); 21 outputArea = new JTextArea(); ScrollPane scrollPane = new ScrollPane(); 24 scrollPane.add( outputArea ); 25 Importeer de package java.io

21 26 Container container = getContentPane(); 27 container.add( enterField, BorderLayout.NORTH ); 28 container.add( scrollPane, BorderLayout.CENTER ); setSize( 400, 400 ); 31 setVisible( true ); } // end constructor // display information about file user specifies 36 public void actionPerformed( ActionEvent actionEvent ) 37 { 38 File name = new File( actionEvent.getActionCommand() ); // if name exists, output information about it 41 if ( name.exists() ) { 42 outputArea.setText( name.getName() + " exists\n" + 43 ( name.isFile() ? "is a file\n" : "is not a file\n" ) + 44 ( name.isDirectory() ? "is a directory\n" : 45 "is not a directory\n" ) + 46 ( name.isAbsolute() ? "is absolute path\n" : 47 "is not absolute path\n" ) + "Last modified: " + 48 name.lastModified() + "\nLength: " + name.length() + 49 "\nPath: " + name.getPath() + "\nAbsolute path: " + 50 name.getAbsolutePath() + "\nParent: " + name.getParent() ); 51 Creëert een nieuwe referentie naar File Body van de if geeft informatie over de file als deze file bestaat

22 52 // output information if name is a file 53 if ( name.isFile() ) { // append contents of file to outputArea 56 try { 57 BufferedReader input = new BufferedReader( 58 new FileReader( name ) ); 59 StringBuffer buffer = new StringBuffer(); 60 String text; 61 outputArea.append( "\n\n" ); while ( ( text = input.readLine() ) != null ) 64 buffer.append( text + "\n" ); outputArea.append( buffer.toString() ); 67 } // process file processing problems 70 catch ( IOException ioException ) { 71 JOptionPane.showMessageDialog( this, "FILE ERROR", 72 "FILE ERROR", JOptionPane.ERROR_MESSAGE ); 73 } } // end if 76 Test of de ingegeven naam een file is Creëer een BufferedReader om de gegevens van de file te lezen Lees de tekst regel per regel tot het einde van de file en plaats de inhoud ervan in buffer

23 77 // output directory listing 78 else if ( name.isDirectory() ) { 79 String directory[] = name.list(); outputArea.append( "\n\nDirectory contents:\n"); for ( int i = 0; i < directory.length; i++ ) 84 outputArea.append( directory[ i ] + "\n" ); 85 } } // end outer if // not file or directory, output error message 90 else { 91 JOptionPane.showMessageDialog( this, 92 actionEvent.getActionCommand() + " Does Not Exist", 93 "ERROR", JOptionPane.ERROR_MESSAGE ); 94 } } // end method actionPerformed public static void main( String args[] ) 99 { 100 FileTest application = new FileTest(); 101 application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 102 } } // end class FileTest Als de file niet bestaat, druk dan een foutboodschap Maak een lijst van alle files in de directory

24

25 25 H 17. FILES EN STREAMS 5. Creatie van een sequentiële file De records worden de één na de andere opgeslagen (consecutief) Java legt geen structuur op aan een file De programmeur structureert zelf de file om tegemoet te komen aan de vereisten van de applicatie De gebruiker geeft de records in de juiste volgorde in (dwz in stijgende volgorde van de recordsleutel)

26 26 H 17. FILES EN STREAMS 5.Creatie van een sequentiële file Basisbewerkingen: Openen van een file om in te schrijven Schrijven van een record naar een file Sluiten van een file Opvangen van de mogelijke excepties: IOException

27 27 H 17. FILES EN STREAMS 5.Creatie van een sequentiële file Openen van een file om in te schrijven Voorbeeld: File filenaam(“c:\\oef\\test.dat”); Hiermee wordt de file NIET geopend ObjectOutputStream output; output = new ObjectOutputStream (new FileOutputStream(filenaam)); Met een FileOutputStream object kan je byte arrays en individuele bytes schrijven naar een file. Om objecten te schrijven hebben we wrapping met ObjectOutputStream nodig. Exception handling moet toegepast worden om problemen op te vangen bij het openen van de file.

28 28 H 17. FILES EN STREAMS 5.Creatie van een sequentiële file Schrijven van een record naar een file Voorbeeld: output.writeObject(record); output.flush(); De methode flush() schrijft de gegevens van de buffer in het geheugen naar de file Sluiten van een file Voorbeeld: output.close(); Exception handling moet toegepast worden voor het geval een file niet kan gesloten worden.

29 29 Voorbeeld 2: Creatie van sequentiële file Dit programma maakt een sequentiële file aan met instanties van AccountRecord. Voor elke klant wordt een instantie van AccountRecord naar de file geschreven. De attributen van AccountRecord zijn: account, firstName, lastName en balance De methoden van AccountRecord zijn: constructor, accessors en mutators

30 30 Voorbeeld 2 We maken twee domeinklassen, namelijk BankUI en AccountRecord die we in de volgende voorbeelden zullen hergebruiken. Daarom nemen we ze op in een package.

31 31 Domeinklasse BankUI Een instantie van BankUI zullen we gebruiken als userinterface Bevat 2 instanties van JButton, een array van instanties van JLabel en een array van instanties van JTextField Het aantal elementen van de arrays wordt in de constructor ingesteld. Er is geen default constructor. De methoden getFieldValues, setFieldValues en clearFields beheren de tekst van de instanties van JTextField. De methoden getFields, getDoTask1Button en getDoTask2Button geven de individuele GUI component weer zodat een programma er bijvoorbeeld ActionListener kan aan toevoegen.

32 1 // Fig. 17.5: BankUI.java 2 // A reusable GUI for the examples in this chapter. 3 package com.deitel.jhtp5.ch17; 4 5 import java.awt.*; 6 import javax.swing.*; 7 8 public class BankUI extends JPanel { 9 10 // label text for GUI 11 protected final static String names[] = { "Account number", 12 "First name", "Last name", "Balance", "Transaction Amount" }; // GUI components; protected for future subclass access 15 protected JLabel labels[]; 16 protected JTextField fields[]; 17 protected JButton doTask1, doTask2; 18 protected JPanel innerPanelCenter, innerPanelSouth; protected int size; // number of text fields in GUI // constants representing text fields in GUI 23 public static final int ACCOUNT = 0, FIRSTNAME = 1, LASTNAME = 2, 24 BALANCE = 3, TRANSACTION = 4; 25 Userinterface voor alle voorbeelden uit dit hoofdstuk Deze knoppen zullen de acties uitvoeren in de voorbeelden Compileer deze klasse in een package voor hergebruik

33 26 // Set up GUI. Constructor argument size determines the number of 27 // rows of GUI components. 28 public BankUI( int mySize ) 29 { 30 size = mySize; 31 labels = new JLabel[ size ]; 32 fields = new JTextField[ size ]; // create labels 35 for ( int count = 0; count < labels.length; count++ ) 36 labels[ count ] = new JLabel( names[ count ] ); // create text fields 39 for ( int count = 0; count < fields.length; count++ ) 40 fields[ count ] = new JTextField(); // create panel to lay out labels and fields 43 innerPanelCenter = new JPanel(); 44 innerPanelCenter.setLayout( new GridLayout( size, 2 ) ); // attach labels and fields to innerPanelCenter 47 for ( int count = 0; count < size; count++ ) { 48 innerPanelCenter.add( labels[ count ] ); 49 innerPanelCenter.add( fields[ count ] ); 50 } 51

34 52 // create generic buttons; no labels or event handlers 53 doTask1 = new JButton(); 54 doTask2 = new JButton(); // create panel to lay out buttons and attach buttons 57 innerPanelSouth = new JPanel(); 58 innerPanelSouth.add( doTask1 ); 59 innerPanelSouth.add( doTask2 ); // set layout of this container and attach panels to it 62 setLayout( new BorderLayout() ); 63 add( innerPanelCenter, BorderLayout.CENTER ); 64 add( innerPanelSouth, BorderLayout.SOUTH ); validate(); // validate layout } // end constructor // return reference to generic task button doTask1 71 public JButton getDoTask1Button() 72 { 73 return doTask1; 74 } // return reference to generic task button doTask2 77 public JButton getDoTask2Button() 78 { 79 return doTask2; 80 } Levert de actieknoppen af

35 81 82 // return reference to fields array of JTextFields 83 public JTextField[] getFields() 84 { 85 return fields; 86 } // clear content of text fields 89 public void clearFields() 90 { 91 for ( int count = 0; count < size; count++ ) 92 fields[ count ].setText( "" ); 93 } // set text field values; throw IllegalArgumentException if 96 // incorrect number of Strings in argument 97 public void setFieldValues( String strings[] ) 98 throws IllegalArgumentException 99 { 100 if ( strings.length != size ) 101 throw new IllegalArgumentException( "There must be " size + " Strings in the array" ); for ( int count = 0; count < size; count++ ) 105 fields[ count ].setText( strings[ count ] ); 106 }

36 // get array of Strings with current text field contents 109 public String[] getFieldValues() 110 { 111 String values[] = new String[ size ]; for ( int count = 0; count < size; count++ ) 114 values[ count ] = fields[ count ].getText(); return values; 117 } } // end class BankUI

37 37 Domeinklasse AccountRecord Implementeert de interface Serializable zodat de instanties van AccountRecord kunnen gebruikt worden met ObjectInputStream en ObjectOutputStream. ObjectOutputStream maakt het mogelijk om objecten te serializeren dwz converteren naar een stroom van bytes. ObjectInputStream maakt het mogelijk om gegevens te deserializeren dwz converteren van een serie bytes naar het oorspronkelijke object. Serializable is een tagging interface, ze bevat geen methoden. Een klasse die deze interface implementeert, is getagged om een Serializable object te zijn.

38 38 Domeinklasse AccountRecord ObjectOutputStream schrijft enkel serialized objecten weg. In een klasse die Serializable implementeert, moeten alle instantievariabelen Serializable zijn of moeten de instantievariabelen transient zijn om aan te duiden dat die variabelen niet Serializable zijn en dat ze dus genegeerd moeten worden bij het serializable proces Alle variabelen van primitieve datatypen zijn bij default serializable. Voor referentievariabelen moet de klasse en mogelijk ook de superklasse nagekeken worden om zeker te zijn dat het type Serializable is.

39 39 Domeinklasse AccountRecord Attributen: account firstName lastName balance Methoden: constructoren accessors en mutators

40 1 // Fig. 17.6: AccountRecord.java 2 // A class that represents one record of information. 3 package com.deitel.jhtp5.ch17; 4 5 import java.io.Serializable; 6 7 public class AccountRecord implements Serializable { 8 private int account; 9 private String firstName; 10 private String lastName; 11 private double balance; // no-argument constructor calls other constructor with default values 14 public AccountRecord() 15 { 16 this( 0, "", "", 0.0 ); 17 } // initialize a record 20 public AccountRecord( int acct, String first, String last, double bal) 21 { 22 setAccount( acct ); 23 setFirstName( first ); 24 setLastName( last ); 25 setBalance( bal ); 26 } 27 Compileer deze klasse in een package voor hergebruik Implementeert Serializable zodat instanties van AccountRecord gebruikt kunnen worden met input en output streams

41 28 // set account number 29 public void setAccount( int acct ) 30 { 31 account = acct; 32 } // get account number 35 public int getAccount() 36 { 37 return account; 38 } // set first name 41 public void setFirstName( String first ) 42 { 43 firstName = first; 44 } // get first name 47 public String getFirstName() 48 { 49 return firstName; 50 } 51

42 52 // set last name 53 public void setLastName( String last ) 54 { 55 lastName = last; 56 } // get last name 59 public String getLastName() 60 { 61 return lastName; 62 } // set balance 65 public void setBalance( double bal ) 66 { 67 balance = bal; 68 } // get balance 71 public double getBalance() 72 { 73 return balance; 74 } } // end class AccountRecord

43 43 Voorbeeld 2: Creatie van sequentiële file We tonen een scherm met labels en tekstvelden om de records in te vullen en twee knoppen “Save into file” en “Enter”. Slechts één van beide knoppen is geactiveerd. Eerst wordt een bestand gekozen waarin de records worden weggeschreven. Hiervoor maken we gebruik van een instantie van JFileChooser met als selectiemode FILES_ONLY. We gebruiken de methode showSaveDialog van JFileChooser om de dialoogbox Save te tonen. Dit is een modal dialoogbox, dwz de gebruiker moet eerst deze dialoogbox sluiten vooraleer hij een andere actie kan ondernemen. De methode getSelectedFile levert de waarde af van de geselecteerde file van het type File. Die bevat informatie over de file zoals de naam en de plaats, maar NIET de inhoud van de file. Om de file te openen gebruiken we FileOutputStream. De file wordt op deze manier geopend voor uitvoer en de eventueel aanwezige inhoud gaat op die manier verloren.

44 44 Voorbeeld 2 Willen we een file openen voor uitbreiding (append), dan maken we gebruik van de constructor met twee argumenten. De bestaande inhoud van de file gaat dan NIET verloren, maar wordt uitgebreid Voorbeeld: new FileOutputStream(filenaam, true); Om objecten te schrijven naar de file, wrappen we de file in een ObjectOutputStream De recordvelden worden ingevuld met de correcte gegevens en als men op de “Enter”-knop drukt, wordt het record weggeschreven naar de file. De records worden weggeschreven in stijgende volgorde van de recordsleutel (Account Number).

45 45 Voorbeeld 2 Het object wegschrijven naar de file gebeurt met de methode writeObject. Nadien wordt de methode flush gebruikt om de gegevens uit de buffer in het geheugen dadelijk weg te schrijven naar de file. Wanneer je wrapped files gebruikt, moet de buitenste stream gebruikt worden om het bestand te sluiten.

46 Het programma toont deze grafische interface Je kan enkel op de knop Save into File... klikken En dan krijg je de volgende dialoogbox Hier geef je de naam van de file die je wenst aan te maken

47 Je kan nu de gegevens van de records invoeren. Wanneer je op de Enter-knop klikt, worden de gegevens weggeschreven naar de file

48 1 // Fig. 17.7: CreateSequentialFile.java 2 // Writing objects sequentially to a file with class ObjectOutputStream. 3 import java.io.*; 4 import java.awt.*; 5 import java.awt.event.*; 6 import javax.swing.*; 7 8 import com.deitel.jhtp5.ch17.BankUI; 9 import com.deitel.jhtp5.ch17.AccountRecord; public class CreateSequentialFile extends JFrame { 12 private ObjectOutputStream output; 13 private BankUI userInterface; 14 private JButton enterButton, openButton; // set up GUI 17 public CreateSequentialFile() 18 { 19 super( "Creating a Sequential File of Objects" ); // create instance of reusable user interface 22 userInterface = new BankUI( 4 ); // four textfields 23 getContentPane().add( userInterface, BorderLayout.CENTER ); // configure button doTask1 for use in this program 26 openButton = userInterface.getDoTask1Button(); 27 openButton.setText( "Save into File..." ); Importeer de grafische interface, een instantie van de klasse BankUI en het record, een instantie van de klasse AccountRecord Creëer de grafische interface en haal een referentie naar de eerste actie knop op

49 28 29 // register listener to call openFile when button pressed 30 openButton.addActionListener( // anonymous inner class to handle openButton event 33 new ActionListener() { // call openFile when button pressed 36 public void actionPerformed( ActionEvent event ) 37 { 38 openFile(); 39 } } // end anonymous inner class ); // end call to addActionListener // configure button doTask2 for use in this program 46 enterButton = userInterface.getDoTask2Button(); 47 enterButton.setText( "Enter" ); 48 enterButton.setEnabled( false ); // disable button // register listener to call addRecord when button pressed 51 enterButton.addActionListener( 52 Haal een referentie naar de tweede actie knop op

50 53 // anonymous inner class to handle enterButton event 54 new ActionListener() { // call addRecord when button pressed 57 public void actionPerformed( ActionEvent event ) 58 { 59 addRecord(); 60 } } // end anonymous inner class ); // end call to addActionListener // register window listener to handle window closing event 67 addWindowListener( // anonymous inner class to handle windowClosing event 70 new WindowAdapter() { // add current record in GUI to file, then close file 73 public void windowClosing( WindowEvent event ) 74 { 75 if ( output != null ) 76 addRecord(); closeFile(); 79 }

51 80 81 } // end anonymous inner class ); // end call to addWindowListener setSize( 300, 200 ); 86 setVisible( true ); } // end CreateSequentialFile constructor // allow user to specify file name 91 private void openFile() 92 { 93 // display file dialog, so user can choose file to open 94 JFileChooser fileChooser = new JFileChooser(); 95 fileChooser.setFileSelectionMode( JFileChooser.FILES_ONLY ); int result = fileChooser.showSaveDialog( this ); // if user clicked Cancel button on dialog, return 100 if ( result == JFileChooser.CANCEL_OPTION ) 101 return; File fileName = fileChooser.getSelectedFile(); // get selected file 104 Instantieer een JFileChooser en ken de referentie toe aan fileChooser De constante FILES_ONLY geeft aan dat alleen files kunnen geselecteerd worden Methode showSaveDialog zorgt ervoor dat de JFileChooser genaamd Save verschijnt Haal de geselecteerde file op

52 105 // display error if invalid 106 if ( fileName == null || fileName.getName().equals( "" ) ) 107 JOptionPane.showMessageDialog( this, "Invalid File Name", 108 "Invalid File Name", JOptionPane.ERROR_MESSAGE ); else { // open file 113 try { 114 output = new ObjectOutputStream( 115 new FileOutputStream( fileName ) ); openButton.setEnabled( false ); 118 enterButton.setEnabled( true ); 119 } // process exceptions from opening file 122 catch ( IOException ioException ) { 123 JOptionPane.showMessageDialog( this, "Error Opening File", 124 "Error", JOptionPane.ERROR_MESSAGE ); 125 } } // end else } // end method openFile 130 Open de geselecteerde file

53 131 // close file and terminate application 132 private void closeFile() 133 { 134 // close file 135 try { 136 output.close(); 137 System.exit( 0 ); 138 } // process exceptions from closing file 141 catch( IOException ioException ) { 142 JOptionPane.showMessageDialog( this, "Error closing file", 143 "Error", JOptionPane.ERROR_MESSAGE ); 144 System.exit( 1 ); 145 } } // end method closeFile // add record to file 150 public void addRecord() 151 { 152 int accountNumber = 0; 153 AccountRecord record; 154 String fieldValues[] = userInterface.getFieldValues(); 155 Methode closeFile sluit de huidige file Haal de gegevens op uit de tekstvelden

54 156 // if account field value is not empty 157 if ( ! fieldValues[ BankUI.ACCOUNT ].equals( "" ) ) { // output values to file 160 try { 161 accountNumber = Integer.parseInt( 162 fieldValues[ BankUI.ACCOUNT ] ); if ( accountNumber > 0 ) { // create new record 167 record = new AccountRecord( accountNumber, 168 fieldValues[ BankUI.FIRSTNAME ], 169 fieldValues[ BankUI.LASTNAME ], 170 Double.parseDouble( fieldValues[ BankUI.BALANCE ] ) ); // output record and flush buffer 173 output.writeObject( record ); 174 output.flush(); 175 } else { 178 JOptionPane.showMessageDialog( this, 179 "Account number must be greater than 0", 180 "Bad account number", JOptionPane.ERROR_MESSAGE ); 181 } 182 Creëer een nieuw record Schrijf het record onmiddellijk weg naar de file

55 183 // clear textfields 184 userInterface.clearFields(); } // end try // process invalid account number or balance format 189 catch ( NumberFormatException formatException ) { 190 JOptionPane.showMessageDialog( this, 191 "Bad account number or balance", "Invalid Number Format", 192 JOptionPane.ERROR_MESSAGE ); 193 } // process exceptions from file output 196 catch ( IOException ioException ) { 197 JOptionPane.showMessageDialog( this, "Error writing to file", 198 "IO Exception", JOptionPane.ERROR_MESSAGE ); 199 closeFile(); 200 } } // end if } // end method addRecord 205

56 206 public static void main( String args[] ) 207 { 208 new CreateSequentialFile(); 209 } } // end class CreateSequentialFile Grafische interface BankUI

57 Selecteer een plaats voor de file Files en directories worden hier getoond Klik Save om de naan van de file door te geven aan het programma

58 58 H 17. FILES EN STREAMS 6. Gegevens lezen uit een sequenti ë le file Gegevens opgeslagen in files worden opgehaald om te verwerken wanneer nodig Toegang tot een sequentiële file: De gegevens moeten gelezen worden in hetzelfde formaat als toen ze weggeschreven werden. Een sequentiële file is enkel sequentieel toegankelijk. File  R1  R2  R3  …  Rn

59 59 H 17. FILES EN STREAMS 6. Gegevens lezen uit een sequenti ë le file Basisbewerkingen: Openen van een file om te lezen Lezen van een record Sluiten van een file Opvangen van de mogelijke excepties: IOException Openen van een file om te lezen Voorbeeld: File filenaam(“c:\\oef\\test.dat”); ObjectInputStream input = new ObjectInputStream (new FileInputStream(filenaam));

60 60 H 17. FILES EN STREAMS 6. Gegevens lezen uit een sequenti ë le file Lezen van een record uit de file Voorbeeld: record = (AccountRecord) input.readObject(); Het gelezen record wordt geconverteerd naar het gepaste recordtype met een expliciete cast. Sluiten van de file Voorbeeld: input.close();

61 61 Voorbeeld 3: sequentiële file lezen De records uit de sequentiële file uit voorbeeld 2 lezen en op het scherm tonen. Maak gebruik van ObjectInputStream gewrapped rond een FileInputStream om de gegevens uit de file te kunnen lezen in hetzelfde formaat als de gegevens werden weggeschreven.

62 62 Voorbeeld 3 De methode showOpenDialog van de klasse JFileChooser wordt gebruikt om een file te selecteren en te openen voor invoer. Telkens de gebruiker op de knop “Next Record” klikt, leest het programma het volgende record uit de file. We gebruiken de methode readObject om een record te lezen uit de file. Het afgeleverde object wordt gecast naar het type AccountRecord.

63 63 Fig Voorbeeldgegevens voor het programma uit voorbeeld 3

64 Het programma toont deze grafische interface Je kan enkel op de knop Open File... klikken En dan krijg je de volgende dialoogbox Hier klik je de naam van de file aan die je wenst te openen Nu worden de gegevens van de records weergegeven. Klik je op Next Record dan krijg je de gegevens van het volgende record te zien

65 1 // Fig. 17.9: ReadSequentialFile.java 2 // This program reads a file of objects sequentially 3 // and displays each record. 4 import java.io.*; 5 import java.awt.*; 6 import java.awt.event.*; 7 import javax.swing.*; 8 9 import com.deitel.jhtp5.ch17.*; public class ReadSequentialFile extends JFrame { 12 private ObjectInputStream input; 13 private BankUI userInterface; 14 private JButton nextButton, openButton; // Constructor -- initialize the Frame 17 public ReadSequentialFile() 18 { 19 super( "Reading a Sequential File of Objects" ); // create instance of reusable user interface 22 userInterface = new BankUI( 4 ); // four textfields 23 getContentPane().add( userInterface, BorderLayout.CENTER ); 24 Creëer de grafische interface

66 25 // get reference to generic task button doTask1 from BankUI 26 openButton = userInterface.getDoTask1Button(); 27 openButton.setText( "Open File" ); // register listener to call openFile when button pressed 30 openButton.addActionListener( // anonymous inner class to handle openButton event 33 new ActionListener() { // close file and terminate application 36 public void actionPerformed( ActionEvent event ) 37 { 38 openFile(); 39 } } // end anonymous inner class ); // end call to addActionListener // register window listener for window closing event 46 addWindowListener( // anonymous inner class to handle windowClosing event 49 new WindowAdapter() { 50 Haal een referentie op naar de eerste actie knop

67 51 // close file and terminate application 52 public void windowClosing( WindowEvent event ) 53 { 54 if ( input != null ) 55 closeFile(); System.exit( 0 ); 58 } } // end anonymous inner class ); // end call to addWindowListener // get reference to generic task button doTask2 from BankUI 65 nextButton = userInterface.getDoTask2Button(); 66 nextButton.setText( "Next Record" ); 67 nextButton.setEnabled( false ); // register listener to call readRecord when button pressed 70 nextButton.addActionListener( // anonymous inner class to handle nextRecord event 73 new ActionListener() { 74 Haal een referentie op naar de tweede actie knop

68 75 // call readRecord when user clicks nextRecord 76 public void actionPerformed( ActionEvent event ) 77 { 78 readRecord(); 79 } } // end anonymous inner class ); // end call to addActionListener pack(); 86 setSize( 300, 200 ); 87 setVisible( true ); } // end ReadSequentialFile constructor // enable user to select file to open 92 private void openFile() 93 { 94 // display file dialog so user can select file to open 95 JFileChooser fileChooser = new JFileChooser(); 96 fileChooser.setFileSelectionMode( JFileChooser.FILES_ONLY ); int result = fileChooser.showOpenDialog( this ); 99 Instantieer een JFileChooser en ken de referentie toe aan fileChooser De constante FILES_ONLY geeft aan dat alleen files kunnen geslecteerd worden De methode showOpenDialog zorgt ervoor dat JFileChooser genaamd Open verschijnt

69 100 // if user clicked Cancel button on dialog, return 101 if ( result == JFileChooser.CANCEL_OPTION ) 102 return; // obtain selected file 105 File fileName = fileChooser.getSelectedFile(); // display error if file name invalid 108 if ( fileName == null || fileName.getName().equals( "" ) ) 109 JOptionPane.showMessageDialog( this, "Invalid File Name", 110 "Invalid File Name", JOptionPane.ERROR_MESSAGE ); else { // open file 115 try { 116 input = new ObjectInputStream( 117 new FileInputStream( fileName ) ); openButton.setEnabled( false ); 120 nextButton.setEnabled( true ); 121 } // process exceptions opening file 124 catch ( IOException ioException ) { 125 JOptionPane.showMessageDialog( this, "Error Opening File", 126 "Error", JOptionPane.ERROR_MESSAGE ); 127 } Wordt afgeleverd wanneer de gebruiker op de Cancel button klikt Haal de geselecteerde file op Creëer de geselecteerde file

70 } // end else } // end method openFile // read record from file 134 public void readRecord() 135 { 136 AccountRecord record; // input the values from the file 139 try { 140 record = ( AccountRecord ) input.readObject(); // create array of Strings to display in GUI 143 String values[] = { String.valueOf( record.getAccount() ), 144 record.getFirstName(), record.getLastName(), 145 String.valueOf( record.getBalance() ) }; // display record contents 148 userInterface.setFieldValues( values ); 149 } // display message when end-of-file reached 152 catch ( EOFException endOfFileException ) { 153 nextButton.setEnabled( false ); 154 De methode readObject leest een Object uit de ObjectInputStream

71 155 JOptionPane.showMessageDialog( this, "No more records in file", 156 "End of File", JOptionPane.ERROR_MESSAGE ); 157 } // display error message if class is not found 160 catch ( ClassNotFoundException classNotFoundException ) { 161 JOptionPane.showMessageDialog( this, "Unable to create object", 162 "Class Not Found", JOptionPane.ERROR_MESSAGE ); 163 } // display error message if cannot read due to problem with file 166 catch ( IOException ioException ) { 167 JOptionPane.showMessageDialog( this, 168 "Error during read from file", 169 "Read Error", JOptionPane.ERROR_MESSAGE ); 170 } } // end method readRecord // close file and terminate application 175 private void closeFile() 176 { 177 // close file and exit 178 try { 179 input.close(); 180 System.exit( 0 ); 181 } Methode closeFile sluit de file

72 // process exception while closing file 184 catch ( IOException ioException ) { 185 JOptionPane.showMessageDialog( this, "Error closing file", 186 "Error", JOptionPane.ERROR_MESSAGE ); System.exit( 1 ); 189 } } // end method closeFile public static void main( String args[] ) 194 { 195 new ReadSequentialFile(); 196 } } // end class ReadSequentialFile

73

74 74 H 17. FILES EN STREAMS 7. Een sequenti ë le file updaten Het is moeilijk om een sequentiële file te updaten Het hele bestand moet herschreven worden om één veld te wijzigen. Deze werkwijze is enkel aanvaardbaar wanneer vele records te samen worden geupdated.

75 75 H 17. FILES EN STREAMS 8. Random access files “Instant-access” applicaties Een record moet onmiddellijk gelokaliseerd worden Transactie verwerkende systemen vereisen een snelle toegang tot de gegevens in een file random access files Toegang tot individuele records is direct en snel Gebruik een vaste lengte voor elk record De relatieve positie van elk record kan gemakkelijk berekend worden ten opzichte van het begin van de file in functie van de recordgrootte en de recordsleutel

76 bytes 100 bytes 100 bytes 100 bytes 100 bytes 100 bytes byte offsets

77 77 Sommige records hebben een inhoud (bestaande records) en andere records zijn leeg (niet-bestaande records) Tussenvoegen van records in een file is mogelijk zonder andere gegevens in de file te vernietigen Gegevens kunnen gewijzigd of verwijderd worden zonder de gehele file te herschrijven

78 78 De gegevens in een random access file zijn sequentieel toegankelijk en direct toegankelijk Sequentiële toegangsfunctie: File  R1  R2  R3  …  Rn Directe toegangsfunctie: File R1 R2 R3 … Rn

79 79 H 17. FILES EN STREAMS 17.9 Creatie van een random access file Instanties van de klasse RandomAccessFile hebben alle mogelijkheden van de klassen FileInputStream, FileOutputStream, DataInputStream en DataOutputstream Bij een random access file worden de gegevens gelezen of geschreven te beginnen bij een plaats in de file, aangegeven door de file-position pointer Alle gegevens worden behandeld als primitieve types (met vaste byte grootte) In de meeste programma’s worden objecten naar de file weggeschreven.

80 80 Voorbeeld: Een transactie verwerkend programma dat tot 100 records met een vaste lengte kan bijhouden voor een bedrijf met 100 klanten. Het programma is in staat om een record te updaten, een nieuw record toe te voegen en een record te verwijderen. We maken een domeinklasse RandomAccessAccountRecord

81 81 Domeinklasse RandomAccessAccountRecord subklasse van AccountRecord Extra attribuut: SIZE, de grootte van één record uitgedrukt in bytes Extra methoden: read: één record lezen uit een random access file write: één record wegschrijven naar een random access file

82 82 Domeinklasse RandomAccessAccountRecord In de methode read gebruiken we methoden van de klasse RandomAccessFile: readInt, readDouble en readChar om de primitieve typen te lezen uit een random access file In de methode write gebruiken we methoden van de klasse RandomAccessFile: writeInt, writeChars en writeDouble om primitieve datatypen weg te schrijven naar een random access file Voor de voornaam (firstName) en de familienaam (lastName) worden exact 15 karakters gelezen en geschreven. Deze namen worden indien nodig aangevuld met blanco’s. Zo krijgt een record een vaste lengte.

83 1 // Fig : RandomAccessAccountRecord.java 2 // Subclass of AccountRecord for random access file programs. 3 package com.deitel.jhtp5.ch17; 4 5 import java.io.*; 6 7 public class RandomAccessAccountRecord extends AccountRecord { 8 9 public static final int SIZE = 72; // bytes in one record // no-argument constructor calls other constructor with default values 12 public RandomAccessAccountRecord() 13 { 14 this( 0, "", "", 0.0 ); 15 } // initialize a RandomAccessAccountRecord 18 public RandomAccessAccountRecord( int account, String firstName, 19 String lastName, double balance ) 20 { 21 super( account, firstName, lastName, balance ); 22 } 23 Subklasse van AccountRecord

84 24 // read a record from specified RandomAccessFile 25 public void read( RandomAccessFile file ) throws IOException 26 { 27 setAccount( file.readInt() ); 28 setFirstName( readName( file ) ); 29 setLastName( readName( file ) ); 30 setBalance( file.readDouble() ); 31 } // ensure that name is proper length 34 private String readName( RandomAccessFile file ) throws IOException 35 { 36 char name[] = new char[ 15 ], temp; for ( int count = 0; count < name.length; count++ ) { 39 temp = file.readChar(); 40 name[ count ] = temp; 41 } return new String( name ).replace( '\0', ' ' ); 44 } 45 Methode read leest één record uit een instantie van de klasse RandomAccessFile Methode readInt leest één geheel getal Methode readDouble leest één gebroken getal met dubbele precisie Methode readChar leest één karakter

85 46 // write a record to specified RandomAccessFile 47 public void write( RandomAccessFile file ) throws IOException 48 { 49 file.writeInt( getAccount() ); 50 writeName( file, getFirstName() ); 51 writeName( file, getLastName() ); 52 file.writeDouble( getBalance() ); 53 } // write a name to file; maximum of 15 characters 56 private void writeName( RandomAccessFile file, String name ) 57 throws IOException 58 { 59 StringBuffer buffer = null; if ( name != null ) 62 buffer = new StringBuffer( name ); 63 else 64 buffer = new StringBuffer( 15 ); buffer.setLength( 15 ); 67 file.writeChars( buffer.toString() ); 68 } } // end class RandomAccessAccountRecord Methode write schrijft één record weg naar een instantie van de klasse RandomAccessFile Methode writeInt schrijft één geheel getal weg Methode writeDouble schrijft één gebroken getal met dubbele precisie weg Methode writeName schrijft een string weg naar een file Methode writeChars schrijft een string weg

86 86 Creatie van een random access file Er wordt een direct bestand gecreëerd hierbij wordt de constructor aangeroepen met 2 parameters namelijk de naam van de file en de open mode (r=read, rw=read en write) 100 blanco records worden weggeschreven naar de random access file De random access file wordt gesloten.

87 Hier typ je de naam van de file Wanneer je op de knop Save klikt, wordt een file gecreëerd

88 1 // Fig : CreateRandomFile.java 2 // Creates random access file by writing 100 empty records to disk. 3 import java.io.*; 4 import javax.swing.*; 5 6 import com.deitel.jhtp5.ch17.RandomAccessAccountRecord; 7 8 public class CreateRandomFile { 9 10 private static final int NUMBER_RECORDS = 100; // enable user to select file to open 13 private void createFile() 14 { 15 // display dialog so user can choose file 16 JFileChooser fileChooser = new JFileChooser(); 17 fileChooser.setFileSelectionMode( JFileChooser.FILES_ONLY ); int result = fileChooser.showSaveDialog( null ); // if user clicked Cancel button on dialog, return 22 if ( result == JFileChooser.CANCEL_OPTION ) 23 return; // obtain selected file 26 File fileName = fileChooser.getSelectedFile();

89 27 28 // display error if file name invalid 29 if ( fileName == null || fileName.getName().equals( "" ) ) 30 JOptionPane.showMessageDialog( null, "Invalid File Name", 31 "Invalid File Name", JOptionPane.ERROR_MESSAGE ); else { // open file 36 try { 37 RandomAccessFile file = 38 new RandomAccessFile( fileName, "rw" ); RandomAccessAccountRecord blankRecord = 41 new RandomAccessAccountRecord(); // write 100 blank records 44 for ( int count = 0; count < NUMBER_RECORDS; count++ ) 45 blankRecord.write( file ); file.close(); // close file // display message that file was created 50 JOptionPane.showMessageDialog( null, "Created file " + 51 fileName, "Status", JOptionPane.INFORMATION_MESSAGE ); Creëert een directe file, een instantie van RandomAccessFile Schrijft 100 lege records weg

90 52 53 System.exit( 0 ); // terminate program } // end try // process exceptions during open, write or close file operations 58 catch ( IOException ioException ) { 59 JOptionPane.showMessageDialog( null, "Error processing file", 60 "Error processing file", JOptionPane.ERROR_MESSAGE ); System.exit( 1 ); 63 } } // end else } // end method createFile public static void main( String args[] ) 70 { 71 CreateRandomFile application = new CreateRandomFile(); 72 application.createFile(); 73 } } // end class CreateRandomFile

91

92 92 H 17. FILES EN STREAMS Gegevens direct wegschrijven naar een random access file De methode seek van de klasse RandomAccessFile Plaatst de file-position pointer op de exacte plaats in de file waar het record moet opgeslagen worden

93 93 Voorbeeld: Schrijf een aantal records naar een random access file De file wordt geopend in de mode “rw” Gebruik de methode seek om de file-pointer pointer te positioneren Gebruik de methode write om een record weg te schrijven naar de file We maken de veronderstelling dat de gebruiker GEEN dubbele recordsleutels ingeeft en zinvolle gegevens invoert

94 94 Er zijn 2 knoppen: Open en Enter Slechts één van beide knoppen is geactiveerd. Wanneer de gebruiker op Open klikt, kan hij een file kiezen die geopend wordt Wanneer de gebruiker waarden invoert in de tekstvelden en vervolgens op de knop Enter klikt, worden de ingevoerde waarden opgeslagen in een instantie van de klasse RandomAccessAccountRecord door gebuik van de methode write

95 Het programma toont deze grafische interface. Je kan enkel op de knop Open… klikken. En dan krijg je de volgende dialoogbox Hier klik je de naam van de file aan die je wenst te openen Wanneer je een Account number invoert en op de knop Enter klikt, worden de gegevens van dat record gelezen uit het bestand.

96 1 // Fig : WriteRandomFile.java 2 // This program uses textfields to get information from the user at the 3 // keyboard and writes the information to a random-access file. 4 import java.awt.*; 5 import java.awt.event.*; 6 import java.io.*; 7 import javax.swing.*; 8 9 import com.deitel.jhtp5.ch17.*; public class WriteRandomFile extends JFrame { 12 private RandomAccessFile output; 13 private BankUI userInterface; 14 private JButton enterButton, openButton; private static final int NUMBER_RECORDS = 100; // set up GUI 19 public WriteRandomFile() 20 { 21 super( "Write to random access file" ); // create instance of reusable user interface BankUI 24 userInterface = new BankUI( 4 ); // four textfields 25 getContentPane().add( userInterface, 26 BorderLayout.CENTER );

97 27 28 // get reference to generic task button doTask1 in BankUI 29 openButton = userInterface.getDoTask1Button(); 30 openButton.setText( "Open..." ); // register listener to call openFile when button pressed 33 openButton.addActionListener( // anonymous inner class to handle openButton event 36 new ActionListener() { // allow user to select file to open 39 public void actionPerformed( ActionEvent event ) 40 { 41 openFile(); 42 } } // end anonymous inner class ); // end call to addActionListener // register window listener for window closing event 49 addWindowListener( 50

98 51 // anonymous inner class to handle windowClosing event 52 new WindowAdapter() { // add record in GUI, then close file 55 public void windowClosing( WindowEvent event ) 56 { 57 if ( output != null ) 58 addRecord(); closeFile(); 61 } } // end anonymous inner class ); // end call to addWindowListener // get reference to generic task button doTask2 in BankUI 68 enterButton = userInterface.getDoTask2Button(); 69 enterButton.setText( "Enter" ); 70 enterButton.setEnabled( false ); // register listener to call addRecord when button pressed 73 enterButton.addActionListener( 74

99 75 // anonymous inner class to handle enterButton event 76 new ActionListener() { // add record to file 79 public void actionPerformed( ActionEvent event ) 80 { 81 addRecord(); 82 } } // end anonymous inner class ); // end call to addActionListener setSize( 300, 150 ); 89 setVisible( true ); 90 } // enable user to choose file to open 93 private void openFile() 94 { 95 // display file dialog so user can select file 96 JFileChooser fileChooser = new JFileChooser(); 97 fileChooser.setFileSelectionMode( JFileChooser.FILES_ONLY ); int result = fileChooser.showOpenDialog( this ); 100

100 101 // if user clicked Cancel button on dialog, return 102 if ( result == JFileChooser.CANCEL_OPTION ) 103 return; // obtain selected fil 106 File fileName = fileChooser.getSelectedFile(); // display error if file name invalid 109 if ( fileName == null || fileName.getName().equals( "" ) ) 110 JOptionPane.showMessageDialog( this, "Invalid File Name", 111 "Invalid File Name", JOptionPane.ERROR_MESSAGE ); else { // open file 116 try { 117 output = new RandomAccessFile( fileName, "rw" ); 118 enterButton.setEnabled( true ); 119 openButton.setEnabled( false ); 120 } // process exception while opening file 123 catch ( IOException ioException ) { 124 JOptionPane.showMessageDialog( this, "File does not exist", 125 "Invalid File Name", JOptionPane.ERROR_MESSAGE ); 126 } Creëert een instantie van de klasse RandomAccessFile

101 } // end else } // end method openFile // close file and terminate application 133 private void closeFile() 134 { 135 // close file and exit 136 try { 137 if ( output != null ) 138 output.close(); System.exit( 0 ); 141 } // process exception while closing file 144 catch( IOException ioException ) { 145 JOptionPane.showMessageDialog( this, "Error closing file", 146 "Error", JOptionPane.ERROR_MESSAGE ); System.exit( 1 ); 149 } } // end method closeFile 152

102 153 // add one record to file 154 private void addRecord() 155 { 156 String fields[] = userInterface.getFieldValues(); // ensure account field has a value 159 if ( ! fields[ BankUI.ACCOUNT ].equals( "" ) ) { // output values to file 162 try { 163 int accountNumber = 164 Integer.parseInt( fields[ ACCOUNT ] ); if ( accountNumber > 0 && accountNumber <= NUMBER_RECORDS ) { 167 RandomAccessAccountRecord record 168 new RandomAccessAccountRecord(); record.setAccount( accountNumber ); 171 record.setFirstName( fields[ BankUI.FIRSTNAME ] ); 172 record.setLastName( fields[ BankUI.LASTNAME ] ); 173 record.setBalance( Double.parseDouble( 174 fields[ BankUI.BALANCE ] ) ); output.seek( ( accountNumber - 1 ) * 177 RandomAccessAccountRecord.SIZE ); 178 record.write( output ); 179 } Zet de file-position pointer op de juiste plaats

103 else { 182 JOptionPane.showMessageDialog( this, 183 "Account must be between 1 and 100", 184 "Invalid account number", JOptionPane.ERROR_MESSAGE ); 185 } userInterface.clearFields(); // clear TextFields } // end try // process improper account number or balance format 192 catch ( NumberFormatException formatException ) { 193 JOptionPane.showMessageDialog( this, 194 "Bad account number or balance", 195 "Invalid Number Format", JOptionPane.ERROR_MESSAGE ); 196 } // process exceptions while writing to file 199 catch ( IOException ioException ) { 200 JOptionPane.showMessageDialog( this, 201 "Error writing to the file", "IO Exception", 202 JOptionPane.ERROR_MESSAGE ); 203 closeFile(); 204 }

104 } // end if } // end method addRecord public static void main( String args[] ) 211 { 212 new WriteRandomFile(); 213 } } // end class WriteRandomFile

105

106 106 H 17. FILES EN STREAMS Gegevens sequentieel lezen uit een random access file De random access file openen in de open mode “r” (alleen lezen) Alle “bestaande records” uit de random access file worden gelezen (sequentiële toegangsfunctie) in volgorde van de recordsleutel

107 107 Voorbeeld Het programma toont twee knoppen “Open File for Reading” en “Next”. Slechts één van beide knoppen is geactiveerd. Met de knop “Open File for Reading” selecteer je een file om te openen Met de knop “Next” wordt het volgende record uit de file gelezen en de inhoud ervan op het scherm getoond. De records worden in stijgende volgorde van de recordsleutel getoond.

108 Het programma toont deze grafische interface. Je kan enkel op de knop Open File for Reading … klikken. En dan krijg je de volgende dialoogbox Hier klik je de naam van de file aan die je wenst te openen. De gegevens van het eerste record uit de file worden getoond. Als je op de knop Next klikt, krijg je de gegevens van het volgende record op het scherm.

109 1 // Fig : ReadRandomFile.java 2 // This program reads a random-access file sequentially and 3 // displays the contents one record at a time in text fields. 4 import java.awt.*; 5 import java.awt.event.*; 6 import java.io.*; 7 import java.text.DecimalFormat; 8 import javax.swing.*; 9 10 import com.deitel.jhtp5.ch17.*; public class ReadRandomFile extends JFrame { 13 private BankUI userInterface; 14 private RandomAccessFile input; 15 private JButton nextButton, openButton; private static DecimalFormat twoDigits = new DecimalFormat( "0.00" ); // set up GUI 20 public ReadRandomFile() 21 { 22 super( "Read Client File" ); // create reusable user interface instance 25 userInterface = new BankUI( 4 ); // four textfields 26 getContentPane().add( userInterface );

110 27 28 // configure generic doTask1 button from BankUI 29 openButton = userInterface.getDoTask1Button(); 30 openButton.setText( "Open File for Reading..." ); // register listener to call openFile when button pressed 33 openButton.addActionListener( // anonymous inner class to handle openButton event 36 new ActionListener() { // enable user to select file to open 39 public void actionPerformed( ActionEvent event ) 40 { 41 openFile(); 42 } } // end anonymous inner class ); // end call to addActionListener // configure generic doTask2 button from BankUI 49 nextButton = userInterface.getDoTask2Button(); 50 nextButton.setText( "Next" ); 51 nextButton.setEnabled( false );

111 52 53 // register listener to call readRecord when button pressed 54 nextButton.addActionListener( // anonymous inner class to handle nextButton event 57 new ActionListener() { // read a record when user clicks nextButton 60 public void actionPerformed( ActionEvent event ) 61 { 62 readRecord(); 63 } } // end anonymous inner class ); // end call to addActionListener // register listener for window closing event 70 addWindowListener( // anonymous inner class to handle windowClosing event 73 new WindowAdapter() { 74

112 75 // close file and terminate application 76 public void windowClosing( WindowEvent event ) 77 { 78 closeFile(); 79 } } // end anonymous inner class ); // end call to addWindowListener setSize( 300, 150 ); 86 setVisible( true ); } // end constructor // enable user to select file to open 91 private void openFile() 92 { 93 // display file dialog so user can select file 94 JFileChooser fileChooser = new JFileChooser(); 95 fileChooser.setFileSelectionMode( JFileChooser.FILES_ONLY ); int result = fileChooser.showOpenDialog( this ); 98

113 99 // if user clicked Cancel button on dialog, return 100 if ( result == JFileChooser.CANCEL_OPTION ) 101 return; // obtain selected file 104 File fileName = fileChooser.getSelectedFile(); // display error is file name invalid 107 if ( fileName == null || fileName.getName().equals( "" ) ) 108 JOptionPane.showMessageDialog( this, "Invalid File Name", 109 "Invalid File Name", JOptionPane.ERROR_MESSAGE ); else { // open file 114 try { 115 input = new RandomAccessFile( fileName, "r" ); 116 nextButton.setEnabled( true ); 117 openButton.setEnabled( false ); 118 } // catch exception while opening file 121 catch ( IOException ioException ) { 122 JOptionPane.showMessageDialog( this, "File does not exist", 123 "Invalid File Name", JOptionPane.ERROR_MESSAGE ); 124 } Opent een random access file, een instantie van RandomAccessFile

114 } // end else } // end method openFile // read one record 131 private void readRecord() 132 { 133 RandomAccessAccountRecord record = new RandomAccessAccountRecord(); // read a record and display 136 try { do { 139 record.read( input ); 140 } while ( record.getAccount() == 0 ); String values[] = { String.valueOf( record.getAccount() ), 143 record.getFirstName(), record.getLastName(), 144 String.valueOf( record.getBalance() ) }; 145 userInterface.setFieldValues( values ); 146 } 147 Leest tot een geldig record wordt gevonden

115 148 // close file when end-of-file reached 149 catch ( EOFException eofException ) { 150 JOptionPane.showMessageDialog( this, "No more records", 151 "End-of-file reached", JOptionPane.INFORMATION_MESSAGE ); 152 closeFile(); 153 } // process exceptions from problem with file 156 catch ( IOException ioException ) { 157 JOptionPane.showMessageDialog( this, "Error Reading File", 158 "Error", JOptionPane.ERROR_MESSAGE ); System.exit( 1 ); 161 } } // end method readRecord // close file and terminate application 166 private void closeFile() 167 { 168 // close file and exit 169 try { 170 if ( input != null ) 171 input.close(); System.exit( 0 ); 174 } Als de end-of-file marker bereikt is, zijn er geen records meer

116 // process exception closing file 177 catch( IOException ioException ) { 178 JOptionPane.showMessageDialog( this, "Error closing file", 179 "Error", JOptionPane.ERROR_MESSAGE ); System.exit( 1 ); 182 } } // end method closeFile public static void main( String args[] ) 187 { 188 new ReadRandomFile(); 189 } } // end class ReadRandomFile

117

118 Case Study Een transactie verwerkend programma Gebruikt een random access file Wijzigen, toevoegen en verwijderen van accounts

119 Het programma toont deze grafische interface Eerst wordt een file geselecteerd om te openen. Vervolgens kunnen de bewerkingen toevoegen, wijzigen en verwijderen van een record plaatsvinden.

120 Voer account number in en druk de Entertoets om het record te lezen uit het bestand en de gegevens ervan te tonen Deze knop krijgt een label afhankelijk van de bewerking die uitgevoerd wordt.

121 Voer een Transaction Amount in Aangepaste waarde nadat de gebruiker op de knop Update geklikt heeft.

122 Een nieuw record aan de random access file toevoegen

123 Verwijderen van een record

124 1 // Fig : TransactionProcessor.java 2 // A transaction processing program using random-access files. 3 import java.awt.*; 4 import java.awt.event.*; 5 import java.io.*; 6 import java.text.DecimalFormat; 7 import javax.swing.*; 8 9 import com.deitel.jhtp5.ch17.*; public class TransactionProcessor extends JFrame { private BankUI userInterface; 14 private JMenuItem newItem, updateItem, deleteItem, openItem, exitItem; 15 private JTextField fields[]; 16 private JTextField accountField, transactionField; 17 private JButton actionButton, cancelButton; 18 private FileEditor dataFile; 19 private RandomAccessAccountRecord record; public TransactionProcessor() 22 { 23 super( "Transaction Processor" ); 24

125 25 // set up desktop, menu bar and File menu 26 userInterface = new BankUI( 5 ); 27 getContentPane().add( userInterface ); 28 userInterface.setVisible( false ); // set up the action button 31 actionButton = userInterface.getDoTask1Button(); 32 actionButton.setText( "Save Changes" ); 33 actionButton.setEnabled( false ); // register action button listener 36 actionButton.addActionListener( new ActionListener() { // anonymous inner class public void actionPerformed( ActionEvent event ) 41 { 42 String action = event.getActionCommand(); 43 performAction( action ); } // end method actionPerformed } // end anonymous inner class ); // end call to addActionListener 50

126 51 // set up the cancel button 52 cancelButton = userInterface.getDoTask2Button(); 53 cancelButton.setText( "Cancel" ); 54 cancelButton.setEnabled( false ); // register cancel button listener 57 cancelButton.addActionListener( new ActionListener() { // anonymous inner class // clear the fields 62 public void actionPerformed( ActionEvent event ) 63 { 64 userInterface.clearFields(); 65 } } // end anonymous inner class ); // end call to addActionListener // set up the listener for the account field 72 fields = userInterface.getFields(); 73 accountField = fields[ BankUI.ACCOUNT ]; 74 accountField.addActionListener( 75

127 76 new ActionListener() { // anonymous inner class public void actionPerformed( ActionEvent event ) 79 { 80 displayRecord( "0" ); 81 } } // end anonymous inner class ); // end call to addActionListener // create reference to the transaction field 88 transactionField = fields[ BankUI.TRANSACTION ]; // register transaction field listener 91 transactionField.addActionListener( new ActionListener() { // anonymous inner class // update the GUI fields 96 public void actionPerformed( ActionEvent event ) 97 { 98 displayRecord( transactionField.getText() ); 99 } } // end anonymous inner class 102

128 103 ); // end call to addActionListener JMenuBar menuBar = new JMenuBar(); // set up the menu 106 setJMenuBar( menuBar ); JMenu fileMenu = new JMenu( "File" ); 109 menuBar.add( fileMenu ); // set up menu item for adding a record 112 newItem = new JMenuItem( "New Record" ); 113 newItem.setEnabled( false ); // register new item listener 116 newItem.addActionListener( new ActionListener() { // anonymous inner class public void actionPerformed( ActionEvent event ) 121 { // set up the GUI fields for editing 124 fields[ BankUI.ACCOUNT ].setEnabled( true ); 125 fields[ BankUI.FIRSTNAME ].setEnabled( true ); 126 fields[ BankUI.LASTNAME ].setEnabled( true ); 127 fields[ BankUI.BALANCE ].setEnabled( true ); 128 fields[ BankUI.TRANSACTION ].setEnabled( false );

129 actionButton.setEnabled( true ); 131 actionButton.setText( "Create" ); 132 cancelButton.setEnabled( true ); userInterface.clearFields(); // reset the textfields } // end method actionPerformed } // end anonymous inner class ); // end call to addActionListener // set up menu item for updating a record 143 updateItem = new JMenuItem( "Update Record" ); 144 updateItem.setEnabled( false ); // register update item listener 147 updateItem.addActionListener( new ActionListener() { // anonymous inner class public void actionPerformed( ActionEvent event ) 152 {

130 153 // set up the GUI fields for editing 154 fields[ BankUI.ACCOUNT ].setEnabled( true ); 155 fields[ BankUI.FIRSTNAME ].setEnabled( false ); 156 fields[ BankUI.LASTNAME ].setEnabled( false ); 157 fields[ BankUI.BALANCE ].setEnabled( false ); 158 fields[ BankUI.TRANSACTION ].setEnabled( true ); actionButton.setEnabled( true ); 161 actionButton.setText( "Update" ); 162 cancelButton.setEnabled( true ); userInterface.clearFields(); // reset the textfields } // end method actionPerformed } // end anonymous inner class ); // end call to addActionListener // set up menu item for deleting a record 173 deleteItem = new JMenuItem( "Delete Record" ); 174 deleteItem.setEnabled( false ); // register delete item listener 177 deleteItem.addActionListener( 178

131 179 new ActionListener() { // anonymous inner class public void actionPerformed( ActionEvent event ) 182 { 183 // set up the GUI fields for editing 184 fields[ BankUI.ACCOUNT ].setEnabled( true ); 185 fields[ BankUI.FIRSTNAME ].setEnabled( false ); 186 fields[ BankUI.LASTNAME ].setEnabled( false ); 187 fields[ BankUI.BALANCE ].setEnabled( false ); 188 fields[ BankUI.TRANSACTION ].setEnabled( false ); actionButton.setEnabled( true ); 191 actionButton.setText( "Delete" ); 192 cancelButton.setEnabled( true ); userInterface.clearFields(); // reset the textfields } // end method actionPerformed } // end anonymous inner class ); // end call to addActionListener // set up menu item for opening file 203 openItem = new JMenuItem( "New/Open File" ); 204

132 205 // register open item listener 206 openItem.addActionListener( new ActionListener() { // anonymous inner class public void actionPerformed( ActionEvent event ) 211 { 212 // try to open the file 213 if ( !openFile() ) 214 return; // set up the menu items 217 newItem.setEnabled( true ); 218 updateItem.setEnabled( true ); 219 deleteItem.setEnabled( true ); 220 openItem.setEnabled( false ); // set the interface 223 userInterface.setVisible( true ); 224 fields[ BankUI.ACCOUNT ].setEnabled( false ); 225 fields[ BankUI.FIRSTNAME ].setEnabled( false ); 226 fields[ BankUI.LASTNAME ].setEnabled( false ); 227 fields[ BankUI.BALANCE ].setEnabled( false ); 228 fields[ BankUI.TRANSACTION ].setEnabled( false ); } // end method actionPerformed 231

133 232 } // end anonymous inner class ); // end call to addActionListener // set up menu item for exiting program 237 exitItem = new JMenuItem( "Exit" ); // register exit item listener 240 exitItem.addActionListener( new ActionListener() { // anonyomus inner class public void actionPerformed( ActionEvent event ) 245 { 246 try { 247 dataFile.closeFile(); // close the file 248 } catch ( IOException ioException ) { 251 JOptionPane.showMessageDialog( 252 TransactionProcessor.this, "Error closing file", 253 "IO Error", JOptionPane.ERROR_MESSAGE ); 254 } finally { 257 System.exit( 0 ); // exit the program 258 }

134 } // end method actionPerformed } // end anonymous inner class ); // end call to addActionListener // attach menu items to File menu 267 fileMenu.add( openItem ); 268 fileMenu.add( newItem ); 269 fileMenu.add( updateItem ); 270 fileMenu.add( deleteItem ); 271 fileMenu.addSeparator(); 272 fileMenu.add( exitItem ); setSize( 400, 250 ); 275 setVisible( true ); } // end constructor public static void main( String args[] ) 280 { 281 new TransactionProcessor(); 282 } 283

135 284 // get the file name and open the file 285 private boolean openFile() 286 { 287 // display dialog so user can select file 288 JFileChooser fileChooser = new JFileChooser(); 289 fileChooser.setFileSelectionMode( JFileChooser.FILES_ONLY ); int result = fileChooser.showOpenDialog( this ); // if user clicked Cancel button on dialog, return 294 if ( result == JFileChooser.CANCEL_OPTION ) 295 return false; // obtain selected file 298 File fileName = fileChooser.getSelectedFile(); // display error if file name invalid 301 if ( fileName == null || fileName.getName().equals( "" ) ) { 302 JOptionPane.showMessageDialog( this, "Invalid File Name", 303 "Bad File Name", JOptionPane.ERROR_MESSAGE ); 304 return false; 305 } try { 308 // call the helper method to open the file 309 dataFile = new FileEditor( fileName ); 310 } Creëer een instantie van FileEditor met de naam van de file

136 catch( IOException ioException ) { 313 JOptionPane.showMessageDialog( this, "Error Opening File", 314 "IO Error", JOptionPane.ERROR_MESSAGE ); 315 return false; 316 } return true; } // end method openFile // create, update or delete the record 323 private void performAction( String action ) 324 { 325 try { // get the textfield values 328 String[] values = userInterface.getFieldValues(); int accountNumber = Integer.parseInt( values[ BankUI.ACCOUNT ] ); 331 String firstName = values[ BankUI.FIRSTNAME ]; 332 String lastName = values[ BankUI.LASTNAME ]; 333 double balance = Double.parseDouble( values[ BankUI.BALANCE ] ); if ( action.equals( "Create" ) ) 336 dataFile.newRecord( accountNumber, // create a new record 337 firstName, lastName, balance ); Wordt opgeroepen wanneer er op de eerste button wordt geklikt Creërt een nieuw record

137 else if ( action.equals( "Update" ) ) 340 dataFile.updateRecord( accountNumber, // update record 341 firstName, lastName, balance ); else if ( action.equals( "Delete" ) ) 344 dataFile.deleteRecord( accountNumber ); // delete record else 347 JOptionPane.showMessageDialog( this, "Invalid Action", 348 "Error executing action", JOptionPane.ERROR_MESSAGE ); } // end try catch( NumberFormatException format ) { 353 JOptionPane.showMessageDialog( this, "Bad Input", 354 "Number Format Error", JOptionPane.ERROR_MESSAGE ); 355 } catch( IllegalArgumentException badAccount ) { 358 JOptionPane.showMessageDialog( this, badAccount.getMessage(), 359 "Bad Account Number", JOptionPane.ERROR_MESSAGE ); 360 } 361 catch( IOException ioException ) { 362 JOptionPane.showMessageDialog( this, "Error writing to the file", 363 "IO Error", JOptionPane.ERROR_MESSAGE ); 364 } Wijzigt een recordVerwijdert een record

138 } // end method performAction // input a record in the textfields and update the balance 369 private void displayRecord( String transaction ) 370 { 371 try { 372 // get the account number 373 int accountNumber = Integer.parseInt( 374 userInterface.getFieldValues()[ BankUI.ACCOUNT ] ); // get the associated record 377 RandomAccessAccountRecord record = 378 dataFile.getRecord( accountNumber ); if ( record.getAccount() == 0 ) 381 JOptionPane.showMessageDialog( this, "Record does not exist", 382 "Bad Account Number", JOptionPane.ERROR_MESSAGE ); // get the transaction 385 double change = Double.parseDouble( transaction ); // create a string array to send to the textfields 388 String[] values = { String.valueOf( record.getAccount() ), 389 record.getFirstName(), record.getLastName(), 390 String.valueOf( record.getBalance() + change ), 391 "Charge(+) or payment (-)" }; Toont een record in de tekstvelden

139 userInterface.setFieldValues( values ); } // end try catch( NumberFormatException format ) { 398 JOptionPane.showMessageDialog( this, "Bad Input", 399 "Number Format Error", JOptionPane.ERROR_MESSAGE ); 400 } catch ( IllegalArgumentException badAccount ) { 403 JOptionPane.showMessageDialog( this, badAccount.getMessage(), 404 "Bad Account Number", JOptionPane.ERROR_MESSAGE ); 405 } catch( IOException ioException ) { 408 JOptionPane.showMessageDialog( this, "Error reading the file", 409 "IO Error", JOptionPane.ERROR_MESSAGE ); 410 } } // end method displayRecord } // end class TransactionProcessor

140 140 Domeinklasse FileEditor Instanties van de klasse FileEditor verrichten de gepaste bewerkingen op de geselecteerde file

141 1 // Fig : FileEditor.java 2 // This class declares methods that manipulate bank account 3 // records in a random access file. 4 import java.io.*; 5 6 import com.deitel.jhtp5.ch17.RandomAccessAccountRecord; 7 8 public class FileEditor { 9 10 RandomAccessFile file; // reference to the file // open the file 13 public FileEditor( File fileName ) throws IOException 14 { 15 file = new RandomAccessFile( fileName, "rw" ); 16 } // close the file 19 public void closeFile() throws IOException 20 { 21 if ( file != null ) 22 file.close(); 23 } 24 Creëert een random access file met gegeven naam Sluit de random access file

142 25 // get a record from the file 26 public RandomAccessAccountRecord getRecord( int accountNumber ) 27 throws IllegalArgumentException, NumberFormatException, IOException 28 { 29 RandomAccessAccountRecord record = new RandomAccessAccountRecord(); if ( accountNumber 100 ) 32 throw new IllegalArgumentException( "Out of range" ); // seek appropriate record in file 35 file.seek( ( accountNumber - 1 ) * RandomAccessAccountRecord.SIZE ); record.read( file ); return record; } // end method getRecord // update record in file 44 public void updateRecord( int accountNumber, String firstName, 45 String lastName, double balance ) 46 throws IllegalArgumentException, IOException 47 { 48 RandomAccessAccountRecord record = getRecord( accountNumber ); 49 if ( accountNumber == 0 ) 50 throw new IllegalArgumentException( "Account does not exist" ); 51 Leest een record uit de file Positioneer de file-position pointer Lees een record Wijzig een record

143 52 // seek appropriate record in file 53 file.seek( ( accountNumber - 1 ) * RandomAccessAccountRecord.SIZE ); record = new RandomAccessAccountRecord( accountNumber, 56 firstName, lastName, balance ); record.write( file ); // write updated record to file } // end method updateRecord // add record to file 63 public void newRecord( int accountNumber, String firstName, 64 String lastName, double balance ) 65 throws IllegalArgumentException, IOException 66 { 67 RandomAccessAccountRecord record = getRecord( accountNumber ); if ( record.getAccount() != 0 ) 70 throw new IllegalArgumentException( "Account already exists" ); // seek appropriate record in file 73 file.seek( ( accountNumber - 1 ) * RandomAccessAccountRecord.SIZE ); record = new RandomAccessAccountRecord( accountNumber, 76 firstName, lastName, balance ); Positioneer de file-position pointer Overschrijf het record Creëer een nieuw record Positioneer de file-position pointer

144 77 78 record.write( file ); // write record to file } // end method newRecord // delete record from file 83 public void deleteRecord( int accountNumber ) 84 throws IllegalArgumentException, IOException 85 { 86 RandomAccessAccountRecord record = getRecord( accountNumber ); if ( record.getAccount() == 0 ) 89 throw new IllegalArgumentException( "Account does not exist" ); // seek appropriate record in file 92 file.seek( ( accountNumber - 1 ) * RandomAccessAccountRecord.SIZE ); // create a blank record to write to the file 95 record = new RandomAccessAccountRecord(); 96 record.write( file ); } // end method deleteRecord } // end class EditFile Schrijf het nieuwe record weg naar de file Verwijder een record Positioneer de file-position pointer Verwijder een record door het oude record te overschrijven met een leeg record

145 Nieuwe I/O APIs voor Java Buffers Om de snelheid van I/O bewerkingen te verhogen Eigenschappen van een buffer: Capacity: hoeveelheid gegevens die je in een buffer kan opslaan Limit: huidig einde van de buffer, limit<=capacity Position: wijst naar het volgende element van de buffer dat wordt gelezen of weggeschreven Mark: herkenningsplaats in de buffer, waar het programma later kan naar terugkeren, mark<=position Put and get bewerkingen om gegevens te schrijven naar en te lezen uit buffers Overige bewerkingen: clear, flip, rewind, reset

146 Nieuwe I/O APIs voor Java Channels Verbinding met een I/O device Werkt efficiënt samen met buffers ReadableByteChannel interface Methode read WriteableByteChannel interface Methode write Scattering reads en gathering writes Class FileChannel stelt een channel voor verbonden met een file

147 Nieuwe I/O APIs voor Java File Locks Beperkt de toegang tot een deel van een file FileChannel, position, size Exclusive of shared Charsets Package java.nio.charset Class Charset Methoden decode, encode Class CharsetDecoder, CharsetEncoder

148 148 Voorbeeld Gegevens lezen en schrijven in een FileChannel door gebruik te maken van buffers.

149 1 // Fig : FileChannelTest.java 2 // Demonstrates FileChannel and ByteBuffer. 3 import java.io.*; 4 import java.nio.*; 5 import java.nio.channels.*; 6 7 public class FileChannelTest { 8 private FileChannel fileChannel; 9 10 // no-arg constructor 11 public FileChannelTest() 12 { 13 // create random access file and get file channel 14 try { 15 RandomAccessFile file = new RandomAccessFile( "Test", "rw" ); 16 fileChannel = file.getChannel(); 17 } 18 catch ( IOException ioException ) { 19 ioException.printStackTrace(); 20 } } // end constructor FileChannelTest 23 Import de java.nio en java.nio.channels packages Haalt een channel op door de methode getChannel aan te roepen

150 24 // write to writeChannel 25 public void writeToFile() throws IOException 26 { 27 // create buffer for writing 28 ByteBuffer buffer = ByteBuffer.allocate( 14 ); // write an int, a char and a double to buffer 31 buffer.putInt( 100 ); 32 buffer.putChar( 'A' ); 33 buffer.putDouble( ); // flip buffer and write buffer to fileChannel 36 buffer.flip(); 37 fileChannel.write( buffer ); 38 } // read from readChannel 41 public void readFromFile() throws IOException 42 { 43 String content = ""; // create buffer for read 46 ByteBuffer buffer = ByteBuffer.allocate( 14 ); 47 Alloceert een buffer van 14 bytes Vul de buffer met een geheel getal, een karakter en een gebroken getal met dubbele precisie Flipt de buffer om hem voor te bereiden om weg te schrijven Schrijft de buffer naar een FileChannel Alloceer een buffer van 14 bytes

151 48 // read buffer from fileChannel 49 fileChannel.position( 0 ); 50 fileChannel.read( buffer ); // flip buffer for reading 53 buffer.flip(); // obtain content 56 content += buffer.getInt() + ", " + buffer.getChar() + ", " + 57 buffer.getDouble(); System.out.println( "File contains: " + content ); // close fileChannel 62 fileChannel.close(); } // end method readFromFile public static void main( String[] args ) 67 { 68 FileChannelTest application = new FileChannelTest(); 69 Positioneer de FileChannel bij het begin en vul de buffer met bytes Flip de buffer om hem voor te bereiden om te lezen Vul de buffer met een geheel getal, een karakter en een gebroken getal met dubbele precisie Sluit de FileChannel

152 70 // write to file and then read from file 71 try { 72 application.writeToFile(); 73 application.readFromFile(); 74 } 75 catch ( IOException ioException ) { 76 ioException.printStackTrace(); 77 } 78 } } // end class FileChannelTest


Download ppt "1 Hoofdstuk 17: FILES EN STREAMS. 2 H 17. FILES EN STREAMS 1. INLEIDING Files kan je enkel gebruiken in applicaties, NIET in applets Korte termijn geheugen."

Verwante presentaties


Ads door Google