Тип файла - получить исходное расширение

Как узнать расширение файла, если файл был переименован? Есть ли какой-нибудь инструмент для этого?

Пример: у меня есть файл "1.doc"; Надеюсь, все знают, что это документ Word, который я только что переименовал в «1.txt». Но файл изначально является документом Word; как я могу получить оригинальное расширение файла?


person Thiru G    schedule 05.01.2011    source источник
comment
Что в имени. Расширение — это просто имя, и оно не имеет ничего общего с фактическим типом содержимого файла.   -  person user562374    schedule 05.01.2011
comment
Другой кандидат на тег confusion-of-ideas - что в имени?   -  person    schedule 05.01.2011
comment
@delnan: Не совсем так. Различные форматы файлов имеют характерные признаки, по которым их можно распознать (см., например, форматы PNG или GIF). OTOH, Windows использовала (до сих пор? Не уверен) распознавать тип файла только по расширению файла, поэтому, если вы переименуете файл, Windows не знает, что с ним делать.   -  person Piskvor left the building    schedule 05.01.2011
comment
Хорошо, файл есть например 1.fgf, кто-то переименовал в fgf, как я могу использовать этот файл? Файл может быть текстовым документом, mp3 и т. д.   -  person Thiru G    schedule 05.01.2011


Ответы (3)


Конечно вы можете :)

Это код C# для вас. Я думаю, вы можете создать свой собственный инструмент;)

using System.Runtime.InteropServices;
using System.IO;
using Microsoft.Win32;

    [DllImport(@"urlmon.dll", CharSet = CharSet.Auto)]
    private extern static System.UInt32 FindMimeFromData(
        System.UInt32 pBC,
        [MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl,
        [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer,
        System.UInt32 cbSize,
        [MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed,
        System.UInt32 dwMimeFlags,
        out System.UInt32 ppwzMimeOut,
        System.UInt32 dwReserverd
    );


    public static string getMimeFromFile(string filename)
    {
        if (!File.Exists(filename))
            throw new FileNotFoundException(filename + " not found");

        byte[] buffer = new byte[256];
        using (FileStream fs = new FileStream(filename, FileMode.Open))
        {
            if (fs.Length >= 256)
                fs.Read(buffer, 0, 256);
            else
                fs.Read(buffer, 0, (int)fs.Length);
        }
        try
        {
            System.UInt32 mimetype;
            FindMimeFromData(0, null, buffer, 256, null, 0, out mimetype, 0);
            System.IntPtr mimeTypePtr = new IntPtr(mimetype);
            string mime = Marshal.PtrToStringUni(mimeTypePtr);
            Marshal.FreeCoTaskMem(mimeTypePtr);
            return mime;
        }
        catch (Exception e)
        {
            return "unknown/unknown";
        }
    }

Вы получаете mimetype, используя этот код. Чтобы найти расширение от mime-type, просто выполните небольшой поиск в Google.

person honibis    schedule 05.01.2011
comment
Хорошо и спасибо, honibis, извлечение мим-типа не проблема :-) - person Thiru G; 05.01.2011
comment
Хотя это сработает, вы не получите обратно исходное расширение, а попытаетесь угадать, каким оно могло быть. Обратите внимание, что это, вероятно, не будет работать для некоторых типов файлов (таких как ZIP-архивы, заголовки которых находятся в конце файла, поэтому начало файла может содержать что угодно). - person Piskvor left the building; 05.01.2011
comment
@Piskvor для zip-файлов, которые он возвращает: application/x-zip-compressed, на самом деле это больше, чем предположение, поскольку исходное расширение файла строго связано с mimetype - person honibis; 05.01.2011
comment
@honibis: Это обоснованное предположение (основанное на артефактах формата и статистике), которое в основном верное, но, тем не менее, предположение. Существуют типы файлов с несколькими расширениями: это было image.jpg или image.jpeg? Как я уже сказал, ваш код будет работать, возможно, в 90+% случаев. Просто имейте в виду, что FindMimeFromData работает на распознавании образов и статистике, а не на магии :) - person Piskvor left the building; 05.01.2011
comment
@Piskvor Есть нечто, называемое «заголовок файла», и все стандартные форматы имеют заголовки. первые 256 байт — это место, где хранятся заголовки. Так что НЕТ распознавания образов или магии. - person honibis; 05.01.2011
comment
@honibis: У меня такое чувство, что мы с тобой согласны :D - person Piskvor left the building; 05.01.2011

Невозможно. Если вы работаете в системе типа *nix, используйте команду file, чтобы определить формат файла.

Если вы действительно параноидально относитесь к подобным вещам (и портите свой рабочий процесс), вы можете сделать 2 вещи:

  1. создайте хэш вашего файла, например, MD5, чтобы вы знали, что ваш файл не возился с
  2. обратите внимание на метку времени вашего файла, чтобы вы могли видеть, когда он в последний раз менялся
  3. обратите внимание на расширение вашего файла в этой метке времени

Это защитит вас несколькими способами:

Хэш гарантирует, что ваш файл не был изменен.

Временная метка сообщит вам, когда она была изменена в последний раз.

Расширение сообщит вам свое исходное расширение.

Поскольку простое переименование расширения файла не изменит его метку времени, вам нужен шаг 3.

Использование таких методов в 99,999999999999% случаев скажет вам, что ваш файл был изменен чем-то или кем-то.

person darioo    schedule 05.01.2011
comment
+1 - file в большинстве случаев очень хорошо угадывает исходный формат. Обратите внимание на акцент на угадывании. - person Piskvor left the building; 05.01.2011

Вы не можете. Вам придется использовать такой инструмент, как file, чтобы попытаться определить формат файла.

person Pekka    schedule 05.01.2011