Невозможно переместить файл после того, как я прочитал и добавил данные в новый файл c#

#c# #foreach

Вопрос:

У меня есть цикл foreach, который добавляет данные из 1 файла (источника) в другой (пункт назначения). Как только файл будет добавлен со всеми данными, я хочу переместить исходный исходный файл. При отладке я получаю сообщение об ошибке «Исключение: «System.IO.IOException» в System.IO.FileSystem.dll»

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

 var stringwrite = new[] { prefix, prefix2 };

                        foreach (string line in File.ReadLines(currentFile))
                        {
                            var lastOne = line.Split(';').Last();
                            if (!stringwrite.Any(stringwrite => lastOne.Contains(stringwrite)))
                                continue;

                            //write lines found to new file 
                            File.AppendAllText(todestination, line   Environment.NewLine);
                        }
                        //move original file to new directory 
                        try
                        {
                            File.Move(currentFile, completeddestination);
                            break;
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show("Issue Moving File");
                        }
 

Комментарии:

1. Скорее всего, он уже закрыт, так как ReadLines() файл закрывается автоматически, поэтому должна быть другая причина, проверьте, есть ли у вас разрешения на перемещение файла. Возможно, это «только для чтения», или приложение должно работать с повышенными разрешениями или sth

2. Проверил все разрешения, и они верны. Бросая мне, как вы говорите, ReadLines() автоматически закрывает файл.

3. @PeterSmith что вы имеете в виду под «закрытием файла»?

4. @cragjungle каковы детали исключения? Один этот тип мало что говорит…

5. В частности, «Файл уже существует». Я проверил, что это не так

Ответ №1:

Поскольку вы читаете исходный файл до конца и записываете его в пункт назначения в зависимости от условий, было бы разумно сохранить как входные, так и выходные потоки открытыми до окончания операций чтения/записи. Обратите внимание, что File.ReadLines откроется исходный файл, прочтите его содержимое, а затем закройте его. Кроме того, File.AppendAllText откроется файл назначения, добавит содержимое, а затем закроет файл. Такой подход неэффективен. Я думаю, что ваша задача может быть правильно реализована с помощью файловых потоков. Пожалуйста, найдите пример ниже:

 static void Main()
{
    var sourcePath = "C:\PathToSource";
    var destinationPath = "C:\PathToDestination";
    var completedDestinationPath = "C:\PathToCompletedDestination";
    
    var prefixes = new[] { "some-prefix", "some-other-prefix" };
    
    foreach (var source in EnumerateDataFiles(sourcePath))
    {
        // This assumes that files in source and destination and completed
        // dectination directories have the same file name but different paths.
        // If you use another convention for your data, please adjust it here
        var destination = GetDestinationFilePath(source, destinationPath);
        var completedDestination = GetDestinationFilePath(source, completedDestinationPath);
        
        try
        {
            AppendData(
                source,
                destination,
                line =>
                {
                    var lastEntry = line.Split(';').Last();
                    return prefixes.Any(prefix => lastEntry.Contains(prefix));
                });
        
            File.Move(source, completedDestination);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Issue Moving File: {ex.Message}");
        }
    }
}

static IEnumerable<string> EnumerateDataFiles(string path)
{
    // Change *.dat to the extension (e.g., *.txt) you use for your data files,
    // or to *.* to include all files from the directory
    return Directory.EnumerateFiles(path, "*.dat", SearchOption.AllDirectories);
}

static string GetDestinationFilePath(string sourceFileName, string destinationPath)
{
    // This will return a file path to the file with the same name as the source
    // but located in the destination directory
    return Path.Combine(destinationPath, Path.GetFileName(sourceFileName));
}

static void AppendData(string source, string destination, Func<string, bool> linePredicate)
{
    using (var inputStream = new FileStream(source, FileMode.Open, FileAccess.Read))
    using (var inputReader = new StreamReader(inputStream))
    using (var outputStream = new FileStream(destination, FileMode.OpenOrCreate, FileAccess.Write))
    using (var outputWriter = new StreamWriter(outputStream))
    {
        while (inputReader.ReadLine() is string inputLine)
        {
            if (!linePredicate(inputLine))
                continue;
            outputWriter.WriteLine(inputLine);
        }
    }
}
 

В приведенном примере я предположил, что у вас одно и то же имя файла, но разные пути к исходному, целевому и завершенному пути к целевому файлу. Если вы используете другой механизм именования, пожалуйста, следуйте комментариям, чтобы соответствующим образом его настроить.

Комментарии:

1. Хотя ваши замечания о производительности, конечно, верны, они, вероятно, не имеют ничего общего с возникшим исключением.

2. Конечно, дело не в исходном коде. Но с помощью кода, который я предоставил, проблема, скорее всего, должна быть решена