| 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. |