Как мой Perl-скрипт может определить, находится ли файл Excel в формате XLS или XLSX? - PullRequest
6 голосов
/ 27 октября 2010

У меня есть Perl-скрипт, который читает данные из двоичного файла Excel (xls). Но клиент, который отправляет нам эти файлы, иногда отправляет нам файлы формата XLSX. Я обновил скрипт, чтобы иметь возможность читать их. Тем не менее, клиент иногда предпочитает называть файлы XLSX с расширением .xls, что в настоящее время приводит в замешательство черт из моего сценария, поскольку он использует имя файла, чтобы определить, какой это тип файла.

Файл XLSX - это zip-файл, который содержит XML. Есть ли у моего скрипта простой способ просмотреть файл и сказать, является ли он файлом zip или нет? Если это так, я могу сделать так, чтобы в моем сценарии использовалось только имя файла.

Ответы [ 7 ]

17 голосов
/ 27 октября 2010

Да, это возможно, отметив магическое число .

В Perl довольно много модулей для проверки магического числа в файле.

Пример использования 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
}

Другой пример использования 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
}
16 голосов
/ 27 октября 2010

.xlsx файлы имеют первые 2 байта как 'PK', поэтому подойдет простое открытие и проверка первых 2 символов.

6 голосов
/ 27 октября 2010

Редактировать: Архив :: Zip лучше

solution
 # Read a Zip file
   my $somezip = Archive::Zip->new();
   unless ( $somezip->read( 'someZip.zip' ) == AZ_OK ) {
       die 'read error';
   }
2 голосов
/ 27 октября 2010

Использование File::Type:

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

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

Я только что протестировал его с файлом .xlsx, и mime_type() вернул application/zip. Аналогично, для файла .xls значение mime_type() равно application/octet-stream.

1 голос
/ 27 октября 2010

Файл xls можно определить, проверив первые байты файла на наличие заголовков Excel.

Список действующих старых заголовков Excel можно получить здесь (если вы не знаете точную версию их Excel, проверьте все применимые возможности):

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


Zip-заголовки описаны здесь: http://en.wikipedia.org/wiki/ZIP_(file_format)#File_headers но я не уверен, что файлы .xlsx имеют одинаковые заголовки.

Логика File :: Type выглядит как "PK \ 003 \ 004" в качестве заголовка файла для выбора zip-файлов ... но я не уверен, будет ли эта логика работать до .xlsx, не имея файл для проверки.

0 голосов
/ 27 октября 2010
The-Evil-MacBook:~ ivucica$ file --mime-type --brief file.zip 
application/zip

Следовательно, вероятно, сравнивая

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

с application/zip поможет обнаружить молнии. Разумеется, вам нужно установить file, что вполне обычно в системах UNIX. Боюсь, я не могу привести пример Perl, так как все знания Perl испарились из моей памяти, и у меня нет под рукой примеров.

0 голосов
/ 27 октября 2010

Я не могу сказать о Perl, но с используемой платформой .Net существует ряд доступных библиотек, которые будут манипулировать zip-файлами, которые вы можете использовать.

Еще одна вещь, которую я видел у людей, это версия WinZip для командной строки. Возвращаемое значение равно 0, когда файл разархивирован, и ненулевому значению при ошибке.

Возможно, это не лучший способ сделать это, но это только начало.

...