Я использую следующий код для распаковки локального ZIP-файла, содержащего сжатый поток Json, полученный HttpClient.Deserializing потоковые данные, большие, чем объем памяти с Json.Net
ProgressStream progressStream = null;
API_Json_Special_Feeds.RootObject root = null;
private void import_File(string file)
{
isImporting = true;
Console.WriteLine("Importing " + Path.GetFileName(file));
using (FileStream read = File.OpenRead(file))
{
progressStream = new ProgressStream(read);
using (GZipStream zip = new GZipStream(progressStream, CompressionMode.Decompress))
{
UTF8Encoding temp = new UTF8Encoding(true);
var serializer = new JsonSerializer();
StreamReader sr = new StreamReader(zip);
using (var jsonTextReader = new JsonTextReader(sr))
{
root = serializer.Deserialize<API_Json_Special_Feeds.RootObject>(jsonTextReader);
//I'd like to manipulate root between these lines
foreach (API_Json_Special_Feeds.Item item in root.items)
{
Special_Feed_Data.special_Feed_Items.Add(item);
}
}
progressStream.Dispose();
}
}
}
Файл довольно большой при сжатии в 300-600 МБ и несжатом 9-11 ГБ. Как вы можете видеть, я вставил промежуточный поток, чтобы проверить пропускную способность. Все это отлично работает на моей 64-гигабайтной машине, но у клиента всего 8 ГБ. Попытка распаковать и сериализовать 9-11G на машине с 8 ГБ ОЗУ не будет интересной.
Я новичок в Json, так что моя оригинальная мысль была поставить какой-то фильтр или пагинацией на данных, как это время десериализации, может быть тем же способом, который я использую для измерения потока пропускной способности:
private void timer()
{
bool isRunning = true;
while (isRunning)
{
if (progressStream != null)
{
kBytes_Read = ((double)progressStream.BytesRead/(double)1024);
mem_Used = get_Memory_Used();
if (root != null)
Console.WriteLine("Root contains " + root.items.Count.ToString() + " items");
//This doesn't work, because root is null until ALL of the data is deserialized
}
Thread.Sleep(450);
}
}
В моей голове я вижу Json.net, десериализуя одну запись за раз и добавляя ее в список элементов в корне. Проблема заключается в том, что «root» оценивает значение null до тех пор, пока поток не будет завершен. Я не могу найти способ доступа к десериализованным данным до тех пор, пока метод десериализации не будет завершен.
Вопрос Есть ли способ получить доступ к данным, которые уже были сериализованы в Root.Items, пока десериализация продолжается? Если нет, как можно остановиться или приостановить или приостановить десериализацию больших данных, чтобы он не сдул память?
Благодарю вас за ваше время и заранее за любые мысли или предложения, которые вы можете предоставить.
Очень важно, Evk! В моем случае файлы (их много) сжимают. Чтобы реализовать это, мне придется отказаться от потоковой передачи, распаковать каждый файл локально, а затем прочитать с помощью текстового редактора? Пожалуйста, проявляйте терпение своим невежеством. Я уверен, вы знаете, как это происходит, когда вы впервые вставляете ногу в новую технику. –
@ShannonHolsinger вы можете использовать JsonTextReader с любым TextReader, таким как [StreamReader] (https://msdn.microsoft.com/en-us/library/system.io.streamreader) – ESG
Нет, не ждите, никогда не подумайте - я думаю, что я получите то, что вы говорите. Вместо использования десериализации я могу реализовать фильтрацию строк, как вы предложили. Потрясающие. Позвольте мне попытаться реализовать. –