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.