大型字符串列表和 .txt 文件的性能真的很差

Really bad performance for large Lists of strings and .txt files

你需要知道的:

我的应用程序使用食品数据库,该数据库存在于 .txt 文件中。每种食物大约有 170 个数据(2-3 位数字),由 tabstops 分隔,并且每种食物再次由 \n 分隔,因此 每一行 在这个 .txt 文件中有 1 食物的数据。

应用程序目标平台是Android,它需要离线工作,我使用Unity 使用 c# 进行编码。

我的两个问题是:

  1. 正在访问 .txt 文件

因为 android 应用程序无法通过

访问 .txt 文件

$"{Application.DataPath}/textFileName.txt"

我在 Inspector 中将 .txt 文件指定为 TextAsset (name: txtFile) .当应用程序第一次启动时,我将 TextAsset 文件的所有数据加载到 json (name: jsonStringList),这包含一个字符串列表:

for (int i = 0; i < amountOfLinesInTextFile; i++); { jsonStringList.Add(txtFile.text.Split('\n')[i]) }

从技术上讲 确实 有效,但不幸的是 txtFile 总共有大约 15000 行,这使得它 真的慢(Stopwatch时间为for-loop≈750000 ms,大约是12.5分钟...)

显然,让用户在第一次打开应用程序时等待那么长时间是不可取的...

  1. 正在搜索 jsonList

再说一遍:技术上可行,但它也太慢(即使很难很多 问题 1)

更快

(Stopwatch 对于 for-loop: ≈1600 ms)

如果能帮助我缩短这两个动作的时间,我将非常高兴! 也许有一种完全不同的方法来处理如此大的 .txt 文件,但每一点减少时间都会有所帮助!

15000 确实不是一个大文件。你只是做了太多不必要的事情reading/transformations。你需要做一次,缓存它(在你的情况下保存在变量中),重复使用它。

var foodIndex = txtFile
  .text
  .Split('\n')                //get rows
  .Select(x=> x.Split('\t'))  //get columns for each row
  .ToDictionary(x=> x[nameIndex], StringComparer.OrdinalIgnoreCase);   //build case-insensitive search index

var myFood = foodIndex["aPpLe"];

这个产品Dictionary<string, string[]>

更好的方法

反序列化 CSV format (your file is obviously CSV table) into POCO 行:

public class Food
{
   [DataMember(Order=1)] //here is your nameIndex
   public string Name {get;set;}
   [DataMember(Order=2)]
   public int Amount {get;set;}
   //...
}

var foodIndex = SomeCSVParse<Food>(txtFile.text)
  .ToDictionary(x=> x.Name, StringComparer.OrdinalIgnoreCase);

var myFood = foodIndex["aPpLe"];

这产生Dictionary<string, Food>搜索索引,看起来更好,更容易使用。

这样所有从字符串到 int/double/datetime/etc 的转换、列的顺序、分隔符(逗号、制表符、空格)、文化(如果有 float/double)、高效阅读、headers,等等可以直接放弃到第 3 方框架。有人在这里做了这个 - Parsing CSV files in C#, with header

nuget 上也有很多框架,只需选择 smaller/popular 或从源代码中复制粘贴即可 - https://www.nuget.org/packages?q=CSV

并详细了解 C# 中的数据结构 - https://docs.microsoft.com/en-us/dotnet/standard/collections/