# Wie prüfe ich die Komplettheit von Dateien?



## aldi15 (12. Jan 2009)

Hallo Liste,
ich habe ein Verzeichnis auf einem Linux-Server, in das in unregelmäßigen Abständen Bilddateien eingestellt werden.
Ich möchte nun ein Programm entwerfen, das in regelmäßigen Abständen nachschaut, ob Dateien vorhanden sind. Wenn ja, soll eine Bildverarbeitung stattfinden. Soweit so gut. Hier mein Problem:
Ich mache von dem Verzeichis ein java.io.File()-Objekt und lasse mir mit listFiles ein File-Array mit allen Dateien im Vz. geben. Das Array gehe ich durch und verarbeite jeden Member.
Allerdings kann es sein, daß unter den Files Dateien sind, die noch nicht komplett geliefert wurden. Diese dürfen (können) nicht weiterverarbeitet werden. Somit muss ich prüfen, ob die Datei komplett ist. Die Methoden "exists" und "canRead" geben auch dann true zurück, wenn die Datei noch nicht komplett ist. MD5 ist auch keine Lösung, da ich die Dateien, die ankommen nicht kenne. Man könnte die Dateigrößen merken und in einem zweiten Durchlauf vergleichen, aber es kommen > 10.000 Dateien an und das wäre zu zeitintensiv.
Weiß jemand hier eine elegante Methode, mit der ich die Komplettheit von Dateien prüfen kann? Gibt es da irgendeinen System-Flag oder sowas?

Schöne Grüße
Albrecht


----------



## HoaX (12. Jan 2009)

einfach versuchen die datei mit exklusiven lese und schreibrechten zu öffnen...


----------



## Wildcard (12. Jan 2009)

aldi15 hat gesagt.:
			
		

> Ich möchte nun ein Programm entwerfen, das in regelmäßigen Abständen nachschaut, ob Dateien vorhanden sind.


http://jnotify.sourceforge.net/


----------



## HoaX (12. Jan 2009)

jnotify löst aber auch nicht das problem ob die datei "fertig" ist oder nicht ...


----------



## voidee (12. Jan 2009)

vielleicht ein bisschen "tricky", aber wie wärs mit einer Minute warten und die Dateigrößen vergleichen?


----------



## Wildcard (12. Jan 2009)

HoaX hat gesagt.:
			
		

> jnotify löst aber auch nicht das problem ob die datei "fertig" ist oder nicht ...


Habe ich auch nicht behauptet, macht aber das Polling unnötig.


----------



## HoaX (13. Jan 2009)

Wildcard hat gesagt.:
			
		

> HoaX hat gesagt.:
> 
> 
> 
> ...



hab auch nicht behauptet dass du das behauptet hast  wollte das nur klarstellen bevor es heißt "da tritt das selbe problem auf"


----------



## aldi15 (13. Jan 2009)

Hi Hoax,


> einfach versuchen die datei mit exklusiven lese und schreibrechten zu öffnen...


das hört sich interessant an. Ich habe ja schon geschrieben, dass ich mit canRead geöffnet habe, aber das ging, obwohl die Datei noch nicht komplett angekommen war. Ich bezweifle, ob es mit canWrite besser geht. 
Aber evtl. meinst du ja noch was anderes? Exklusiv lesen/schreiben? Ich kann in der Kommandozeile einen Befehl mit sudo absetzen. Wie mache ich das denn in einer Java- Funktion?
Schöne Grüße
Albrecht


----------



## aldi15 (13. Jan 2009)

Hi nochmal,
also ich habe mir den Vorschlag von Wildcard mit jnotify mal angesehen:
jnotify:


> JNotify is a java library that allow java application to listen to file system events, such as:
> 
> * file created.
> * file modified.
> ...


Das hört sich für mich schon so an, als ob ich das brauchen könnte. Wenn man ein Event 'file created' abfragen kann und ich einen entsprechenden flag zurückbekomme, müsste ich doch wissen, ob die Datei komplett ist. Wieso meinst du das löst mein Problem nicht, ob die Datei fertig ist? ???:L

Grüße
Albrecht


----------



## NTB (13. Jan 2009)

Kannst Du die Methode beeinflussen, wie die Dateien auf den Server kommen?
Wenn ja, könntest Du sie umbenennen, sobald sie fertig hochgeladen sind und Deinem Programm beibringen, nur die umbenannten Dateien zu nehmen.


----------



## ARadauer (13. Jan 2009)

oder wenn du beginnst etwas rauf zu stellen legst du eine hinweis datein hin. ichbingraddabeiwaszuschreiben.info und wenn du fertig bist löscht du das file. so kann der downloader erkennen, dass gerade was passiert


----------



## aldi15 (13. Jan 2009)

Die Idee mit dem umbenennen oder eine Datei zuhilfe zu nehmen wäre naheliegend, aber ich habe keinerlei Einfluss auf den Lieferprozess. Wir bekommen die *.tif-Dateien nach einer Aktualisierung des Datenbestandes. Die Aktualisierung und das Liefern passieren automatisch durch einen Prozess, der schon implementiert ist. Ich muss hier Systemseitig erkennen, wann eine Datei angekommen ist, damit ich sie weiterverarbeiten kann.
Grüße
Albrecht


----------



## Gast2 (13. Jan 2009)

Moin,



			
				aldi15 hat gesagt.:
			
		

> Ich muss hier Systemseitig erkennen, wann eine Datei angekommen ist, damit ich sie weiterverarbeiten kann.


JNotify ist eine super Idee ... Create-Event abfangen ... anschließend warten ... die Zeit die Du wartest kannst Du ja am Anfang abschätzen (durchschnittliche Bildgröße etc.) ... das warten dauert bei mir ca. 500 ms ... dann periodisch versuchen die Datei zum Schreiben(/Lesen) öffnen ... ein kleiner Timeout zwischen den Zugriffen spart CPU-Power (100ms sind nicht zu viel) ... Schreiben in eine Datei darf nur ein Programm ... konntest Du die Datei öffnen, dann gehört sie Dir

hand, mogel

PS: ich bekomme Bilder via FTP geliefert und muss sie in einen Ringspeicher schreiben ... prinzipell das gleiche


----------



## Ark (13. Jan 2009)

mogel hat gesagt.:
			
		

> Schreiben in eine Datei darf nur ein Programm ... konntest Du die Datei öffnen, dann gehört sie Dir


Da wäre ich mir mal nicht so sicher ...

Ark


----------



## Wildcard (13. Jan 2009)

Ark hat gesagt.:
			
		

> Da wäre ich mir mal nicht so sicher ...


Genau. Bei Unix Systemen wird in der Regel per Default kein Lock gesetzt.


----------



## HoaX (13. Jan 2009)

Um diesen Lock zu setzen ist die Klasse "FileChannel" dein(e) Freund(in).


----------



## aldi15 (14. Jan 2009)

Wow, viele Antworten! OK., ich werd mal versuchen, das zu sortieren und melde mich wieder.


----------



## aldi15 (14. Jan 2009)

@mogel:
Übrigens - bei dem Linux-Server gibts tatsächlich keinen Lock des Systems auf die (noch) nicht komplette Datei. Das habe ich schon ausprobiert - große Datei >100 MB - kopiert, dann versucht mit canRead und canWrite und geht beides. Wenn das nicht gegangen wäre (sprich, wenns einen Lock bei nicht kompletten Dateien gegeben hätte), hätte ich ja ein Signal gehabt, nach dem ich die Verarbeitung starten könnte.

@Hoax:
OK, ich habe mir mal die Klasse FileChannel angeschaut. Ja, da gibts eine Methode "lock". Aber eines kapiere ich nicht dabei: Wenn ich den lock jetzt als root auf ein file setzte, das ich testen will, dann kann ich es, wenn ich (bzw. mein Programm) als root das file öffnen will das doch mit Sicherheit auch tun- oder? Meiner Meinung nach müsste der lock doch eigentlich vom System kommen, damit ich mit öffnen/nicht-öffnen nachprüfen kann, ob die Datei vollständig ist. Wie kann FileChannel mir da helfen? Hab' ich jetzt einen Knoten irgendwo?
Grüße
Albrecht


----------



## Wildcard (14. Jan 2009)

Das ist kein Java internes Lock, sondern ein System-Lock. Auf Systemen die das generell nicht gestatten, wird der Versuch einfach fehlschlagen.


----------



## aldi15 (15. Jan 2009)

Hi,
ich habe es mal getestet mit einem lock. Hat tatsächlich kein Ergebnis gebracht:

```
private boolean IsFileValid(File testfile) {
            boolean bIsValid = false;
            fos = new FileOutputStream(new File(testfile.toString()));
            FileLock lock = fos.getChannel().tryLock();
            if (lock != null) {
                lock.release();
                // File komplett!
                System.out.println("Die Datei "+testfile+" ist komplett");           
            }else{
                 System.out.println("Die Datei "+testfile+" ist noch nicht komplett");
            }
              fos.close();
     return bIsValid;
  }
```
 if (lock != null) ist auch dann wahr, wenn die Datei noch nicht vollständig ist. Schade.
Hat noch jemand eine Idee? Wenn nicht, werde ich wohl oder übel doch Dateigrößen vergleichen müssen.  :cry: 
Grüße
Albrecht


----------



## Gast2 (15. Jan 2009)

Moin,



			
				aldi15 hat gesagt.:
			
		

> if (lock != null) ist auch dann wahr, wenn die Datei noch nicht vollständig ist.


klar ... in dem Moment wo Du den Lock auf das File setzt, wird die Datei nicht mehr weiter eingeliefert da der FTP-Server ($WHATEVER) nicht mehr in die Datei schreiben kann ... der FTP-Server muss den Lock setzen und frei geben

du kannst die Größen vergleichen innerhalb eines gewissen Zeitrahmens, wird sich ja wohl nicht mehr ändern wenn die Datei fertig ist ... Du kannst auch testen ob die Datei komplett ist ... bei JPEG gibt es ein SOI und EOI Marker .. .wie es bei TIF ist weis ich nicht

hand, mogel


----------



## aldi15 (15. Jan 2009)

Hi Mogel,


> der FTP-Server muss den Lock setzen und frei geben


Und darauf habe ich leider keinen Einfluss. Also Dateigrößen vergleichen.


> wie es bei TIF ist weis ich nicht


Man kann die Dateigröße wohl auch aus dem Header lesen, aber das scheint mir potentiell unsicher, denn der Lieferserver ist eine Windows-Kiste und mein Arbeitsserver Linux. Da auf NTFS und ext3 die Dateigrößen unterschiedlich berechnet werden, könnte es kleine Differenzen geben. Habe ich aber noch nicht ausprobiert.
Ansonsten lese ich mir die Dateigröße aus, warte 100ms und schaue nochmal nach. 
Ist nicht wirklich schön, aber funktioniert.
Bis denne
Albrecht


----------



## HoaX (15. Jan 2009)

aldi15 hat gesagt.:
			
		

> . Da auf NTFS und ext3 die Dateigrößen unterschiedlich berechnet werden, könnte es kleine Differenzen geben. Habe ich aber noch nicht ausprobiert.



falsch, wenn du dir die bytes anschaust sind das immer gleich viele, wäre ja auch schlimm wenns anders wäre ... was du meinst ist vielleicht die anzeige in der gui, aber das hat nichts mit dem dateisystem zu tun.


----------



## Ebenius (15. Jan 2009)

Vielleicht meint aldi15 auch den phyiskalisch verwendeten Speicher auf der Disk; in Abhängigkeit von Blockgrößen, oder so. Ich stimme meinem Vorredner zu; auf Dataisystemebene haben die Dateien exakt die gleiche Größe.


----------

