где утечка в моем коде? - PullRequest
3 голосов
/ 18 мая 2009

Вот мой код, который открывает файл XML (old.xml), фильтрует недопустимые символы и записывает в другой файл XML (abc.xml). Наконец, я снова загружу XML (abc.xml). При выполнении следующей строки, исключение говорит, что файл xml используется другим процессом,

xDoc.Load("C:\\abc.xml");

У кого-нибудь есть идеи, что не так? Есть ли утечки в моем коде и почему (я все время использую ключевое слово «using», смущенный, чтобы увидеть утечки ...)?

Вот весь мой код, я использую C # + VSTS 2008 под Windows Vista x64.

    // Create an instance of StreamReader to read from a file.
    // The using statement also closes the StreamReader.
    Encoding encoding = Encoding.GetEncoding("utf-8", new EncoderReplacementFallback(String.Empty), new DecoderReplacementFallback(String.Empty));
    using (TextWriter writer = new StreamWriter(new FileStream("C:\\abc.xml", FileMode.Create), Encoding.UTF8))
    {
        using (StreamReader sr = new StreamReader(
            "C:\\old.xml",
            encoding
            ))
        {
            int bufferSize = 10 * 1024 * 1024; //could be anything
            char[] buffer = new char[bufferSize];
            // Read from the file until the end of the file is reached.
            int actualsize = sr.Read(buffer, 0, bufferSize);
            writer.Write(buffer, 0, actualsize);
            while (actualsize > 0)
            {
                actualsize = sr.Read(buffer, 0, bufferSize);
                writer.Write(buffer, 0, actualsize);
            }
        }
    }

    try
    {
        XmlDocument xDoc = new XmlDocument();
        xDoc.Load("C:\\abc.xml");
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }

EDIT1: я попытался изменить размер буфера с 10M до 1M, и это работает! Я так растерялся, есть идеи?

РЕДАКТИРОВАТЬ2: Я считаю, что эту проблему очень легко воспроизвести, когда входной старый XML-файл очень большой, например, 100M или что-то в этом роде. Я подозреваю, что это известная ошибка .Net? Я собираюсь использовать такие инструменты, как ProcessExplorer / ProcessMonitor, чтобы увидеть, какой процесс блокирует файл, чтобы предотвратить доступ к нему XmlDocument.Load.

Ответы [ 11 ]

4 голосов
/ 18 мая 2009

Это прекрасно работает для меня. Чисто предположение, но, может быть, антивирус проверяет файл? Чтобы провести расследование, попробуйте отключить средство проверки на вирусы и посмотреть, работает ли оно (а затем снова включить средство проверки на вирусы).

Кроме того, есть один способ, которым он может оставить файл открытым: если конструктор StreamReader выдает исключение; но тогда вы все равно не доберетесь до XmlDocument ... но подумайте:

using (FileStream fs = new FileStream("C:\\abc.xml", FileMode.Create))
using (TextWriter writer = new StreamWriter(fs, Encoding.UTF8))
{
   ...
}

Теперь fs располагается в крайнем случае, куда бросает new StreamWriter(...). Тем не менее, я не считаю, что это проблема здесь.

2 голосов
/ 18 мая 2009

Я второе предложение Леппи использовать ProcessMonitor (или его эквивалент), чтобы точно знать, кто блокирует файл. Все остальное - просто предположение.

2 голосов
/ 18 мая 2009

Проблема в вашем char[], который кажется слишком большим. Если он слишком большой, он находится в куче больших объектов, а не в стеке. Следовательно, кучи больших объектов не сжимаются, пока выполняется программное обеспечение, и выделенное пространство может больше не использоваться, что выглядит как утечка памяти. Попробуйте разделить массив на более мелкие куски.

2 голосов
/ 18 мая 2009

Вы запускаете FileSystemWatcher в корне, возможно?

Вы также можете использовать ProcessMonitor, чтобы увидеть, кто обращается к этому файлу.

1 голос
/ 18 мая 2009

Уверен, у вас запущено антивирусное решение, которое блокирует файл после его закрытия. Для проверки попробуйте добавить задержку (например, 1 секунду) перед загрузкой файла. Если это работает, вы, вероятно, нашли причину.

1 голос
/ 18 мая 2009

Тот факт, что это работает для некоторых людей, а не для других, заставляет меня думать, что файл не закрывается. Закройте программу записи перед попыткой загрузить файл.

1 голос
/ 18 мая 2009

Вы проверяли, что никакой другой процесс не пытается получить доступ к файлу?

1 голос
/ 18 мая 2009

с использованием вызовет Dispose, но будет ли Dispose вызывать закрытие в потоке записи? Если это не так, система все еще может считать файл открытым для записи.

Я бы попытался закрыть writer непосредственно перед тем, как закончится его блок using.

Редактировать: Только что тоже попробовал код. Скомпилировано и запущено без проблем, которые вы видите. Попробуйте отключить антивирусные сканеры, как упоминали некоторые другие, и убедитесь, что у вас нет окна где-нибудь с открытым файлом.

1 голос
/ 18 мая 2009

Код работает нормально. Только что проверил.

1 голос
/ 18 мая 2009

Ваш буфер не освобожден, не так ли?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...