Использование MemoryStream для загрузки .jpg без блокировки файла процессом?

У меня есть своего рода редактор, в котором есть несколько строк и изображение, отображаемое в пользовательском интерфейсе, и я сохраняю данные в текстовом файле и отдельном файле .jpg с тем же именем.

Теперь, когда я пытаюсь переопределить файл .jpg с помощью File.Replace, он говорит, что изображение заблокировано другим процессом, который, очевидно, является процессом моего собственного приложения.

Я надеюсь, что поток памяти может исправить это, потому что он обрабатывается в ОЗУ. Поэтому я хотел бы загрузить все файлы jpg с помощью потока памяти, но я не понимаю, как загрузить что-либо с помощью потока памяти, если это вообще возможное решение моей проблемы.

Изменить: в основном фрагмент кода, о котором идет речь, таков:

private void CopyPicture(bool PictureHasChanged)
    {
        try
        {   //kopiere die datei nur, wenn sie nicht bereits vorhanden ist.  
            if (File.Exists(TargetFolder + Exercise.Name + ".jpg") == false)
            {//kopiert das neue bild in das zielverzeichnis
                File.Copy(Exercise.Bild.UriSource.LocalPath, TargetFolder + Exercise.Name + ".jpg");
            }
            else
            {
                //wenn das Bild einer bestehenden übung geändert wurde
                if (PictureHasChanged)
                {
                    //überprüft ob eine datei mit dem namen existiert 
                    if (File.Exists(TargetFolder + Exercise.Name + ".jpg") == true)
                    {//löscht die existente datei
                        File.Replace(Exercise.Bild.UriSource.LocalPath, TargetFolder + Exercise.Name + ".jpg", TargetFolder + Exercise.Name + ".jpg");
                    }

                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message + "\n\n" + ex.Source);
            return;
        }

    }

и у меня есть изображение, хранящееся внутри в простом списке в виде растрового изображения: new BitmapImage(new Uri(f.FullName.ToString().Remove(f.FullName.Length - 4, 4) + ".jpg",UriKind.RelativeOrAbsolute))

я надеюсь, что это поможет лучше понять проблему

РЕДАКТИРОВАТЬ 2: теперь я делаю следующее, чтобы загрузить изображение:

FileStream fsSource = new FileStream(JpgTarget, FileMode.Open, FileAccess.Read);
                        byte[] bytes = new byte[fsSource.Length];
                        using (fsSource)
                        {
                            // Read the source file into a byte array.
                            int numBytesToRead = (int)fsSource.Length;
                            int numBytesRead = 0;
                            while (numBytesToRead > 0)
                            {
                                // Read may return anything from 0 to numBytesToRead.
                                int n = fsSource.Read(bytes, numBytesRead, numBytesToRead);

                                // Break when the end of the file is reached.
                                if (n == 0)
                                    break;

                                numBytesRead += n;
                                numBytesToRead -= n;
                            }
                            //numBytesToRead = bytes.Length;
                        }

                        BitmapImage Image = new BitmapImage();
                        //erstellt das bitmap für die liste
                        using (MemoryStream Memstream = new MemoryStream(bytes))
                        {

                            Image.BeginInit();
                            Image.StreamSource = Memstream;
                            Image.CacheOption = BitmapCacheOption.OnLoad;
                            Image.EndInit();
                            Image.Freeze();
                        }
                        fsSource.Close();

Но он продолжает говорить мне, что The Pictrue, который я пытаюсь перезаписать, уже используется другим процессом.

Изменить 3: я попытался использовать решение Pennie Pet и в итоге получил ту же проблему с заблокированным файлом:

  Bitmap newBitmap = GetImageFromByteArray(File.ReadAllBytes(JpgTarget));

                        using (MemoryStream memory = new MemoryStream())
                        {
                            newBitmap.Save(memory, newBitmap.RawFormat);
                            memory.Position = 0;
                            BitmapImage bitmapImage = new BitmapImage();
                            bitmapImage.BeginInit();
                            bitmapImage.StreamSource = memory;
                            bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                            bitmapImage.EndInit();


                            //fügt der liste die aus der textdatei gelesene übung hinzu
                            List.Add(new Uebung(text, Sitting, wdh, bitmapImage, f.Name.Substring(0, f.Name.Length - 4)));
                        }

См. метод GetImageFromByteArray в сообщении PenniePet.

Последнее редактирование:

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

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

Я надеюсь, что вы, ребята, не рассердитесь. Спасибо за всю твою помощь!


person Marv    schedule 20.11.2014    source источник
comment
Было бы полезно увидеть код, который вы на самом деле используете. Вам понадобится FileStream для чтения файла в любом случае, но похоже, что вы можете, да, загрузить его в MemoryStream в качестве буфера. Но я также не уверен, что это лучший способ сделать то, что вы ищете. Нам действительно нужно увидеть ваш код и лучшее описание того, что вы пытаетесь сделать.   -  person Matthew Haugen    schedule 20.11.2014
comment
@MatthewHaugen, ну вот, надеюсь, для тебя это имеет смысл :/   -  person Marv    schedule 20.11.2014
comment
Вы распоряжаетесь растровым изображением?   -  person CodeCaster    schedule 20.11.2014
comment
@CodeCaster не совсем, я должен сделать это сам? Я думал, что это сделано, когда все ссылки исчезли   -  person Marv    schedule 25.11.2014
comment
Вы говорите, что в конечном итоге файл заблокирован, даже если вы касаетесь его только с помощью File.ReadAllBytes(JpgTarget)? Это звучит очень, очень странно. Вы уверены, что в вашей программе нет ничего, что касается файла?   -  person RenniePet    schedule 26.11.2014
comment
Боже мой, ты прав. Я совершенно забыл, что кадр предварительного просмотра также загружает растровое изображение, это так неловко.   -  person Marv    schedule 26.11.2014


Ответы (3)


Если я правильно понимаю, вы хотите прочитать файл .jpg и преобразовать его в объект .Net Bitmap таким образом, чтобы гарантировать, что файл .jpg не будет заблокирован. Если да, то вот несколько фрагментов кода из моего предыдущего ответа: https://stackoverflow.com/a/16576471/253938

Bitmap newBitmap = GetImageFromByteArray(File.ReadAllBytes(fileName));

и

  /// <summary>
  /// Method that uses the ImageConverter object in .Net Framework to convert a byte array, 
  /// presumably containing a JPEG or PNG file image, into a Bitmap object, which can also be 
  /// used as an Image object.
  /// </summary>
  /// <param name="byteArray">byte array containing JPEG or PNG file image or similar</param>
  /// <returns>Bitmap object if it works, else exception is thrown</returns>
  public static Bitmap GetImageFromByteArray(byte[] byteArray)
  {
     Bitmap bm = (Bitmap)_imageConverter.ConvertFrom(byteArray);

     if (bm != null && (bm.HorizontalResolution != (int)bm.HorizontalResolution ||
                        bm.VerticalResolution != (int)bm.VerticalResolution))
     {
        // Correct a strange glitch that has been observed in the test program when converting 
        //  from a PNG file image created by CopyImageToByteArray() - the dpi value "drifts" 
        //  slightly away from the nominal integer value
        bm.SetResolution((int)(bm.HorizontalResolution + 0.5f), 
                         (int)(bm.VerticalResolution + 0.5f));
     }

     return bm;
  }
person RenniePet    schedule 25.11.2014
comment
Мне удалось преобразовать его в растровое изображение, но оно также дает мне ту же ошибку. - person Marv; 26.11.2014

Обязательно закройте поток после сохранения файла .jpg.

При чтении файла убедитесь, что вы установили только Read доступ при открытии потока.

System.IO.FileStream f = new System.IO.FileStream(sPath, FileMode.Open,
                                                         FileAccess.Read);

Используйте поток f для чтения байтов и создайте экземпляр MemoryStream, используя прочитанные байты:

System.IO.MemoryStream x = new System.IO.MemoryStream(buffer)
person alex.pulver    schedule 20.11.2014
comment
извините, но я действительно не понимаю, что такое буфер в этом случае, он создается файловым потоком? и как я могу получить к нему доступ? - person Marv; 20.11.2014
comment
Да, методом FileStream.Read - person alex.pulver; 20.11.2014
comment
Вы уверены, что это правильный способ заполнения потока памяти? Я использую это из MSDN (msdn.microsoft.com/de-de/library/) и это (stackoverflow.com/questions/5346727/), чтобы загрузить растровое изображение. Но когда я пытаюсь перезаписать Jpg, он все равно говорит мне, что к нему уже обращался другой процесс. - person Marv; 25.11.2014
comment
код из ссылки msdn не закрывает поток. Используйте fsSource.Close() после чтения байтов. - person alex.pulver; 25.11.2014
comment
Я добавил закрытие вызова, но он все равно не работает, с той же ошибкой - person Marv; 25.11.2014
comment
пожалуйста, измените пример кода, чтобы отразить добавление метода close() - person alex.pulver; 25.11.2014
comment
поставить fsSource.Close(); перед созданием BitmapImage - person alex.pulver; 25.11.2014
comment
Вы закрываете поток, когда создаете файл изображения на жестком диске? Проверьте все потоки, которые указывают на ваш файл изображения, и посмотрите, закрыты ли они. Ищите также ошибки или операторы if, которые могут обойти закрытие потока. - person alex.pulver; 26.11.2014
comment
Спасибо за ваши усилия, Алекс, но это был не незакрытый поток, это был мой элемент управления предварительным просмотром изображения, который также заблокировал изображение. - person Marv; 27.11.2014

Вы должны использовать

bitmap.CacheOption = BitmapCacheOption.OnLoad;

в противном случае ваш файл изображения заблокирован.

person Sinatr    schedule 20.11.2014
comment
Я использую его сейчас, вы можете увидеть во втором моем редактировании. Но он все еще заблокирован, есть идеи? :/ - person Marv; 25.11.2014
comment
Вы должны закрыть исходный поток. Добавьте fsSource.Close(); в конце (после закрытия потока памяти). - person Sinatr; 25.11.2014
comment
Ах, кажется, я неправильно понял, что такое использование. Я добавил вызов метода close сейчас, но у меня все та же проблема. - person Marv; 25.11.2014
comment
using закроет MemoryStream в конце блока using, но я не уверен в базовом потоке, поэтому предлагаю закрыть его явно. Можете ли вы отредактировать свой вопрос, чтобы показать, где вы поставили fsSource.Close();? - person Sinatr; 25.11.2014