0

我正在做的项目列表的一部分是一个小文本编辑器。

在某一时刻,您可以加载给定目录中的所有子目录和文件。该程序会将每个节点添加为 TreeView 中的一个节点。

我想要的功能是只添加普通文本阅读器可读的文件。

此代码当前将其添加到树中:

TreeNode navNode = new TreeNode();
navNode.Text = file.Name;
navNode.Tag = file.FullName;

 directoryNode.Nodes.Add(navNode);

我知道我可以轻松地创建一个 if 语句,例如:

if(file.extension.equals(".txt"))

但我必须扩展该语句以包含它可能的每一个扩展。

有没有更简单的方法来做到这一点?我认为这可能与 mime 类型或文件编码有关。

4

4 回答 4

4

没有通用的方法来确定文件中存储的信息类型。

即使您事先知道它是某种文本,如果您不知道用于创建文件的编码是什么,您也可能无法正确加载它。

请注意,HTTP 通过 content-type 标头为您提供有关文件类型的一些提示,但在文件系统上没有此类信息。

于 2013-01-22T01:10:18.730 回答
1

您可以使用几种方法来“最佳猜测”该文件是否为文本文件。当然,您支持的编码越多,这就越难,特别是如果计划支持 CJK(中文日文韩文)脚本。让我们从Encoding.Ascii现在开始Encoding.UTF-8

幸运的是,大多数非文本文件(可执行文件图像等)在其前几 KB都有很多不可解析的字符。

您可以做的是获取一个文件并扫描前 1-4KB(由您决定),看看是否出现任何“不可打印”字符。此操作不会花费太多时间,并且至少可以让您确定文件的内容。

public static async Task<bool> IsValidTextFileAsync(string path,
                                                    int scanLength = 4096)
{
  using(var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read))
  using(var reader = new StreamReader(stream, Encoding.UTF8))
  {
    var bufferLength = (int)Math.Min(scanLength, stream.Length);
    var buffer = new char[bufferLength];

    var bytesRead = await reader.ReadBlockAsync(buffer, 0, bufferLength);
    reader.Close();

    if(bytesRead != bufferLength)
      throw new IOException("There was an error reading from the file.");

    for(int i = 0; i < bytesRead; i++)
    {
      var c = buffer[i];

      if(char.IsControl(c))
        return false;
    }

    return true;
  }
}
于 2013-01-22T01:27:11.700 回答
1

我的方法基于@Rubenisme 的评论和@Erik 的回答。

    public static bool IsValidTextFile(string path)
    {
        using (var stream = System.IO.File.Open(path, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read))
        using (var reader = new System.IO.StreamReader(stream, System.Text.Encoding.UTF8)) 
        {
            var bytesRead = reader.ReadToEnd();
            reader.Close();
            return bytesRead.All(c => // Are all the characters either a:
                c == (char)10  // New line
                || c == (char)13 // Carriage Return
                || c == (char)11 // Tab
                || !char.IsControl(c) // Non-control (regular) character
                );
        }
    }
于 2016-11-04T19:40:12.967 回答
0

一个 hacky 方法是查看文件是否包含任何不是空格形式的较低控制字符 (0-31)(回车、制表符、垂直制表符、换行符,只是为了安全起见null 和文本结尾)。如果是这样,那么它可能是二进制的。如果没有,它可能不是。我没有做任何测试或任何事情来看看将这个规则应用于非 ASCII 编码时会发生什么,所以你必须自己进一步调查:)

于 2013-01-22T01:15:00.887 回答