首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OutOfMemoryException at StringWriter.ToString()

OutOfMemoryException at StringWriter.ToString()
EN

Stack Overflow用户
提问于 2015-07-16 06:23:21
回答 4查看 3.4K关注 0票数 3

在我的OutOfMemoryException上调用ToString时,我得到了一个ToString

代码语言:javascript
复制
StringWriter stringWriter = new System.IO.StringWriter();
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(stringWriter, data);
string xmlString = stringWriter.ToString(); // <-- Exception occurs here

我怎样才能解决这个问题?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-07-23 03:34:27

这样做是有效的..。

代码语言:javascript
复制
   using (MemoryStream ms = new MemoryStream())
            {
                serializer.Serialize(ms, data);
                ms.Position = 0;
                XmlReader reader = XmlReader.Create(ms, schemaReaderSettings);
            }
票数 0
EN

Stack Overflow用户

发布于 2015-07-16 07:52:09

试试这段代码。它使用一个文件作为临时缓冲区。

代码语言:javascript
复制
List<Dummy> lst = new List<Dummy>();

        for (var i = 0; i < 100000; i++)

        {
            lst.Add(new Dummy()
                    {
                        X =  i,
                        Y =  i * 2
                    });

        }

        XmlSerializer serializer = new XmlSerializer(typeof(List<Dummy>));

        // estimate your memory consumption ... it would be around 4 bytes reference + 4 bytes object type pointer + 8 bytes those ints + let's say another 4 bytes other hidden CLR metadatas. a total of 20 bytes per instance + 4 bytes reference to our object (in the list array) => around 24 bytes per instance. Round up to a let's say 50 bytes per instance. Multiply it by 100.000 = 5.000.000

        MemoryStream memStream = new MemoryStream(5000000);

        serializer.Serialize(memStream, lst);
        memStream.Position = 0;

        string tempDatafileName = null;
        var dataWasWritten = false;
        try
        {
            var fileName = Guid.NewGuid().ToString() + ".tempd";
            var specialFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);

            using (var fs = new FileStream(tempDatafileName, FileMode.Create, FileAccess.ReadWrite))
                memStream.WriteTo(fs);

            dataWasWritten = true;

            memStream.Dispose();
            memStream = null;

            lst.Clear();
            lst = null;
            // force a full second generational GC
            GC.Collect(2);

            // reading the content in string
            string myXml = File.ReadAllText(tempDatafileName);
        }
        finally
        {
            if (dataWasWritten && string.IsNullOrWhiteSpace(tempDatafileName) == false)
            {
                if (File.Exists(tempDatafileName))
                {
                    try
                    {
                        File.Delete(tempDatafileName);
                    }
                    catch
                    {

                    }
                }
            }
        }
票数 1
EN

Stack Overflow用户

发布于 2015-07-16 06:39:54

我确信stringWriter已经非常大了,比方说大于1GB的大小,并且您的计算机的总内存为2GB。当您调用ToString ()时,内存将加倍,因为将在1GB大小的堆中创建和分配一个新字符串,以便复制stringWriter的内容。尽量避免不必要的ToString (),并尝试直接使用stringWriter来完成您需要做的事情。避免使用ToString(),通常会减少50%的内存占用。

但是,如果您确实需要将数据作为字符串,并且没有足够的内存,请尝试首先将内容保存在文件中,释放StringWriter并使用StreamReader.ReadToEnd () API将文件内容加载到字符串中。

另一种方法是尝试剪切您的序列化数据块,并尝试以块的形式解析它。例如,让我们考虑具有如下结构的XML:

代码语言:javascript
复制
<Root>
    <Item>some data 1</Item>
    <Item>some data 2</Item>
    <Item>some data 3</Item>
    ....
    <Item>some data n</Item>
</Root>

您可以将对象序列化为一个MemoryStream,然后以块的形式读取它,并从如下所示的块中创建“小”XML数据:

第一个xml:

代码语言:javascript
复制
<Root>
    <Item> some data 1 </Item>
</Root>

第二个xml:

代码语言:javascript
复制
 <Root>
    <Item> some data 2 </Item>
</Root>

等等,这可以单独检查和验证。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31446657

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档