Delphi :按类型获取文件扩展名列表

zlhcx6iw  于 2023-06-29  发布在  其他
关注(0)|答案(1)|浏览(229)

是否有方法从Windows获取已注册文件扩展名/类型的列表?也许GetExts('Video')

eulz3vhy

eulz3vhy1#

文件格式

到目前为止,文件格式不仅属于一个类别-大多数人们称之为“视频”的格式实际上是容器(因为它们可以携带不仅仅是视频,例如:音频、字幕、菜单...)。它们不绑定到文件名,因为文件名可以有任何形式:

  • 仅仅因为文件名为music.mp3,并不能保证其实际内容是MPEG-1 audio,并且
  • MPEG-4 container可以具有文件扩展名.mp4.m4v.m4a甚至.co.uk

扩展名如何保存(Windows)?

根据File Types,注册表以这种方式存储它们,这至少从Windows 95开始发生:
文件扩展名子项的一般形式如下。所有条目类型都是REG_SZ类型。

HKEY_CLASSES_ROOT
   .ext
      (Default) = ProgID.ext.1
      Content Type = MIME content type
      PerceivedType = PerceivedType

.鉴于:

内容类型:文件类型的MIME内容类型
感知类型:如果有,则文件属于哪个。Windows Vista之前的Windows版本不使用此字符串。有关详细信息,请参阅Perceived Types and Application Registration

后者最终将我们引导到AssocGetPerceivedType(),但该函数仅在我们已经知道文件扩展名时才有用。很可能它只是一个阅读注册表项和值的 Package 器。
所以我们要做的就是:

  • 枚举注册表的HKEY_CLASSES_ROOT键,用于所有以点开头的键,以及
  • 每个键检查潜在值
  • Content Type(可以有类似video/mpeg的内容)和/或
  • PerceivedType(可以有video)。

注册表MIME数据库

根据Remy LebeauIs there a way to get an extension for a given content type?,也存在这种结构:

HKEY_CLASSES_ROOT
   MIME
      Database
         Content Type
            video/*
               Extension = .ext

这似乎是Best Practices for File Associations中提到的 *Internet Explorer MIME数据库 *。对于每个以video/开头的键,我们可以读取其名称为Extension的值,然后知道文件扩展名。它应该已经作为一个键存在于HKEY_CLASSES_ROOT根目录tho中,而不是我们会发现的新东西。

Pascal语言

Delphi 已经为那些不想直接处理WinAPI functions的人提供了 Package 器类TRegistry

uses
  Registry;

procedure TForm1.Button1Click(Sender: TObject);
const
  NAME_ContentType= 'Content Type';
  NAME_PerceivedType= 'PerceivedType';
  VALUE_video= 'video';
  KEY_MIME= 'MIME\Database\Content Type';  // Actually "HKEY_LOCAL_MACHINE\SOFTWARE\Classes\MIME\Database" and "HKEY_CURRENT_USER\Software\Classes\MIME\DataBase" in one
  NAME_Extension= 'Extension';
var
  oReg: TRegistry;
  lKey: TStringList;  // Enumerating all keys of the Registry root key
  iKey: Integer;  // Iterating over the list
  sKey, sValue: String;  // Current key name, current value content

  // Used on both values - either can exist or be absent
  function _CheckValue( _sName: String ): Boolean;
  begin
    result:= oReg.ValueExists( _sName );  // Is the value even available?
    if result then begin
      sValue:= oReg.ReadString( _sName );
      result:= Copy( sValue, 1, 5 )= VALUE_video;  // Does the value begin with 'video'?
    end;
  end;

begin
  oReg:= TRegistry.Create( KEY_READ );  // No need to write to it
  oReg.RootKey:= HKEY_CLASSES_ROOT;  // Actually "HKEY_CURRENT_USER\Software\Classes" and "HKEY_LOCAL_MACHINE\Software\Classes" in one
  oReg.OpenKeyReadOnly( '' );  // The root key is not automatically opened

  lKey:= TStringList.Create;
  oReg.GetKeyNames( lKey );  // All keys of the root key
  oReg.CloseKey();  // The open root key is no longer needed
  for iKey:= 0 to lKey.Count- 1 do begin
    sKey:= lKey[iKey];
    if Copy( sKey, 1, 1 )= '.' then begin  // Does the key name begin with a dot? It's a filename extension definition.
      if oReg.OpenKeyReadOnly( sKey ) then begin  // Key opened successfully?
        if _CheckValue( NAME_ContentType )
        or _CheckValue( NAME_PerceivedType ) then Memo1.Lines.Add( sKey );  // If one is successful, list key name = filename extension
      end;
      oReg.CloseKey();  // Key is no longer needed
    end;
  end;

  oReg.OpenKeyReadOnly( KEY_MIME );  // Internet Explorer MIME database
  lKey.Clear();  // Empty the list
  oReg.GetKeyNames( lKey );
  oReg.CloseKey();
  for iKey:= 0 to lKey.Count- 1 do begin
    sKey:= lKey[iKey];
    if Copy( sKey, 1, 5 )= VALUE_video then begin  // Does the key start with 'video'?
      if oReg.OpenKeyReadOnly( KEY_MIME+ '\'+ sKey ) then begin
        if oReg.ValueExists( NAME_Extension ) then begin  // Does a value with this name exist?
          sValue:= oReg.ReadString( NAME_Extension );
          if Memo1.Lines.IndexOf( sValue )= -1 then Memo1.Lines.Add( sKey );  // Could have been found earlier already
        end;
      end;
      oReg.CloseKey();
    end;
  end;

  lKey.Free;
  oReg.Free;
end;

结果和完整性

对我来说,这产生(摘录):

  • .3gp
  • .asf
  • .avi
  • .DVR-MS
  • .M2TS
  • .mov
  • .mp4
  • .mpg
  • .MTS
  • .vob
  • .wmv

但是,它不会列出

这是因为单个Windows安装并不知道所有格式。有不少格式是通过手动定义的,或者通过安装播放器软件来定义的,该软件可以自动定义它支持的所有格式。因此,此代码将为每个人产生不同的结果。

延伸阅读

一个完整的格式列表并不存在,因为还有许多专有格式存在,这些格式只用于软件产品(例如游戏中的动画和视频),而没有任何意图在该范围之外使用。然后还有一些边缘情况,即动画仍然是图片而不是视频(如.gif.mng)。

相关问题