2010-10-27 5 views
6

Ich habe ein Perl-Skript, das Daten aus einer Excel-Binärdatei (xls) liest. Aber der Client, der uns diese Dateien sendet, hat uns begonnen, uns Dateien im Format XLSX zu senden. Ich habe das Skript aktualisiert, um auch diese lesen zu können. Manchmal nennt der Client jedoch gerne die XLSX Dateien mit einer .xls Erweiterung, die derzeit das Ende meines Skripts verwirrt, da es den Dateinamen verwendet, um zu bestimmen, welcher Dateityp es ist.Wie kann mein Perl-Skript feststellen, ob eine Excel-Datei im XLS- oder XLSX-Format vorliegt?

Eine XLSX Datei ist eine Zip-Datei, die XML-Zeug enthält. Gibt es eine einfache Möglichkeit für mein Skript, sich die Datei anzusehen und festzustellen, ob es sich um eine ZIP-Datei handelt oder nicht? Wenn das der Fall ist, kann ich mein Skript anstelle des Dateinamens verwenden.

Antwort

16

XLSX-Dateien den ersten 2 Bytes als 'PK' haben, so dass eine einfache, offene und Prüfung der ersten 2 Zeichen zu tun.

+5

Um genauer zu sein, die ersten 4 Bytes sind "PK \ 003 \ 004" '. – cjm

+0

Obwohl dies wahrscheinlich für alle .xlsx-Dateien gilt, die von bestimmten Anwendungen erzeugt werden, ist dies im ZIP-Dateiformat nicht erforderlich - siehe http://en.wikipedia.org/wiki/Zip_file#Structure. –

+0

Ja! Das habe ich mir erhofft; eine schnelle und einfache Möglichkeit, eine Datei zu überprüfen, vorzugsweise ohne ein weiteres Modul zu verwenden. Vielen Dank! – DaveKub

-2

Ich kann nicht über Perl sagen, aber mit dem Framework, das ich verwende, .Net, gibt es eine Reihe von Bibliotheken zur Verfügung, die ZIP-Dateien bearbeiten können, die Sie verwenden könnten.

Eine andere Sache, die ich gesehen habe, ist die Befehlszeilenversion von WinZip. Es gibt einen Rückgabewert, der 0 ist, wenn eine Datei entpackt wird, und Null, wenn ein Fehler auftritt.

Dies ist möglicherweise nicht der beste Weg, dies zu tun, aber es ist ein Anfang.

2

Verwendung File::Type:

my $file = "foo.zip"; 
my $filetype = File::Type->new(); 

if($filetype->mime_type($file) eq 'application/zip') { 
    # File is a zip archive. 
    ... 
} 

Getestet habe ich es nur mit einer .xlsx-Datei und die mime_type() zurück application/zip. Ähnlich ist für eine .xls Datei die mime_type()application/octet-stream.

6

Edit: Archive :: Zip ist eine bessere

solution 
# Read a Zip file 
    my $somezip = Archive::Zip->new(); 
    unless ($somezip->read('someZip.zip') == AZ_OK) { 
     die 'read error'; 
    } 
+2

+1 Immer zuerst überprüfen CPAN :) – Konerak

+1

Dies funktioniert nicht - das verwendet das Dateinamensuffix, um den Dateityp zu bestimmen, siehe http://search.cpan.org/~bingos/Archive-Extract-0.46/ lib/Archiv/Extrakt.pm. Ich habe das erhöht, aber es ist zu spät und ich kann meine Stimme nicht entfernen. –

17

Ja, es ist möglich, indem Sie magic number überprüfen.

Es gibt einige Module in Perl zum Überprüfen magic number in einer Datei.

ein Beispiel unter Verwendung File::LibMagic:

use strict; 
use warnings; 

use File::LibMagic; 

my $lm = File::LibMagic->new(); 

if ($lm->checktype_filename($filename) eq 'application/zip; charset=binary') { 
    # XLSX format 
} 
elsif ($lm->checktype_filename($filename) eq 'application/vnd.ms-office; charset=binary') { 
    # XLS format 
} 

Ein weiteres Beispiel, mit File::Type:

use strict; 
use warnings; 

use File::Type; 

my $ft = File::Type->new(); 

if ($ft->mime_type($file) eq 'application/zip') { 
    # XLSX format 
} 
else { 
    # probably XLS format 
} 
+4

File :: Type ist ein ziemlich großes Modul. Da Sie nur an einem Dateityp interessiert sind, würde ich wahrscheinlich den Test von dort kopieren. Es wird nur überprüft, ob die ersten 4 Bytes der Datei "PK \ 003 \ 004" 'sind. – cjm

+1

+1 für libmagic. Die nächste Version wird viele Verbesserungen für zip-abgeleitete Dateitypen enthalten, siehe [Mailinglistenarchiv] (http://mx.gw.com/pipermail/file/2010/thread.html). – daxim

1

Sie können, indem Sie die ersten Bytes der Datei für Excel-Header die xls-Datei erfassen.

Eine Liste gültiger älteren Excel-Header können von hier geholt werden (es sei denn, Sie genaue Version ihrer Excel kennen, für alle anwendbaren Möglichkeiten prüfen):

http://toorcon.techpathways.com/uploads/headersig.txt


Zip-Header hier beschrieben sind : http://en.wikipedia.org/wiki/ZIP_(file_format)#File_headers aber ich bin mir nicht sicher, ob .xlsx-Dateien die gleichen Header haben.

Datei :: Typ-Logik scheint zu sein "PK \ 003 \ 004" als Datei-Header auf Zip-Dateien zu entscheiden ... aber ich bin mir nicht sicher, ob diese Logik so weit wie .xlsx funktionieren würde, nicht eine zu testende Datei

-1
The-Evil-MacBook:~ ivucica$ file --mime-type --brief file.zip 
application/zip 

daher wahrscheinlich

würde den Trick des Erfassens RVs
`file --mime-type --brief $filename` 

mit application/zip Vergleich zu tun. Natürlich müssen Sie file installiert haben, was auf UNIX-Systemen durchaus üblich ist. Ich fürchte, ich kann kein Perl-Beispiel liefern, da das gesamte Wissen von Perl aus meiner Erinnerung verschwunden ist und ich keine Beispiele zur Hand habe.

Verwandte Themen