如何更有效地分割字符串

本文关键字:字符串 分割 有效地 何更 | 更新日期: 2023-09-27 18:07:09

我有一个JSON字符串,看起来像:

{"Detail": [
  {"PrimaryKey":111,"Date":"2016-09-01","Version":"7","Count":2,"Name":"Windows","LastAccessTime":"2016-05-25T21:49:52.36Z"},
  {"PrimaryKey":222,"Date":"2016-09-02","Version":"8","Count":2,"Name":"Windows","LastAccessTime":"2016-07-25T21:49:52.36Z"},
  {"PrimaryKey":333,"Date":"2016-09-03","Version":"9","Count":3,"Name":"iOS","LastAccessTime":"2016-08-22T21:49:52.36Z"},
  .....( *many values )
]} 

数组Detail有许多PrimaryKey。有时约为500K PrimaryKey s。我们使用的系统只能处理一定长度的JSON字符串,即128KB。所以我必须将这个JSON字符串分割成段(每个是128KB或更少的字符长度)。

Regex reg = new Regex(@"'{"".{0," + (128*1024).ToString() + @"}""'}");
MatchCollection mc = reg.Matches(myListString);

目前,我使用正则表达式来完成此操作。它工作得很好。但是,它使用了太多的内存。是否有更好的方法来做到这一点(不需要正则表达式)?

***添加更多信息。

我上面提到的"系统"是Azure DocumentDB。默认情况下,文档只能是512KB(就像现在一样)。虽然我们可以请求MS增加这个,但是我们得到的json文件总是远远超过512KB。这就是为什么我们要想办法解决这个问题。

如果可能的话,我们希望继续使用documentDB,但我们愿意接受其他建议。

***一些信息澄清:1)数组中的值是不同的。不重复。2)是的,我使用StringBuilder只要我可以。3)是的,我试过IndexOf & &;子字符串,但基于测试,在这种情况下性能并不比正则表达式好(尽管它可能是我实现它的方式)。

* ** json对象是复杂的,但我所关心的是这个"细节",这是一个数组。我们可以假设字符串就像示例一样,只有"Detail"。我们需要将这个json数组字符串分割成小于512KB的大小。基本上,我们可以把它看作一个简单的字符串,而不是json。但是,它是json格式,所以也许一些库可以做得更好。

如何更有效地分割字符串

看看Json.NET(可通过NuGet获得)。

它有一个JsonReader类,它允许你通过令牌读取json来创建所需的对象,用JsonReader读取json的例子。并不是说,如果你传递无效的json字符串(例如,没有"end array"字符或没有"end object"字符)到JsonReader -它将抛出一个异常,只有当它达到无效的项目,所以你可以传递不同的子字符串给它。

另外,我猜你的系统有类似于JsonReader的东西,所以你可以使用它。

StringReader读取string不应该需要太多的应用程序内存,它应该比通过正则表达式匹配迭代更快。

假设data包含您的JSON数据,这里有一个简单的解决方案:

var details = data
    .Split('[')[1]
    .Split(']')[0]
    .Split(new[] { "}," }, StringSplitOptions.None)
    .Select(d => d.Trim())
    .Select(d => d.EndsWith("}") ? d : d + "}");;
foreach (var detail in details)
{
    // Now process "detail" with your JSON library.
}

工作示例:https://dotnetfiddle.net/sBQjyi

显然,只有当你真的不能使用普通的JSON库时,你才应该这样做。参考Mikhail Neofitov对图书馆建议的回答。

如果你从文件或网络中读取JSON数据,你应该实现一个更像流的处理,你读取一个细节行,用你的JSON库反序列化它,然后把它交给调用者。当调用者请求下一个细节对象时,读取下一行,对其进行反序列化,以此类推。这样就可以最小化反序列化器的内存占用。

您可能需要考虑将每个细节存储在单独的文档中。这意味着需要两次往返才能获得标题和所有详细文档,但这意味着您永远不会处理真正大的JSON文档。此外,如果以增量方式添加Detail,那么写操作将更加高效,因为没有办法只添加另一行。你必须重写整个文档。你的读/写比率将决定整体效率的盈亏平衡点。

这样做的另一个理由是,通过JSON解析器输入正则表达式,然后重新组装它的复杂性消失了。您永远不知道您的regex解析器是否会处理所有情况(引号内的逗号、国际字符等)。我见过许多人认为他们有一个很好的正则表达式,只是为了在生产中发现奇怪的情况。

如果您的Detail数组可以无限制地增长(甚至有很大的界限),那么无论JSON解析器的限制或读/写比率如何,您都应该进行此更改,因为最终您将超过限制。