【问题标题】:is file readable (contains text rather is accessible )文件可读(包含文本而不是可访问)
【发布时间】:2016-02-16 04:15:48
【问题描述】:

我正在做一个从本地硬盘读取所有文件的项目, 我指定了我想在搜索中包含的扩展名。

所有选择的文件扩展名都基于文件是文本内容这一事实。

所以为了我的使用,我可以指定要考虑哪些扩展, 比如 .cs .html .htm .css .js 等'

如果我想添加一个可以让普通用户选择扩展的功能怎么办? 并让他从所有可用的 Windows 文件扩展名中进行选择,但在该列表中仅包含他系统中的那些文本文件。 例如我们知道exe,mp3。 mpg、avi 不是 但他可能有一些我们没有考虑到的其他类型的文件(.extensions)。

有没有办法根据系统文件属性来决定, 如果不是什么方法只过滤文本内容文件?

【问题讨论】:

  • 没有什么好的方法可以做到这一点......所以,“尝试阅读,如果你能理解内容,它就是文本”是“最好的”。您可以考虑搜索“检测不带扩展名的文件类型”(或类似内容)以了解以前关于该主题的讨论。
  • 扩展仅提供文件内容的微弱指示。我敢打赌,有些应用程序也使用 .cs 扩展名,但这些文件不包含文本。
  • 我认为没有,至少不是通用的。例如:word 文件的扩展名 docx 不是文本,docx 文件是压缩的 XML 文件。但作为用户,您可能希望将 word 文件视为文本。
  • @DirkTrilsbeek docx, doc 可以通过 .Net 专用类解析,因此它应该被视为文本,因为您已经写入它并且您也可以解析它
  • @JbobJohan 这正是我的意思。没有基于文件本身的通用方法来确定文件是否包含文本内容。因为在我的示例中,docx 包含文本内容,但从技术角度来看,它不是文本。当然,您可以阅读 doc/docx,但是其他许多类似但您不知道的格式呢?你无法解释你还没有听说过的东西。

标签: c# string algorithm file text


【解决方案1】:

Windows 机器的一种机制是在与文件扩展名关联的 Windows 注册表中查找内容类型。 (如果没有直接的注册表查找,我不知道如何做到这一点。)

在注册表中,基于文本的文件扩展名通常应具有以下一个或多个特征:

  • 指示 MIME 主要文本类型的内容类型,例如 text/plaintext/application
  • text 的感知类型
  • 具有 GUID {5e941d80-bf96-11cd-b579-08002b30bfeb} 的默认处理程序,分配给纯文本持久处理程序。

以下方法将返回与这些特征相关的所有系统扩展:

// include using reference to Microsoft.Win32;
static IEnumerable<string> GetTextExtensions()
{
    var defaultcomp = StringComparison.InvariantCultureIgnoreCase;
    var root = Registry.ClassesRoot;
    foreach (var s in root.GetSubKeyNames()
        .Where(a => a.StartsWith(".")))
    {
        using (RegistryKey subkey = root.OpenSubKey(s))
        {
            if (subkey.GetValue("Content Type")?.ToString().StartsWith("text/", defaultcomp) == true)
                yield return s;
            else if (subkey.GetValue("PerceivedType")?.ToString().Equals("text", defaultcomp) == true)
                yield return s;
            else
            {
                using (var ph = subkey.OpenSubKey("PersistentHandler"))
                {
                    if (ph?.GetValue("")?.ToString().Equals("{5e941d80-bf96-11cd-b579-08002b30bfeb}", defaultcomp) == true)
                        yield return s;
                }

            }
        }
    }
}

输出取决于工作站配置,但在我当前的机器上返回:

.a、.AddIn、.ans、.asc、.asm、.asmx、.aspx、.asx、.bas、.bat、.bcp、.c、.cc、.cd、.cls、.cmd , ...

虽然这取决于应用程序安装程序是否正确映射文件扩展名,但它似乎可以识别大多数主要的文本文件类型。

【讨论】:

  • 顺便说一句,使用对 Microsoft.Win32 的引用 ..你在哪里调用了 Win32 中的任何方法?
  • @JbobJohan Registry 类位于 Microsoft.Win32 命名空间中。
  • 对不起,我使用 RegistryKey 时没有记住需要参考(:意思是直到现在才意识到它是 Win32 功能而不是 .Net 标准
  • 由于注册表是特定于 Windows 的,因此注册表类位于 Microsoft 命名空间中,而不是更常见的 System 命名空间中。但这些是 Windows 上的 .NET 标准类;注册表类与其他核心 .NET 类一起导出到 mscorlib.dll 中。
  • 我已将此标记为正确答案,我认为无需再添加任何内容,它应该尽可能多地涵盖任务要求,以编程方式完成。欢呼
【解决方案2】:

一般来说,没有任何好的可靠方法可以做到这一点。

您无法通过比较文件扩展名来决定 - 它只是文件名的一部分,每个人都可以更改它,因此即使 file.exe 也可以是纯文本文件。

C# - Check if File is Text Based
您可以只检查前 1000 个(任意数字)字符,看看是否有不可打印的字符,或者它们是否都是特定范围内的 ascii。

【讨论】:

  • 我还没有意识到“没有办法”是编程的一个选项,特别是在这样一个微不足道的任务中。
  • 所以我想解决方法是指定您所知道的所有内容并添加一个选项供用户添加..(他将能够添加任何内容!!)
  • @LorenPechtel 实际上,那些与 ASCII 完全相同的不可打印文件。除非您的意思是 UTF-16,其中每隔一个字节是 \0
猜你喜欢
  • 2014-09-29
  • 1970-01-01
  • 2014-06-09
  • 2023-04-01
  • 2015-04-13
  • 2011-05-12
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
相关资源
最近更新 更多