Файл С# 2 ГБ составляет 4 ГБ в оперативной памяти. Почему?

Я читаю файл (этот файл состоит из одной длинной строки длиной 2 ГБ).

Это моя функция, которая считывает все содержимое файла в память, а затем разбивает строку и размещает: *reader = StreamReader

public List<char[]> GetAllContentAsList()
        {
            int bytesToRead = 1000000;
            char[] buffer = new char[bytesToRead];
            List<char[]> results = new List<char[]>();

            while (_reader.Read(buffer, 0, bytesToRead) != 0)
            {
                char[] temp = new char[bytesToRead];
                Array.Copy(buffer,temp,bytesToRead);
                results.Add(temp);
            }

            return results;
        }

Когда все данные помещены в список, они занимают 4 Гб оперативной памяти. Как это возможно, если размер файла составляет всего 2 ГБ?

*Редактировать

Это то, что я в итоге сделал. Я не преобразовываю массив байтов в строку, я просто передаю байты при манипулировании ими. Это было поле только 2Gb в памяти вместо 4gb

 public List<byte[]> GetAllContentAsList()
            {
                int bytesToRead = 1000000;
                var buffer = new byte[bytesToRead];
                List<byte[]> results = new List<byte[]>();

                while (_reader.Read(buffer, 0, bytesToRead) != 0)
                {
                    //string temp = Encoding.UTF8.GetString(buffer);
                    byte[] b = new byte[bytesToRead];
                    Array.Copy(buffer,b,bytesToRead);
                    results.Add(b);
                }

                return results;
            }

person Ivan Bacher    schedule 08.05.2013    source источник
comment
Как вы пришли к выводу, что список занимает 4 ГБ памяти. Размер одного объекта ограничен 2 ГБ. Вы же понимаете, что строка Array.Copy(buffer,temp,bytesToRead); продолжает потреблять память до тех пор, пока сборщик мусора не решит убрать за вами, верно?   -  person Security Hound    schedule 08.05.2013
comment
Вы можете использовать 4 ГБ в С#?   -  person Venson    schedule 08.05.2013
comment
@Venson - на 64-битной ОС и процессе, конечно, почему бы и нет?   -  person Oded    schedule 08.05.2013
comment
как говорит Одед, char может быть больше, чем закодированные byte(s). Почему произвольное создание List и чрезмерное клонирование массивов в вашем коде? Files.ReadAllText("yourfile").ToCharArray() кажется эквивалентным.   -  person Jodrell    schedule 08.05.2013
comment
@Oded, в настоящее время я работаю над программой, которая использует много оперативной памяти (множественное преобразование PDF-файлов в растровые изображения и их печать), и у меня много проблем с ограничением в 1,5 гигабайта (даже с LARGEADDRESSAWARE и/или компиляцией x64), которые вы можете получить Ссылка на то, что вам нужно, но я думаю, что запихнуть реальные 4 ГБ данных в вашу оперативную память не так просто и умно   -  person Venson    schedule 08.05.2013
comment
Кстати, это довольно ужасный способ чтения данных; было бы намного лучше использовать потоковый API (или API для чтения)   -  person Marc Gravell    schedule 08.05.2013
comment
@Venson - Какой именно лимит в 1,5 ГБ? .NET 4.0 позволяет использовать очень большие объекты с флагом. Непонятно даже, как автор определяет использование памяти коллекцией.   -  person Security Hound    schedule 08.05.2013
comment
@Ramhound Я получил много изображений в виде массивов байтов, и когда я пытаюсь сохранить в своей программе больше, чем от 1 до 2 ГБ данных, приложение вылетает с исключением OutOfMemory. Через некоторое время поиска я нашел сообщение MSDN, в котором описывается, что невозможно успешно сделать что-то подобное, но похоже, что LARGEADDRESSAWARE - это такой обходной путь, но он мне не помогает ... так что это post Описывает, что даже невозможно выделить больше, чем 1,3 ГБ   -  person Venson    schedule 08.05.2013


Ответы (1)


Образованное предположение здесь:

Файл имеет формат UTF-8 или ASCII закодирован и только (в основном) содержит символы шириной в один байт (или, возможно, какую-то другую кодовую страницу, которая в основном имеет ширину в один байт).

Теперь символы .NET представляют собой UTF-16, и все они имеют длину 2 (или более) байта.

Значит, в памяти символы будут вдвое больше.

person Oded    schedule 08.05.2013
comment
+1 Легко проверить, изменив кодировку файла при его сохранении. - person slugster; 08.05.2013
comment
Это, наверное, все. Char имеет размер 16 бит (2 байта). - person Corak; 08.05.2013
comment
@slugster - Конечно, но с файлом размером 2 ГБ я оставлю это вам для проверки;) - person Oded; 08.05.2013
comment
Кроме того, насколько я помню, Array.Copy может влиять на память сам по себе (хотя это больше во время рабочего процесса, а не в конечном результате). - person Brad Christie; 08.05.2013
comment
Круто, спасибо за быстрый ответ. я попробую - person Ivan Bacher; 08.05.2013
comment
Кроме того, этот список будет изменять свой размер на протяжении всей операции и оставлять позади объекты, которые GC, возможно, не собрал к тому времени, когда вы смотрите на использование памяти. - person ta.speot.is; 08.05.2013
comment
Спасибо, ваш ответ решил мою проблему. В итоге я просто передавал байты, а не преобразовывал их в символы. - person Ivan Bacher; 09.05.2013