Discussion:
Dateityp erkennen
(zu alt für eine Antwort)
Lupus Goebel
2006-11-28 22:57:05 UTC
Permalink
Hallöschen,

gibt es eine elegante Möglichkeit den Dateityp einer Datei auszulesen?

Bisher lese ich mit dem Code:
\\\
Private Type strFile
tName As String
dDate As Date
dSize As Double
dTyp As String
End Type
Function ReadFolder(strLWPfad As String)
Dim fso As Scripting.FileSystemObject
Dim f As Scripting.Folder
Dim d As Scripting.File
Dim ds As Scripting.Files
Dim i As Long, n As Long
Dim da() As strFile
Dim j As Long, tmp As strFile
Dim strEinleseDateiArt As String
Dim rs As Recordset

Set fso = New Scripting.FileSystemObject
Set f = fso.GetFolder(strLWPfad)
Set ds = f.Files
n = ds.count
If n > 0 Then
ReDim da(1 To n)

For Each d In ds
Set rs = CurrentDb.OpenRecordset("tblImportliste")
rs.AddNew
rs.Fields("DateiName").Value = d.Name
rs.Fields("DateiDatum").Value = d.DateLastModified
rs.Fields("Groesse").Value = d.Size
rs.Fields("dateipfad") = strLWPfad
rs.Fields("Dateityp") = d.Type
rs.Update
rs.Close
Set rs = Nothing

Next d

End If

Set ds = Nothing
Set f = Nothing
Set fso = Nothing

End Function
////

Es wird zwar der Dateityp angegeben, das sieht dann aber so aus:
Dateityp
HTML Document
Adobe Acrobat 7.0 Document
Cascading Style Sheet-Dokument
IrfanView PNG File

Mit dem Dateityp muss ich Verknüpfungen machen. Was nun aber wenn ein
User anstelle Adobe Acrobat 7 eben Adobe Acrobat *5* hat?

Daher suche ich nach einer Möglichkeit die mir eben *pdf* oder *asp*
etc. ausgibt.

Erster Gedanke, suche im Dateinamen nach einem Punkt und gebe mir das
aus was rechts davon steht.
Cool, meine Kollegen haben solche Dateinamen: "20.11.2006.xls"

Nun, nennt mir bitte ein paar Stichwörter, damit weiss wonach ich suchen
muss.
--
MfG - Lupus Goebel
Der Sumpf- und Morasthobbybastler und Anfaenger mit
Wissensdurst (http://www.lupusdw.de)
Meine private FAQ http://www.lupusdw.de/faq
Mark Doerbandt
2006-11-28 23:07:53 UTC
Permalink
Hallo, Lupus,
Post by Lupus Goebel
Dim fso As Scripting.FileSystemObject
schon wieder FSO - was Ihr nur alle damit habt...
Post by Lupus Goebel
Erster Gedanke, suche im Dateinamen nach einem Punkt und gebe mir das
aus was rechts davon steht.
Der erste Gedanke ist ja oft auch der beste!

Schau Dir mal in der Online-Hilfe die Stichworte "Dir" und "InStrRev"
an.

Gruss - Mark
--
Informationen fuer Neulinge in den Access-Newsgroups unter
http://www.doerbandt.de/Access/Newbie.htm

Bitte keine eMails auf Newsgroup-Beiträge senden.
Lupus Goebel
2006-11-29 07:08:11 UTC
Permalink
Morsche,

Am 29.11.2006 00:07 schrieb Mark Doerbandt:

[...]
Post by Mark Doerbandt
Post by Lupus Goebel
Erster Gedanke, suche im Dateinamen nach einem Punkt und gebe mir
das aus was rechts davon steht.
Der erste Gedanke ist ja oft auch der beste!
Schau Dir mal in der Online-Hilfe die Stichworte "Dir" und "InStrRev"
an.
Ahja. In meinem Fall sieht dann die Lösung so aus:

rs.Fields("Dateityp") =
Right(d.Name, Len(d.Name) - InStrRev(d.Name, ".", -1, vbTextCompare))

Ab und zu fehlt mir eben nur der richtige Suchbegriff. Danke schön aber
auch.
--
MfG - Lupus Goebel
Der Sumpf- und Morasthobbybastler und Anfaenger mit
Wissensdurst (http://www.lupusdw.de)
Meine private FAQ http://www.lupusdw.de/faq
Henry Habermacher [MVP Access]
2006-11-29 03:37:37 UTC
Permalink
Hallo Lupus
... tonnenweise Code gestrippt ...
Post by Lupus Goebel
Dateityp
HTML Document
Adobe Acrobat 7.0 Document
Cascading Style Sheet-Dokument
IrfanView PNG File
Mit dem Dateityp muss ich Verknüpfungen machen. Was nun aber wenn ein
User anstelle Adobe Acrobat 7 eben Adobe Acrobat *5* hat?
Daher suche ich nach einer Möglichkeit die mir eben *pdf* oder *asp*
etc. ausgibt.
Mein erster Gedanke wäre, dafür das Scripting.FileSystemObject zu verwenden,
weil das im Datei Handling wirklich sehr gut ist.

Hier ein Beispiel (mit Late Binding, musst also keinen Verweis auf die
Microsoft Scripting Runime setzen.

Public Function getFileType(strFileName) As String
Dim objFS As Object
Set objFS = CreateObject("Scripting.FileSystemObject")
getFileType = objFS.GetExtensionName(strFileName)
End Function

Aufruf im Direktfenster:

? getFileType("C:\Foo 1.1.2006.bar")
bar

Dabei interessiert es die Funktion GEtExtensionName überhaupt nicht, ob die
Datei existiert oder nicht. Sie liefert einfach das zurück, was auch das
Betriebssystem als Dateityp bestimmen würde.

HTH

Henry
--
Keine E-Mails auf Postings in NGs senden!
KB: http://support.microsoft.com/default.aspx
FAQ: http://www.donkarl.com (neu mit Suchfunktion!)
OH: Online Hilfe von Microsoft Access (Taste F1)
Downloads: http://www.dbdev.org
Lupus Goebel
2006-11-29 08:55:50 UTC
Permalink
Morsche,
Post by Henry Habermacher [MVP Access]
Post by Lupus Goebel
Daher suche ich nach einer Möglichkeit die mir eben *pdf* oder *asp*
etc. ausgibt.
Mein erster Gedanke wäre, dafür das Scripting.FileSystemObject zu
verwenden, weil das im Datei Handling wirklich sehr gut ist.
Hier ein Beispiel (mit Late Binding, musst also keinen Verweis auf die
Microsoft Scripting Runime setzen.
Public Function getFileType(strFileName) As String
Dim objFS As Object
Set objFS = CreateObject("Scripting.FileSystemObject")
getFileType = objFS.GetExtensionName(strFileName)
End Function
Hat das ein Vorteil gegenüber der Lösung von Mark?
--
MfG - Lupus Goebel
Der Sumpf- und Morasthobbybastler und Anfaenger mit
Wissensdurst (http://www.lupusdw.de)
Meine private FAQ http://www.lupusdw.de/faq
Henry Habermacher [MVP Access]
2006-11-29 10:10:43 UTC
Permalink
Hallo Lupus
Post by Lupus Goebel
Post by Henry Habermacher [MVP Access]
Public Function getFileType(strFileName) As String
Dim objFS As Object
Set objFS = CreateObject("Scripting.FileSystemObject")
getFileType = objFS.GetExtensionName(strFileName)
End Function
Hat das ein Vorteil gegenüber der Lösung von Mark?
Der Vorteil liegt darin, dass es den Typen zurückliefert, den auch das
Betriebssystem auslesen würde.

Versuch' mal folgendes:
? getfiletype("c:\test.dir\test")

Also den Typen einer Datei zu ermitteln, welche keine Extension hat und in
einem Verzeichnis liegt, das einen (erlaubten) Punkt drin hat.
Obiges liefert richtigerweise den Typen Empty zurück. Die von Mark
angedeutete Lösung mit InStrRev liefert wohl dann "dir\test" als DAteityp
zurück, wobei \ ein verbotenes Zeichen für eine Extension ist.

Der andere Vorteil ist der, dass man ja in der Regel dann etwas mit der
Datei machen möchte und das FSO eben ermöglicht viele Dinge ziemlich einfach
zu erledigen, welche oft auch mit VBA, aber dann einiges umständlicher
möglich sind.

Gruss
Henry
--
Keine E-Mails auf Postings in NGs senden!
KB: http://support.microsoft.com/default.aspx
FAQ: http://www.donkarl.com (neu mit Suchfunktion!)
OH: Online Hilfe von Microsoft Access (Taste F1)
Downloads: http://www.dbdev.org
Mark Doerbandt
2006-11-29 10:25:21 UTC
Permalink
Hallo, Henry,
Post by Henry Habermacher [MVP Access]
? getfiletype("c:\test.dir\test")
Die von Mark angedeutete Lösung mit InStrRev liefert wohl dann
"dir\test" als DAteityp zurück, ...
ok, dann muesste man noch auf \ pruefen...

Gruss - Mark
Henry Habermacher [MVP Access]
2006-11-29 11:12:20 UTC
Permalink
Hallo Mark
Post by Mark Doerbandt
Post by Henry Habermacher [MVP Access]
? getfiletype("c:\test.dir\test")
Die von Mark angedeutete Lösung mit InStrRev liefert wohl dann
"dir\test" als DAteityp zurück, ...
ok, dann muesste man noch auf \ pruefen...
... war nur ein Beispiel, wieso ein bereits existierender Mechanismus
Vorteile hat. Andere Fälle wären andere nicht erlaubte Sonderzeichen, Datei
im Root, ohne dass diese eine Extension hat, UNC Pfade ohne \, etc.
Selbstvertänglich ist Dein Ansatz in den allermeisten Fällen mehr als
ausreichend.

Gruss
Henry
--
Keine E-Mails auf Postings in NGs senden!
KB: http://support.microsoft.com/default.aspx
FAQ: http://www.donkarl.com (neu mit Suchfunktion!)
OH: Online Hilfe von Microsoft Access (Taste F1)
Downloads: http://www.dbdev.org
Mark Doerbandt
2006-11-29 11:32:14 UTC
Permalink
Hallo, Henry,
Post by Henry Habermacher [MVP Access]
Selbstvertänglich ist Dein Ansatz in den allermeisten Fällen mehr als
ausreichend.
interessant waere mal ein Performancevergleich. Natuerlich hat die im
Betriebssystem "eingebaute" Loesung (FSO) Vorteile, da sie die
erlaubten und unerlaubten Faellen alle kennt. Dafuer nimmt man aber
die Instanziierung eines Objektes in Kauf. Hast Du Erfahrungen, was
das fuer einen Performanceunterschied macht und welcher Speicher
dafuer belegt wird?

Evtl. ist FSO ja sogar schneller, was den Durchlauf von vielen Dateien
angeht. Ich habe mal vor langer Zeit eine kleine DB bereitgestellt,
die mit Dir etc. die ganze Platte durchwandert und eine
Platzauswertung macht (DiskSpace.mdb). Wenn ich mal Zeit habe, werde
ich die mit FSO reimplementieren und einen Performancevergleich
machen.

Gruss - Mark
Henry Habermacher [MVP Access]
2006-11-29 12:46:02 UTC
Permalink
Hallo Mark
Post by Mark Doerbandt
interessant waere mal ein Performancevergleich. Natuerlich hat die im
Betriebssystem "eingebaute" Loesung (FSO) Vorteile, da sie die
erlaubten und unerlaubten Faellen alle kennt. Dafuer nimmt man aber
die Instanziierung eines Objektes in Kauf. Hast Du Erfahrungen, was
das fuer einen Performanceunterschied macht und welcher Speicher
dafuer belegt wird?
Das FSO ist zwar nicht langsam, aber eine Objekt Instanziierung inkl. dem
Laden der Typelibrary zu einem Objekt ist sicher wesentlich langsamer als
eine reine Stringmanipulation. Bei den heutigen Computern ist dies jedoch in
der Regel nicht mehr spürbar. Schneller wird es, wenn das Objekt nicht
instanziiert werden muss, also über die Referenzen deklariert wird, welche
beim Starten der Anwendung einmal geladen werden, dafür handelt man sich das
Risiko zerschossener Referenzen ein.
Post by Mark Doerbandt
Evtl. ist FSO ja sogar schneller, was den Durchlauf von vielen Dateien
angeht. Ich habe mal vor langer Zeit eine kleine DB bereitgestellt,
die mit Dir etc. die ganze Platte durchwandert und eine
Platzauswertung macht (DiskSpace.mdb). Wenn ich mal Zeit habe, werde
ich die mit FSO reimplementieren und einen Performancevergleich
machen.
Mal abgesehen, dass das Folder Object eine Size-Property hat, welche die
Grösse des Ordners ausgibt (Summe aller Dateien im Ordner inkl. aller
Unterordner), kannst Du aber auch mit der SubFolders Collection und
rekursivem Funktionsaufruf die effektive Filegrösse durch Aufsummieren
selber ermitteln. Das Schöne daran ist: Solche Dinge lassen sich mit dem FSO
wirklich einfach wartbar programmieren. Mit Dir() und String Manipulationen
ist ähnlicher Code nur mehr schwer lesbar.

Hier ein triviales Beispiel, das das für einen Ordner alle Dateien durchgeht
und die Summe der Dateigrössen je Ordner im Debugfenster ausgibt. Dann geht
es durch alle Unterordner des Ordners durch (in einem rekursiven Aufruf).
Als Endergebnis wird dann die Summe aller Summen als Zahl zurückgegeben.

Public Function calcSumFileSize(strPath As String) As Double
Dim fso As Object 'early binding: FileSystemObject
Set fso = CreateObject("Scripting.FileSystemObject")
Dim fd As Object 'early binding: Folder
Dim fl As Object 'early binding: File
Dim sz As Double 'Size in Bytes
If Right(strPath, 1) <> "\" Then strPath = strPath & "\"
sz = 0
Set fd = fso.GetFolder(strPath)
For Each fl In fd.Files
sz = sz + fl.Size
Next
Debug.Print "Size " & strPath & " = " & Format(sz, "#,##0 Bytes")
For Each fd In fd.SubFolders
sz = sz + calcSumFileSize(strPath & fd.Name)
Next
calcSumFileSize = sz
End Function

Aufruf im Direktfenster für D:\MSDN ergibt z.B.

? "Total: " & Format(calcSumFileSize("d:\msdn"), "#,##0 Bytes")
Size d:\msdn\ = 0 Bytes
Size d:\msdn\MSDN8.0\ = 0 Bytes
Size d:\msdn\MSDN8.0\1033\ = 66'010 Bytes
Size d:\msdn\MSDN8.0\Common\ = 136'530 Bytes
Size d:\msdn\MSDN8.0\Common\1033\ = 277'412'639 Bytes
Size d:\msdn\MSDN8.0\Global\ = 0 Bytes
Size d:\msdn\MSDN8.0\Global\1033\ = 263'258 Bytes
Size d:\msdn\MSDN8.0\kb10\ = 0 Bytes
Size d:\msdn\MSDN8.0\kb10\1033\ = 132'349'020 Bytes
Size d:\msdn\MSDN8.0\Language Neutral Files\ = 0 Bytes
Size d:\msdn\MSDN8.0\Language Neutral Files\entserv10\ = 87'503'742 Bytes
Size d:\msdn\MSDN8.0\Language Neutral Files\eosadd10\ = 12'123'021 Bytes
Size d:\msdn\MSDN8.0\Language Neutral Files\foxpro\ = 11'602'901 Bytes
Size d:\msdn\MSDN8.0\Language Neutral Files\Glob_neu\ = 63'096 Bytes
Size d:\msdn\MSDN8.0\Language Neutral Files\mobembdev10\ = 47'695'451 Bytes
Size d:\msdn\MSDN8.0\Language Neutral Files\netdev10\ = 99'224'132 Bytes
Size d:\msdn\MSDN8.0\Language Neutral Files\offadd10\ = 45'238'386 Bytes
Size d:\msdn\MSDN8.0\Language Neutral Files\sak30\ = 1'971'464 Bytes
Size d:\msdn\MSDN8.0\Language Neutral Files\sql2000\ = 23'428'747 Bytes
Size d:\msdn\MSDN8.0\Language Neutral Files\sqladd10\ = 28'686'633 Bytes
Size d:\msdn\MSDN8.0\Language Neutral Files\vsadd10\ = 47'181'955 Bytes
Size d:\msdn\MSDN8.0\Language Neutral Files\webdev10\ = 44'794'545 Bytes
Size d:\msdn\MSDN8.0\Language Neutral Files\win32com10\ = 175'946'006 Bytes
Size d:\msdn\MSDN8.0\Language Neutral Files\wince50\ = 38'286'102 Bytes
Size d:\msdn\MSDN8.0\netdevfx20\ = 0 Bytes
Size d:\msdn\MSDN8.0\netdevfx20\1033\ = 213'564'306 Bytes
Size d:\msdn\MSDN8.0\office11\ = 0 Bytes
Size d:\msdn\MSDN8.0\office11\1033\ = 37'643'663 Bytes
Size d:\msdn\MSDN8.0\sql2005\ = 0 Bytes
Size d:\msdn\MSDN8.0\sql2005\1033\ = 97'536'083 Bytes
Size d:\msdn\MSDN8.0\Visual Studio 8.0\ = 0 Bytes
Size d:\msdn\MSDN8.0\Visual Studio 8.0\1033\ = 199'113'174 Bytes
Size d:\msdn\MSDN8.0\vsent80\ = 0 Bytes
Size d:\msdn\MSDN8.0\vsent80\1033\ = 10'097'918 Bytes
Total: 1'631'928'782 Bytes

und ist blitzschnell fertig.

Nett, gell?

Gruss
Henry
--
Keine E-Mails auf Postings in NGs senden!
KB: http://support.microsoft.com/default.aspx
FAQ: http://www.donkarl.com (neu mit Suchfunktion!)
OH: Online Hilfe von Microsoft Access (Taste F1)
Downloads: http://www.dbdev.org
Mark Doerbandt
2006-11-29 12:56:53 UTC
Permalink
Hallo, Henry,
Post by Henry Habermacher [MVP Access]
Hier ein triviales Beispiel, das das für einen Ordner alle Dateien durchgeht
und die Summe der Dateigrössen je Ordner im Debugfenster ausgibt. Dann geht
es durch alle Unterordner des Ordners durch (in einem rekursiven Aufruf).
Als Endergebnis wird dann die Summe aller Summen als Zahl zurückgegeben.
oh, ja: sieht gut aus!

Ich werde das dieser Tage mal gegen mein DiskSpace.mdb laufen lassen
und hier wieder posten.

Gruss - Mark
Henry Habermacher [MVP Access]
2006-11-29 13:03:28 UTC
Permalink
Hallo Mark
Post by Mark Doerbandt
Ich werde das dieser Tage mal gegen mein DiskSpace.mdb laufen lassen
und hier wieder posten.
Das Ergebnis interessiert mich. Bitte mal mit Early und mal mit Late Binding
testen, zum Vergleich.

Watch auf Thread gesetzt.

Gruss
Henry
--
Keine E-Mails auf Postings in NGs senden!
KB: http://support.microsoft.com/default.aspx
FAQ: http://www.donkarl.com (neu mit Suchfunktion!)
OH: Online Hilfe von Microsoft Access (Taste F1)
Downloads: http://www.dbdev.org
Jörg Ostendorp
2006-11-29 18:51:21 UTC
Permalink
Hallo Mark, Henry,
Post by Henry Habermacher [MVP Access]
Post by Mark Doerbandt
Ich werde das dieser Tage mal gegen mein DiskSpace.mdb laufen lassen
und hier wieder posten.
Das Ergebnis interessiert mich.
mich auch. Und wenn Du eh schon dabei bist, mach doch auch mal einen Test
mit FindFirsFile/FindNextFile und GetFileAttributes/ShGetFileInformation
etc. :-)
--
Grüßle vom Bodensee
Jörg Ostendorp

- Access-FAQ: www.donkarl.com
- my home: www.meersburg.de
Henry Habermacher [MVP Access]
2006-11-30 01:40:05 UTC
Permalink
Hallo Jörg
Post by Jörg Ostendorp
mich auch. Und wenn Du eh schon dabei bist, mach doch auch mal einen
Test mit FindFirsFile/FindNextFile und
GetFileAttributes/ShGetFileInformation etc. :-)
Das macht er nur, wenn Du ihm fertigen Beispielcode wie ich lieferst. Also
her mit dem 10-Zeiler, oder wird es mehr, wenn man API Calls macht? ;-)

Gruss
Henry
--
Keine E-Mails auf Postings in NGs senden!
KB: http://support.microsoft.com/default.aspx
FAQ: http://www.donkarl.com (neu mit Suchfunktion!)
OH: Online Hilfe von Microsoft Access (Taste F1)
Downloads: http://www.dbdev.org
Jörg Ostendorp
2006-11-30 09:58:23 UTC
Permalink
Hallo Henry,
Post by Henry Habermacher [MVP Access]
Post by Jörg Ostendorp
mich auch. Und wenn Du eh schon dabei bist, mach doch auch mal einen
Test mit FindFirsFile/FindNextFile und
GetFileAttributes/ShGetFileInformation etc. :-)
Das macht er nur, wenn Du ihm fertigen Beispielcode wie ich lieferst. Also
her mit dem 10-Zeiler, oder wird es mehr, wenn man API Calls macht? ;-)
Wenn Mark sagt, welche Funktionen er da genau seiner DiskSpace.mdb testen
will, gern. Bezogen auf Dein Beispiel dachte ich an sowas:

http://www.allapi.net/apilist/DAD43CF20ED09D1897B0ECAAF0BF86EE.html

Und mit ein paar Doppelpunkten ist das auch in 10 Zeilen machbar ;-)
--
Grüßle vom Bodensee
Jörg Ostendorp

- Access-FAQ: www.donkarl.com
- my home: www.meersburg.de
Mark Doerbandt
2006-11-30 10:09:37 UTC
Permalink
Hallo, Jörg,
Post by Jörg Ostendorp
Und mit ein paar Doppelpunkten ist das auch in 10 Zeilen machbar ;-)
na, dann mach doch mal ein Beispiel. Meine DiskSpace.mdb ist alt und
nutzt Dir etc., Henries FSO und Deine API-Lösung analog dazu. ich
mache dann einen gemeinsamen Performance-Test und stelle die
Beispiel-DB online.

Gruss - Mark
Stefan Hoffmann
2006-11-30 10:30:10 UTC
Permalink
tach Mark,
Post by Mark Doerbandt
na, dann mach doch mal ein Beispiel. Meine DiskSpace.mdb ist alt und
nutzt Dir etc., Henries FSO und Deine API-Lösung analog dazu. ich
mache dann einen gemeinsamen Performance-Test und stelle die
Beispiel-DB online.
http://vbnet.mvps.org/index.html?code/fileapi/fsoapicompare.htm

kennt ihr?


mfG
--> stefan <--
Mark Doerbandt
2006-11-30 10:36:23 UTC
Permalink
Hallo, Stefan,
Post by Stefan Hoffmann
http://vbnet.mvps.org/index.html?code/fileapi/fsoapicompare.htm
kennt ihr?
noe, noch nicht - aber Du ersparst mir einige Tests! ;-)

Dank & Gruss - Mark
Henry Habermacher [MVP Access]
2006-11-30 10:37:17 UTC
Permalink
Hallo Stefan
Post by Stefan Hoffmann
http://vbnet.mvps.org/index.html?code/fileapi/fsoapicompare.htm
Sieht schon mal gut aus. Lediglich eine Verdoppelung gegenüber API Calls,
das scheint mir ziemlich gut zu sein. Jetzt fehlt nur noch der Vergleich mit
Early/Late Binding und dann noch mit der herkömmlichen VBA-Dir() Methode und
String Manipulationen.

Gruss
Henry
--
Keine E-Mails auf Postings in NGs senden!
KB: http://support.microsoft.com/default.aspx
FAQ: http://www.donkarl.com (neu mit Suchfunktion!)
OH: Online Hilfe von Microsoft Access (Taste F1)
Downloads: http://www.dbdev.org
Jörg Ostendorp
2006-11-30 10:49:14 UTC
Permalink
Hallo Stefan,
Post by Stefan Hoffmann
Post by Mark Doerbandt
na, dann mach doch mal ein Beispiel. Meine DiskSpace.mdb ist alt und
nutzt Dir etc., Henries FSO und Deine API-Lösung analog dazu. ich
mache dann einen gemeinsamen Performance-Test und stelle die
Beispiel-DB online.
http://vbnet.mvps.org/index.html?code/fileapi/fsoapicompare.htm
kennt ihr?
Ja, aber den Testaufbau von Randy finde ich ein wenig unbrauchbar für einen
Performance-Vergleich der Funktionen, da er die Zeit für das Hinzufügen ins
ListView mitberechnet. Wenn der Api-Call z.B. 2 Sekunden dauern würde, FSO
hingegen 4 Sekunden, dann wäre Api-Call nur doppelt so schnell. Wenn Du
hingegen die Zeit für die reichlich lahme ListView-Steuerung abziehst,
kommst Du vermutlich zu einem ganz anderen Verhältnis...
--
Grüßle vom Bodensee
Jörg Ostendorp

- Access-FAQ: www.donkarl.com
- my home: www.meersburg.de
Henry Habermacher [MVP Access]
2006-11-30 11:00:37 UTC
Permalink
Hallo Jörg
Post by Jörg Ostendorp
Ja, aber den Testaufbau von Randy finde ich ein wenig unbrauchbar für
einen Performance-Vergleich der Funktionen, da er die Zeit für das
Hinzufügen ins ListView mitberechnet. Wenn der Api-Call z.B. 2
Sekunden dauern würde, FSO hingegen 4 Sekunden, dann wäre Api-Call
nur doppelt so schnell. Wenn Du hingegen die Zeit für die reichlich
lahme ListView-Steuerung abziehst, kommst Du vermutlich zu einem ganz
anderen Verhältnis...
Ertappt! (ich habe gehofft, es merk's niemand)

Also liefere endlich den Code, damit Mark testen kann ;-)

Gruss
Henry
--
Keine E-Mails auf Postings in NGs senden!
KB: http://support.microsoft.com/default.aspx
FAQ: http://www.donkarl.com (neu mit Suchfunktion!)
OH: Online Hilfe von Microsoft Access (Taste F1)
Downloads: http://www.dbdev.org
Jörg Ostendorp
2006-11-30 11:38:28 UTC
Permalink
Hallo Henry,
Post by Henry Habermacher [MVP Access]
Also liefere endlich den Code, damit Mark testen kann ;-)
Ich hab mal beide Funktionen etwas angepaßt, so daß nur die Dateigrößen
addiert werden. FSO ist formularweit dimensioniert und wird nur einmal
außerhalb der Zeitmessung instanziert (sollte also keinen Unterschied zu
Early Binding ergeben ?).

Komme mit folgendem Testszenario etwa auf ein Verhältnis Api:FSO von 1:2,5.

Code im Formular mit 2 CommandButtons:

Option Compare Database
Option Explicit

Private Declare Function FindFirstFile _
Lib "kernel32" _
Alias "FindFirstFileA" ( _
ByVal lpFileName As String, _
lpFindFileData As WIN32_FIND_DATA _
) As Long

Private Declare Function FindNextFile _
Lib "kernel32" _
Alias "FindNextFileA" ( _
ByVal hFindFile As Long, _
lpFindFileData As WIN32_FIND_DATA _
) As Long

Private Declare Function GetFileAttributes _
Lib "kernel32" _
Alias "GetFileAttributesA" ( _
ByVal lpFileName As String _
) As Long

Private Declare Function FindClose _
Lib "kernel32" ( _
ByVal hFindFile As Long _
) As Long
Private Declare Function QueryPerformanceCounter _
Lib "kernel32" ( _
x As Currency _
) As Boolean

Private Declare Function QueryPerformanceFrequency _
Lib "kernel32" ( _
x As Currency _
) As Boolean

Const MAX_PATH = 260
Const MAXDWORD = &HFFFF
Const INVALID_HANDLE_VALUE = -1
Const FILE_ATTRIBUTE_ARCHIVE = &H20
Const FILE_ATTRIBUTE_DIRECTORY = &H10
Const FILE_ATTRIBUTE_HIDDEN = &H2
Const FILE_ATTRIBUTE_NORMAL = &H80
Const FILE_ATTRIBUTE_READONLY = &H1
Const FILE_ATTRIBUTE_SYSTEM = &H4
Const FILE_ATTRIBUTE_TEMPORARY = &H100

Private Type FILETIME
dwLowDateTime As Long
dwHighDateTime As Long
End Type

Private Type WIN32_FIND_DATA
dwFileAttributes As Long
ftCreationTime As FILETIME
ftLastAccessTime As FILETIME
ftLastWriteTime As FILETIME
nFileSizeHigh As Long
nFileSizeLow As Long
dwReserved0 As Long
dwReserved1 As Long
cFileName As String * MAX_PATH
cAlternate As String * 14
End Type

Dim fso As Object


Function StripNulls(OriginalStr As String) As String
If (InStr(OriginalStr, Chr(0)) > 0) Then
OriginalStr = Left$(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)
End If
StripNulls = OriginalStr
End Function

Function FindFilesAPI(path As String, SearchStr As String, _
FileCount As Long, DirCount As Long)
'KPD-Team 1999
'E-Mail: ***@Allapi.net
'URL: http://www.allapi.net/
On Error Resume Next
Dim FileName As String ' Walking filename variable...
Dim DirName As String ' SubDirectory Name
Dim dirNames() As String ' Buffer for directory name entries
Dim nDir As Long ' Number of directories in this path
Dim i As Long ' For-loop counter...
Dim hSearch As Long ' Search Handle
Dim WFD As WIN32_FIND_DATA
Dim Cont As Long
If Right$(path, 1) <> "\" Then path = path & "\"
' Search for subdirectories.
nDir = 0
ReDim dirNames(nDir)
Cont = True
hSearch = FindFirstFile(path & "*", WFD)
If hSearch <> INVALID_HANDLE_VALUE Then
Do While Cont
DirName = StripNulls(WFD.cFileName)
' Ignore the current and encompassing directories.
If (DirName <> ".") And (DirName <> "..") Then
' Check for directory with bitwise comparison.
If GetFileAttributes(path & DirName) And _
FILE_ATTRIBUTE_DIRECTORY Then
dirNames(nDir) = DirName
DirCount = DirCount + 1
nDir = nDir + 1
ReDim Preserve dirNames(nDir)
End If
End If
Cont = FindNextFile(hSearch, WFD) 'Get next subdirectory.
Loop
Cont = FindClose(hSearch)
End If
' Walk through this directory and sum file sizes.
hSearch = FindFirstFile(path & SearchStr, WFD)
Cont = True
If hSearch <> INVALID_HANDLE_VALUE Then
While Cont
FileName = StripNulls(WFD.cFileName)
If (FileName <> ".") And (FileName <> "..") Then
FindFilesAPI = FindFilesAPI + _
(WFD.nFileSizeHigh * MAXDWORD) + WFD.nFileSizeLow
FileCount = FileCount + 1
'List1.AddItem Left(path & FileName, 250)
End If
Cont = FindNextFile(hSearch, WFD) ' Get next file
Wend
Cont = FindClose(hSearch)
End If
' If there are sub-directories...
If nDir > 0 Then
' Recursively walk into them...
For i = 0 To nDir - 1
FindFilesAPI = FindFilesAPI + _
FindFilesAPI(path & dirNames(i) & "\", _
SearchStr, FileCount, DirCount)
Next i
End If
End Function

Private Sub Command0_Click()
Dim SearchPath As String
Dim FindStr As String
Dim FileSize As Double
Dim NumFiles As Long
Dim NumDirs As Long
Dim curStart As Currency
Dim curEnde As Currency
Dim curF As Currency
SearchPath = "D:\"
FindStr = "*"
QueryPerformanceFrequency curF
QueryPerformanceCounter curStart
FileSize = FindFilesAPI(SearchPath, _
FindStr, _
NumFiles, _
NumDirs) _
/ 1000000

QueryPerformanceCounter curEnde
MsgBox Format(FileSize * 1000000, "#,###,###,##0") & " Bytes"
MsgBox "Zeit: " & Format((curEnde - curStart) * 1000 / _
curF, "#.00 \m\s")
End Sub

Private Sub Command11_Click()
Dim SearchPath As String
Dim FindStr As String
Dim FileSize As Double
Dim curStart As Currency
Dim curEnde As Currency
Dim curF As Currency

Set fso = CreateObject("Scripting.FileSystemObject")

SearchPath = "D:\"
FindStr = "*"

QueryPerformanceFrequency curF
QueryPerformanceCounter curStart

FileSize = calcSumFileSize(SearchPath)
QueryPerformanceCounter curEnde
MsgBox Format(FileSize * 1000000, "#,###,###,##0") & " Bytes"
MsgBox "Zeit: " & Format((curEnde - curStart) * 1000 / _
curF, "#.00 \m\s")

End Sub

Public Function calcSumFileSize(strPath As String) As Double
On Error Resume Next
Dim fd As Object
Dim fl As Object
Dim sz As Double
If Right$(strPath, 1) <> "\" Then strPath = strPath & "\"
sz = 0
Set fd = fso.GetFolder(strPath)
For Each fl In fd.Files
sz = sz + fl.Size / 1000000
Next

For Each fd In fd.SubFolders
sz = sz + calcSumFileSize(strPath & fd.Name)
Next
calcSumFileSize = sz
End Function
--
Grüßle vom Bodensee
Jörg Ostendorp

- Access-FAQ: www.donkarl.com
- my home: www.meersburg.de
Henry Habermacher [MVP Access]
2006-11-30 12:55:26 UTC
Permalink
Hallo Jörg
Post by Jörg Ostendorp
Ich hab mal beide Funktionen etwas angepaßt, so daß nur die
Dateigrößen addiert werden. FSO ist formularweit dimensioniert und
wird nur einmal außerhalb der Zeitmessung instanziert (sollte also
keinen Unterschied zu Early Binding ergeben ?).
Die Variablen fl und fd sind aber weiterhin über Late Binding drin (als
Object deklariert) und müssen zur Laufzeit an den Datentypen gebunden
werden, die die benutzte Methode liefert (File und Folder). Ein gewisser
Unterschied wird da schon vorhanden sein.

2.5 : 1 ist ein guter Wert für das FSO im Vergleich zu API Calls, Ich hätte
wesentlich schlechtere Werte erwartet.

Wie lange dauert es bei Dir, wenn Du mit Deinem Code die Summe der FileSizes
ermittelst? Mach zum Vergleich nur mal auf dem Root Folder in FSO die
Methode fl.getSize auf. Ich vermute, diese geht auch über API alle Ordner
durch und ermittelt die Grösse. Wäre nun interessant diese Werte zu
vergleichen. Evt. ist hier das FSO sogar schneller, weil es die Kontrolle
nicht mehr an VBA zurückgeben muss, sondern einfach die Session blockiert,
bis die Grösse ermittelt worden ist.

Gruss
Henry
Jörg Ostendorp
2006-11-30 23:18:10 UTC
Permalink
Hallo Henry,
Post by Henry Habermacher [MVP Access]
2.5 : 1 ist ein guter Wert für das FSO im Vergleich zu API Calls, Ich hätte
wesentlich schlechtere Werte erwartet.
Naja, 2.5 zu 1 bezieht sich ja nur auf den konkreten Code...
Und ob das gut oder schlecht ist würde ich letztlich an der Gesamtlaufzeit
festmachen wollen. Ob Du 0,1 oder 0,25 Sekunden wartest ist wirklich
ziemlich Schnuppe, bei Stunden schauts dann halt anders aus.

Aber generell ist FSO ja auch nicht unbedingt langsam. Nur überflüssig :-)
Post by Henry Habermacher [MVP Access]
Wie lange dauert es bei Dir, wenn Du mit Deinem Code die Summe der FileSizes
ermittelst?
? Wie meinst Du, in Sekunden? Habs jetzt hier auf einem Laufwerk mit ca.
50.000 Dateien getestet. Wenn der Suchindex aufgebaut ist, ist das
Verhältnis etwa 3,5 Sekunden für die Api-Version und 9 Sekunden für FSO.
Post by Henry Habermacher [MVP Access]
Mach zum Vergleich nur mal auf dem Root Folder in FSO die
Methode fl.getSize auf. Ich vermute, diese geht auch über API alle Ordner
durch und ermittelt die Grösse. Wäre nun interessant diese Werte zu
vergleichen.
? Öh, ich finde keine Methode .GetSize.
Post by Henry Habermacher [MVP Access]
Evt. ist hier das FSO sogar schneller, weil es die Kontrolle
nicht mehr an VBA zurückgeben muss, sondern einfach die Session blockiert,
bis die Grösse ermittelt worden ist.
Eine Blockade ist natürlich höchst erstrebenswert ;-) SCNR
--
Grüßle vom Bodensee
Jörg Ostendorp

- Access-FAQ: www.donkarl.com
- my home: www.meersburg.de
Henry Habermacher [MVP Access]
2006-12-01 01:19:25 UTC
Permalink
Hallo Jörg
Post by Jörg Ostendorp
Post by Henry Habermacher [MVP Access]
Mach zum Vergleich nur mal auf dem Root Folder in FSO die
Methode fl.getSize auf. Ich vermute, diese geht auch über API alle
Ordner durch und ermittelt die Grösse. Wäre nun interessant diese
Werte zu vergleichen.
? Öh, ich finde keine Methode .GetSize.
Sorry, ich meinte Folder.Size

würde etwa so aussehen:
Public Function getFolderSize(strPath As String) As Double
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
getFolderSize = fso.GetFolder(strPath).Size
End Function
Post by Jörg Ostendorp
Post by Henry Habermacher [MVP Access]
Evt. ist hier das FSO sogar schneller, weil es die Kontrolle
nicht mehr an VBA zurückgeben muss, sondern einfach die Session
blockiert, bis die Grösse ermittelt worden ist.
Eine Blockade ist natürlich höchst erstrebenswert ;-) SCNR
Es wird natürlich nicht das ganze System blockiert, einfach die Anwendung,
welche gerade versucht, die Grössen zu ermitteln, zeigt die Sanduhr und
reagiert nicht mehr auf Interaktionen.

Gruss
Henry
Jörg Ostendorp
2006-12-01 12:06:39 UTC
Permalink
Hallo Henry,
Post by Henry Habermacher [MVP Access]
Public Function getFolderSize(strPath As String) As Double
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
getFolderSize = fso.GetFolder(strPath).Size
End Function
Post by Henry Habermacher [MVP Access]
Evt. ist hier das FSO sogar schneller, weil es die Kontrolle
nicht mehr an VBA zurückgeben muss, sondern einfach die Session
blockiert, bis die Grösse ermittelt worden ist.
Jipp, FSO läuft bei mir auf diese Weise für einen einzelnen Ordner etwa
sechs Mal so schnell durch wie die Api-Variante. Unverschämtheit! ;-)
--
Grüßle vom Bodensee
Jörg Ostendorp

- Access-FAQ: www.donkarl.com
- my home: www.meersburg.de
Henry Habermacher [MVP Access]
2006-12-06 02:13:55 UTC
Permalink
Hallo Jörg
Post by Jörg Ostendorp
Jipp, FSO läuft bei mir auf diese Weise für einen einzelnen Ordner
etwa sechs Mal so schnell durch wie die Api-Variante.
Unverschämtheit! ;-)
LOL! Ist das das Ende des APIs?

Henry
--
Keine E-Mails auf Postings in NGs senden!
KB: http://support.microsoft.com/default.aspx
FAQ: http://www.donkarl.com (neu mit Suchfunktion!)
OH: Online Hilfe von Microsoft Access (Taste F1)
Downloads: http://www.dbdev.org
Jörg Ostendorp
2006-12-06 10:37:46 UTC
Permalink
Hallo Henry,
Post by Henry Habermacher [MVP Access]
Post by Jörg Ostendorp
Jipp, FSO läuft bei mir auf diese Weise für einen einzelnen Ordner
etwa sechs Mal so schnell durch wie die Api-Variante.
Unverschämtheit! ;-)
LOL! Ist das das Ende des APIs?
tse, träum weiter! ;-)
--
Grüßle vom Bodensee
Jörg Ostendorp

- Access-FAQ: www.donkarl.com
- my home: www.meersburg.de
Lupus Goebel
2006-12-01 14:55:16 UTC
Permalink
Tach,

Am 29.11.2006 13:46 schrieb Henry Habermacher [MVP Access]:

[...]
Post by Henry Habermacher [MVP Access]
Public Function calcSumFileSize(strPath As String) As Double
Dim fso As Object 'early binding: FileSystemObject
Set fso = CreateObject("Scripting.FileSystemObject")
Dim fd As Object 'early binding: Folder
Dim fl As Object 'early binding: File
Dim sz As Double 'Size in Bytes
If Right(strPath, 1) <> "\" Then strPath = strPath & "\"
sz = 0
Set fd = fso.GetFolder(strPath)
For Each fl In fd.Files
sz = sz + fl.Size
Next
Debug.Print "Size " & strPath & " = " & Format(sz, "#,##0 Bytes")
For Each fd In fd.SubFolders
sz = sz + calcSumFileSize(strPath & fd.Name)
Next
calcSumFileSize = sz
End Function
So kanns kommen. Hätte ich nicht gefragt hätte ich diesen Code evtl. nie
zu sehen bekommen. Diese Möglichkeit Ordner und Unterordner einzulesen
kannte ich nicht. Ist jedoch weit aus schneller wie das was ich bisher
hatte. Vor allem, weit aus weniger Code.
habe daraufhin meine gesamte Anwendung umgeschrieben und alles sehr
vereinfacht.

Danke, das ist es was ich an NG so liebe. Man hofft auf *eine* Lösung
und bekommt gleich noch eine Gratis dazu, zu etwas wovon man dachte es
wäre schon gut. Super.

[...]
--
MfG - Lupus Goebel
Der Sumpf- und Morasthobbybastler und Anfaenger mit
Wissensdurst (http://www.lupusdw.de)
Meine private FAQ http://www.lupusdw.de/faq
Frank Müller
2006-11-29 03:49:38 UTC
Permalink
Hallo Lupus,
Post by Lupus Goebel
gibt es eine elegante Möglichkeit den Dateityp einer Datei auszulesen?
FSO mal nicht wichtig hier
Post by Lupus Goebel
Dateityp
HTML Document
Adobe Acrobat 7.0 Document
Cascading Style Sheet-Dokument
IrfanView PNG File
Das sieht aber nur bei dir so aus.
Weil was du da siehst entspricht genau dem was du auch
im Windows Explorer über die Eigenschaften der Datei siehst.
Und der Text kommt vom Namen der Anwendung die in deinem
Windows mit dem entsprechenden Dateityp verknüpft ist.

*.png z.B. hat überhaupt nichts mit IrfanView zu tun, wer den
nicht hat, sieht trotzdem diese Dateien halt in einer anderen Anwendung.
Post by Lupus Goebel
Mit dem Dateityp muss ich Verknüpfungen machen. Was nun aber wenn ein
User anstelle Adobe Acrobat 7 eben Adobe Acrobat *5* hat?
Gar nichts, es ist und bleibt eine pdf Datei und die wird halt mit
demjenigen
Programm geöffnet welches für diesen Dateityp auf dem jeweiligen Rechner
"zuständig" ist.

Aber was genau meinst du mit Verknüpfungen?
Möchtest du ermitteln welcher Dateityp zu welcher Anwendung beim
User gehört und genau dieses Programm aufrufen?
Post by Lupus Goebel
Daher suche ich nach einer Möglichkeit die mir eben *pdf* oder *asp*
etc. ausgibt.
Erster Gedanke, suche im Dateinamen nach einem Punkt und gebe mir das
aus was rechts davon steht.
Cool, meine Kollegen haben solche Dateinamen: "20.11.2006.xls"
Na die Endung steht immer nach dem letzten Punkt.
Mach es so wie Mark vorgeschlagen hat oder einfach ein Split auf
den Punkt im Dateinamen und dann ist der Inhalt des Ubound Elements
des Arrays deine Endung.

Die Dateiendung alleine sagt allerdings erst mal gar nichts darüber
aus, ob es auch eine Datei ist die zur Endung gehört. Man kann ja
z.B. eine *.png Datei auch in *.pdf umbenennen. Wenn du jetzt
feststellen möchtest ob die Endung auch zur Datei passt sieht die Sache
natürlich anders aus und ist wesentlich komplizierter.

Gruß,
Frank
Lupus Goebel
2006-11-29 08:53:58 UTC
Permalink
Morsche,
Post by Frank Müller
Post by Lupus Goebel
gibt es eine elegante Möglichkeit den Dateityp einer Datei auszulesen?
FSO mal nicht wichtig hier
Hätte ja sein können.
Post by Frank Müller
Post by Lupus Goebel
Dateityp
HTML Document
Adobe Acrobat 7.0 Document
Cascading Style Sheet-Dokument
IrfanView PNG File
Das sieht aber nur bei dir so aus.
Weil was du da siehst entspricht genau dem was du auch
im Windows Explorer über die Eigenschaften der Datei siehst.
Und der Text kommt vom Namen der Anwendung die in deinem
Windows mit dem entsprechenden Dateityp verknüpft ist.
*.png z.B. hat überhaupt nichts mit IrfanView zu tun, wer den
nicht hat, sieht trotzdem diese Dateien halt in einer anderen Anwendung.
Eben, deswegen frage ich ja nach.
Post by Frank Müller
Post by Lupus Goebel
Mit dem Dateityp muss ich Verknüpfungen machen. Was nun aber wenn ein
User anstelle Adobe Acrobat 7 eben Adobe Acrobat *5* hat?
Gar nichts, es ist und bleibt eine pdf Datei und die wird halt mit
demjenigen Programm geöffnet welches für diesen Dateityp auf dem jeweiligen Rechner
"zuständig" ist.
Aber was genau meinst du mit Verknüpfungen?
Möchtest du ermitteln welcher Dateityp zu welcher Anwendung beim
User gehört und genau dieses Programm aufrufen?
Nö, ich erstelle mit meiner Anwendung eine XML-Datei für Google.
Siehe: https://www.google.com/webmasters/tools/docs/de/protocol.html

In der Sitmap haben nur bestimmte Dateien was zu suchen, wie z.B html,
asp oder php.
Habe die Lösung von Mark genommen, mir hat halt nur der richtige
Suchbegriff gefehlt.

Danke.


[..]
--
MfG - Lupus Goebel
Der Sumpf- und Morasthobbybastler und Anfaenger mit
Wissensdurst (http://www.lupusdw.de)
Meine private FAQ http://www.lupusdw.de/faq
Christoph Juengling
2006-12-01 12:50:25 UTC
Permalink
Post by Lupus Goebel
Erster Gedanke, suche im Dateinamen nach einem Punkt und gebe mir das
aus was rechts davon steht.
Cool, meine Kollegen haben solche Dateinamen: "20.11.2006.xls"
Macht nix, der letzte Punkt zählt:

p = InstrRev(strDateiname, ".")

Chris
Loading...