Filer |
Vejledende løsninger |
1 | Main.java
import java.io.*; public class Main { public static void main( String[] args ) { try { FileReader input = new FileReader( "src/Main.java" ); while ( input.ready() ) System.out.print( (char) input.read() ); } catch ( FileNotFoundException e ) { System.out.println( "Sourcefilen findes ikke!" ); } catch ( IOException e ) { System.out.println( "Der opstod fejl under indlæsning" ); } } } |
2 | Main.java
import java.io.*; import java.text.DecimalFormat; public class Main { public static void main( String[] args ) { String sourceFilename = "jekyll_hyde.txt"; String statsFilename = "statistik.txt"; int[] stat = new int['Z'-'A'+1]; int total=0; /* * Indlæsning af file */ try { FileReader input = new FileReader( sourceFilename ); while ( input.ready() ) { char c = Character.toUpperCase( (char) input.read() ); if ( 'A' <= c && c <= 'Z' ) { stat[c-'A']++; total++; } } input.close(); } catch ( FileNotFoundException e ) { System.out.println( "Sourcefilen findes ikke: " + sourceFilename ); } catch ( IOException e ) { System.out.println( "Der opstod fejl under læsning fra sourcefilen: " + sourceFilename ); } /* * Udskrivning af statistik */ try { BufferedWriter output = new BufferedWriter( new FileWriter( statsFilename ) ); output.write( "Statistik for filen: " + sourceFilename ); output.newLine(); output.newLine(); // tom linie DecimalFormat formater = new DecimalFormat( "#.##" ); for ( int i=0; i < stat.length; i++ ) { double procent = (double) stat[i] / total * 100; output.write( " " + (char)(i+'A') + ": " + formater.format( procent ) + "%" ); output.newLine(); } output.close(); } catch ( FileNotFoundException e ) { System.out.println( "Kunne ikke åbne statfilen: " + statsFilename ); } catch ( IOException e ) { System.out.println( "Der opstod fejl under skrivning til statfilen: " + statsFilename ); } } } |
Afbildningerne mellem index og tegn illustrerer, at der aldrig er behov for at arbejde konkret med unicode-værdier. | |
3 | Vi vælger her at anvende selve kildetekst-filen som den file vi vil filtrere: |
Main.java
import java.io.*; public class Main { public static void main( String[] args ) { String source = "src/Main.java"; String destination = "cleaned.txt"; try { FileReader input = new FileReader( source ); FileWriter output = new FileWriter( destination ); while ( input.ready() ) { char original = (char) input.read(); char c = Character.toUpperCase( original ); if ( 'A' <= c && c <= 'Z' || c == ' ' ) output.write( original ); } input.close(); output.close(); } catch ( FileNotFoundException e ) { System.out.println( "Fejl ved åbning af file" ); } catch ( IOException e ) { System.out.println( "Fejl ved læsning eller skrivning" ); } } } |
|
Da vi både har indlæsning og udskrivning i samme try-blok, er det ikke muligt for catch-blokkene at fastslå, om exception er kastet i forbindelse med input eller output. Derfor bliver fejlmeddelelserne mere generelle. Man kun have valgt at splitte try-blokken op i flere små try-blokke for få en entydig identifikation, men i dette program er det ikke væsentligt nok til at vi vil acceptere den nedsatte læsbarhed, i form af flere små try-blokke. | |
Bemærk, at vi i forbindelse med toUpperCase, gemmer det oprindelige tegn i original. Ellers ville udskriften blive med alene store bogstaver; hvilket ikke er ønsket i opgaven. | |
4 | StringFileFilter.java
import java.io.*; import java.util.*; public class StringFileFilter implements FileFilter { private LinkedList masker; public StringFileFilter() { masker = new LinkedList(); } public StringFileFilter( String maske ) { this(); add( maske ); } public void add( String maske ) { masker.add( maske ); } public boolean accept( File f ) { if ( masker.size() == 0 ) return true; else for ( int i=0; i<masker.size(); i++ ) { String maske = (String) masker.get(i); if ( filter( f.getName(), maske ) ) return true; } return false; } private boolean filter( String name, String filter ) { if ( name.length() == 0 && filter.length() == 0 ) return true; else if ( filter.length() > 0 && name.length() == 0 ) // Der er ikke flere tegn tilbage i 'name', men 'filter' er ikke udtømt return false; else if ( name.length() > 0 && filter.length() == 0 ) // der er flere tegn i 'name', men 'filter' er udtømt return false; // INV: name.length() > 0 && filter.length() > 0 else if ( filter.startsWith( "#" ) ) { // skal være et ciffer if ( Character.isDigit( name.charAt( 0 ) ) ) return filter( name.substring( 1 ), filter.substring( 1 ) ); else return false; } else if ( filter.startsWith( "?" ) ) // et hvilket som helst tegn return filter( name.substring( 1 ), filter.substring( 1 ) ); else if ( filter.equals( "*" ) ) // en hvilken som helst sekvens return true; else if ( filter.startsWith( "*" ) && !filter.endsWith( "*" ) ) // forsæt fra den anden ende return filter( reverse( name ), reverse( filter ) ); else if ( filter.startsWith( "*" ) ) { // en hvilken som helst sekvens, og mere end det (den svære!) for ( int i=0; i < name.length(); i++ ) if ( filter( name.substring( i ), filter.substring( 1 ) ) ) return true; return false; } else { // specifikt tegn if ( name.substring( 0, 1 ).equalsIgnoreCase( filter.substring( 0, 1 ) ) ) return filter( name.substring( 1 ), filter.substring( 1 ) ); else return false; } } private String reverse( String s ) { StringBuffer sb = new StringBuffer( s ); sb.reverse(); return sb.toString(); } } |
Det svære ved opgaven er den rekursive metode, som tester om 'name' og 'filter' stemmer overens. |