# Downcast - Ich krieg das nicht gebacken...



## hubertb (19. Oktober 2006)

Hallo!

Ich habe eine Klasse FileData, die ich aus File abgeleitet habe. Weiterhin habe ich eine Funktion "Vector<FileData> directoryTraverser(FileData startDirectory)", welche mir rekursiv im startDirectory beginnend alle Dateien in den Unterverzeichnissen sammeln soll. Dazu wollte ich die von File mitgenommene Funktion listFiles(). Dummerweise liefert die aber ein File[] - Array zurück. Downcasten von File nach FileData kann ich das ganze nicht, da bekomm ich immer ne ClassCastException. Was nun?


```
package problemfall;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Vector;

public class DirectoryTraverser {
	private static Vector<FileData> files = null;

	/**
	 * Recursivly visits all directories and collects all filenames it founds in
	 * that directories.
	 * 
	 * @param startDirectory
	 *            Directory where to start the collection.
	 * @return Vector<FileData> containing all found filenames.
	 * @throws FileNotFoundException
	 *             if the input paramter is not a directory or does not exist.
	 */
	public static Vector<FileData> getFiles(FileData startDirectory)
			throws FileNotFoundException {
		if (!startDirectory.isDirectory()) {
			throw new FileNotFoundException(startDirectory.getName()
					+ " ist kein Verzeichnis oder existiert nicht.");
		}
		traverseDirectories(startDirectory);
		return files;
	}

	private static void traverseDirectories(FileData inputDirectory) {
		File[] directoryContent = inputDirectory.listFiles();
		for (int i = 0; i < directoryContent.length; i++) {
			if (directoryContent[i].isDirectory()) {
				traverseDirectories(directoryContent[i]);
			} else {
				if (files == null) {
					files = new Vector<FileData>();
				}
				files.add((FileData)directoryContent[i]); // <= HIER KNALLTS
			}
		}
	}
}
```


----------



## RedWing (19. Oktober 2006)

Hallo,

welchen Zweck erfüllt denn deine Klasse FileData?

Das mit dem Downcast kann nicht funktionieren, da die Objekte die dir von der
Funktion listFiles() geliefert werden eben keine Objekte vom Typ FileData sondern
Objekte vom Typ File sind und somit auch ein andres Speicherbild besitzen

Gruß,
RedWing


----------



## hubertb (19. Oktober 2006)

Ich speicher darin einfach nur noch ein paar Strings, Integers und Booleans und implementiere ein Parserinterface. Ich will nach dem rekursiven Sammeln aller Dateinamen diese parsen, da sie (im Normalfall) ein bestimmtes Muster haben. Haben sie dieses Muster nicht, enden aber auf *.mpg, *.MPG, *.wav oder *.WAV will ich sie trotzdem dem User anzeigen und ihm die Möglichkeit geben, diese Dateien um zu bennen so dass sie auf das Muster passen (daher auch die Idee aus File abzuleiten).


```
package problemfall;

import java.io.File;
import java.net.URI;
import java.util.regex.Pattern;

public class FileData extends File implements FileParser {
	private boolean parsedMatch = false;
	private boolean parsedInteresting = false;
	private String parsedName;
	private String parsedPrename;
	private String parsedKind;
	private int parsedDay;
	private int parsedMonth;
	private int parsedYear;

	public FileData(File parent, String child) {
		super(parent, child);
	}

	public FileData(String parent, String child) {
		super(parent, child);
	}

	public FileData(String pathname) {
		super(pathname);
	}

	public FileData(URI uri) {
		super(uri);
	}

	public int getParsedDay() {
		return parsedDay;
	}

	public boolean isParsedInteresting() {
		return parsedInteresting;
	}

	public String getParsedKind() {
		return parsedKind;
	}

	public boolean isParsedMatch() {
		return parsedMatch;
	}

	public int getParsedMonth() {
		return parsedMonth;
	}

	public String getParsedName() {
		return parsedName;
	}

	public String getParsedPrename() {
		return parsedPrename;
	}

	public int getParsedYear() {
		return parsedYear;
	}

	public void parseFile() {
		// TODO this.getName() geht vllt auch anders?!
		if(Pattern.matches(fileRegex, this.getName())) {
			// Als treffer eintragen
			parsedMatch = true;
			// String aufsplitten
			String[] splitChar = charPattern.split(this.getName(), 4);
			// Name
			parsedName = splitChar[0];
			// Vorname
			parsedPrename = splitChar[1];
			// Art des Gesprächs
			parsedKind = splitChar[2];
			// Aufgesplitteten Teilstring nochmal aufsplitten
			String[] splitDate = datePattern.split(splitChar[3], 4);
			// Tag
			parsedDay = Integer.parseInt(splitDate[0]);
			// Monat
			parsedMonth = Integer.parseInt(splitDate[1]);
			// Jahr
			parsedYear = Integer.parseInt(splitDate[2]);
		} else {
			if (Pattern.matches(elseRegex, this.getName())) {
				// Als Niete aber potenziellen Kandidaten eintragen
				parsedInteresting = true;
			}
		}
	}
}
```


```
package problemfall;

import java.util.regex.Pattern;

public interface FileParser {
	// TODO parseFiles() für String (Upload über Webmodul)
	// TODO Eventuell bisschen Javadoc
	public final static String fileRegex = "[a-zA-ZßÄÖÜäöü]+[,]?\\s[a-zA-ZßÄÖÜäöü]+[,]?\\s(Abschluss|Lesetext|Interview|Telefon|Vorgespräch)[,]?\\s\\d{1,2}\\.\\d{1,2}\\.\\d{4}\\.(mpg|MPG|wav|WAV)";
	public final static String charRegex = "[,]?\\s";
	public final static String dateRegex = "\\.";
	public final static String elseRegex = ".+\\.(mpg|MPG|wav|WAV)";
	public final static Pattern charPattern = Pattern.compile(charRegex);
	public final static Pattern datePattern = Pattern.compile(dateRegex);
	public final static Pattern elsePattern = Pattern.compile(elseRegex);	

	public void parseFile();
}
```


----------



## RedWing (19. Oktober 2006)

Also auf die schnelle würd ich sagen das du dein Design evtl. ändern müsstest...
Auch kann ich nich die unbedingte Notwendigkeit sehen warum du dein FileData 
von File ableitest. Ich würde einfach entweder deinen FileParser so gestalten
das ein FileParser für alle Dateien existiert und du deiner Methode
parseFile() ein Objekt vom Typ File mitgibst, oder du machst für jedes File
ein FileData Objekt was die Referenz auf das dazugehörige File hält, ala:


```
public class FileData implements FileParser {
        private File toParse = null;

	public FileData(File toParse) {
             this.toParse = toParse;
	}
```

oder du überlegst dir was ganz andres  (hängt halt von deinem Anwendungsfall 
ab)...

Jedenfalls der Downcast so wie du Ihn da vor hattest, funktioniert so nicht...

Gruß,
RedWing


----------



## hubertb (19. Oktober 2006)

Bingo (@private File toParse! Ich hab den Wald vor lauter Bäumen nicht gesehen. Danke!

Wie kann man hier eigentlich so schön formatierten Javacode einfügen? Ich hab hier nur Knöpfe für QUOTE, CODE, HTML und PHP


----------



## zeja (19. Oktober 2006)

Wenn du nicht weiss wie andere es schaffen ihren Kram zu formatieren, einfach mal bei deren Beiträgen auf zitieren klicken und schon siehst dus


----------

