是否有比使用Shell COM组件更快的方法来获取文件元数据?

时间:2018-07-01 16:57:20

标签: windows vb.net filesystems

在这里和其他地方阅读各种答案,我将这一点拼凑在一起以获得所需的文件元数据:

<link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet">
<table>
  <tr>
    <td>
      <select id="z4" name="color">
        <option value="" disabled selected>Color</option>
        <option value="red">Red</option>
        <option value="orange">Orange</option>
        <option value="yellow">Yellow</option>
        <option value="green">Green</option>
        <option value="purple">Purple</option>
        <option value="white">White</option>
        <option value="black">Black</option>
        <option value="gray">Gray</option>
        <option value="Other">Other</option>
      </select>      
      <input id="other" name="other" type="text" placeholder="Type other">
    </td>
  </tr>
</table>
<br>
<div class="display">  
  <button onclick="sentence()"> Submit </button>
</div>

这不是世界上最高效的代码,即在目录中获取每个文件的path属性以标识我实际感兴趣的文件。优化此代码以使其仅读取一次每个文件的path属性即可速度提高50%(通过让其获取第一个文件来确定其是否正确)进行了测试,但不管怎么说,它的速度都比预期的慢得多。

它需要从每个文件中获取24个属性,并且需要在大约100k内找到大约20k个文件,目前这需要一个小时的时间。

配置文件告诉我CPU是瓶颈,无论占用了什么周期,我都看不到,因为它的99%位于Shell32.Folder.GetDetailsOf方法中。

是否有更快的获取元数据的方法?答案不必特定于vb或.net。

1 个答案:

答案 0 :(得分:0)

由于您正在寻求最高速度,因此建议您为代码启用Option Strict并进行必要的修改,IDE会建议这些修改。这将消除不必要的类型转换。

例如

Public Shared Function get_interesting_data(path) As Dictionary(Of String, String)

应为:

Public Shared Function get_interesting_data(path As String) As Dictionary(Of String, String)

使用Shell32.Folder.ParseName Method来直接检索Shell32.Folder.Items对象,而不是枚举FolderItem集合。可以将此对象转换为允许使用ShellFolderItem.ExtendedProperty methodShell32.ShellFolderItem

  

有两种指定属性的方法。首先是分配   属性的知名名称,例如sPropName的“作者”或“日期”。   但是,每个属性都是组件对象模型(COM)的成员   属性集,也可以通过指定其格式ID进行标识   (FMTID)和属性ID(PID)。 FMTID是一个GUID,用于标识   属性集,而PID是标识特定对象的整数   属性集中的属性。

     

通过FMTID / PID值指定属性通常会更多   比使用其名称更有效。使用属性的FMTID / PID值   如果使用ExtendedProperty,则必须将它们组合成一个SCID。 SCID是   一个字符串,其中包含FMTID / PID值,格式为“ FMTID ** PID”,   其中FMTID是属性集的GUID的字符串形式。对于   例如,摘要信息属性集的作者的SCID   属性为“ {F29F85E0-4FF9-1068-AB91-08002B27B3D9} 4”。

FMTID / PID值可以在Windows Properties上的链接下找到。

将某些选定的属性放在一起:

Public Shared Function get_interesting_data(path As String) As Dictionary(Of String, String)
    Dim fi As New IO.FileInfo(path)
    Dim f_dir As Shell32.Folder = shell.NameSpace(fi.DirectoryName)

    ' instead of enumerating f_dir.Items to find the file of interest
    ' directly retrieve the item reference
    Dim item As Shell32.ShellFolderItem = DirectCast(f_dir.ParseName(fi.Name), Shell32.ShellFolderItem)

    Dim scid_Bitrate As String = "{64440490-4C8B-11D1-8B70-080036B11A03} 4"    ' Audio: System.Audio.EncodingBitrate
    Dim scid_Title As String = "{F29F85E0 - 4.0FF9-1068-AB91-08002B27B3D9} 2"  ' Core: System.Title
    Dim scid_Created As String = "{B725F130-47EF-101A-A5F1-02608C9EEBAC} 15"   ' Core: System.DateCreated
    Dim scid_Copyright As String = "{64440492-4C8B-11D1-8B70-080036B11A03} 11" ' Core: System.Copyright
    Dim scid_Publisher As String = "{64440492-4C8B-11D1-8B70-080036B11A03} 30" ' Media: System.Media.Publisher
    Dim scid_FullDetails As String = "{C9944A21-A406-48FE-8225-AEC7E24C211B} 2" ' PropList: System.PropList.FullDetails

    Dim bitrate As Object = item.ExtendedProperty(scid_Bitrate)
    Dim title As Object = item.ExtendedProperty(scid_Title)
    Dim created As Object = item.ExtendedProperty(scid_Created)
    Dim copyright As Object = item.ExtendedProperty(scid_Copyright)
    Dim publisher As Object = item.ExtendedProperty(scid_Publisher)
    Dim fullDetails As Object = item.ExtendedProperty(scid_FullDetails)

    Dim data As New Dictionary(Of String, String)
    ' save the retrieved properties

    Return data
End Function

我不知道这种检索属性的方法是否比您目前使用的GetDetailsOf快,但是其他更改应该有所改进。