2010-10-27 11 views
6

Mam skrypt Perl, który odczytuje dane z pliku binarnego programu Excel (xls). Ale klient, który wysyła nam te pliki, zaczął czasami wysyłać nam pliki w formacie XLSX. Zaktualizowałem skrypt, aby móc je czytać. Jednak klient czasami lubi nazywać pliki XLSX z rozszerzeniem .xls, które obecnie mylą mój skrypt, ponieważ używa nazwy pliku do określenia, który to typ pliku.W jaki sposób mój skrypt Perla może ustalić, czy plik Excel jest w formacie XLS czy XLSX?

Plik XLSX to plik zip, który zawiera pliki XML. Czy istnieje prosty sposób, aby mój skrypt sprawdził plik i czy jest to plik zip, czy nie? Jeśli tak, mogę zmienić mój skrypt zamiast tylko nazwy pliku.

Odpowiedz

16

.xlsx pliki mają pierwsze 2 bajty jako „PK”, tak proste i otwarte badanie z 2 pierwszych znaków zrobi.

+5

Aby być bardziej szczegółowym, pierwsze 4 bajty to '' PK \ 003 \ 004 "'. – cjm

+0

Chociaż prawdopodobnie dotyczy to wszystkich plików .xlsx produkowanych przez poszczególne aplikacje, format pliku ZIP tego nie wymaga - patrz http://en.wikipedia.org/wiki/Zip_file#Structure. –

+0

Tak! Tego właśnie oczekiwałem; szybki i łatwy sposób sprawdzenia pliku, najlepiej bez użycia kolejnego modułu. Dzięki! – DaveKub

-2

Nie mogę powiedzieć o Perlu, ale przy użyciu frameworka .Net, dostępnych jest wiele bibliotek, które będą manipulować plikami zip, z których możesz skorzystać.

Inną rzeczą, którą widziałem, jest użycie wersji WinZip z wiersza poleceń. Podaje wartość zwracaną równą 0, gdy plik jest rozpakowany i niezerowy, gdy wystąpi błąd.

To może nie być najlepszy sposób na zrobienie tego, ale to dopiero początek.

2

Zastosowanie File::Type:

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

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

Właśnie testowałem go z plikiem .xlsx i mime_type() powrócił application/zip. Podobnie, dla pliku .xls, mime_type() jest .

6

Edit: Archiwum :: pocztowy jest lepszym

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

+1 Zawsze najpierw sprawdzaj CPAN :) – Konerak

+1

To nie działa - używa sufiksu nazwy pliku do określenia typu pliku, patrz http://search.cpan.org/~bingos/Archive-Extract-0.46/ lib/Archive/Extract.pm. Przegapiłem to, ale jest już za późno i nie mogę odebrać głosu. –

17

Tak, jest to możliwe po sprawdzeniu magic number.

Istnieje sporo modułów w Perlu do sprawdzania magic number w pliku.

Przykładem korzystania 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 
} 

Innym przykładem, używając 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

Plik :: Typ jest raczej dużym modułem. Ponieważ interesujesz się tylko jednym typem pliku, prawdopodobnie skopiowałbym ten test. Sprawdza tylko, czy pierwsze 4 bajty pliku to '' PK \ 003 \ 004 ". – cjm

+1

+1 dla libmagic. Następne wydanie będzie zawierało wiele ulepszeń dla typów plików pochodnych zip, zobacz [archiwum listy mailingowej] (http://mx.gw.com/pipermail/file/2010/thread.html). – daxim

1

Można wykryć plik xls sprawdzając pierwszych bajtów pliku nagłówków Excel.

Wykaz prawidłowych nagłówków starszych Excel można zdobyć tutaj (chyba że wiesz dokładnie wersję swojego programu Excel, należy sprawdzić ze wszystkimi właściwymi możliwości):

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


nagłówki Zip opisane są tutaj : http://en.wikipedia.org/wiki/ZIP_(file_format)#File_headers , ale nie jestem pewien, czy pliki .xlsx mają te same nagłówki.

Plik :: Logika typu wydaje się być "PK \ 003 \ 004" jako nagłówek pliku do decydowania o plikach zip ... ale nie jestem pewien, czy ta logika działałaby aż do .xlsx, nie mając plik do przetestowania.

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

Stąd prawdopodobnie porównując

`file --mime-type --brief $filename` 

z application/zip by rade wykrywania zamki. Oczywiście, musisz mieć zainstalowane file, co jest dość powszechne w systemach UNIX. Obawiam się, że nie mogę podać przykładu Perla, ponieważ cała wiedza o Perlu wyparowała z mojej pamięci i nie mam pod ręką żadnych przykładów.

Powiązane problemy