1

Im having a sort of an editor, that has some strings and a picture displayed in the ui and iam saving the data in a textfile and a detached .jpg file with the same name.

Now when iam trying to override the .jpg file by File.Replace, it says that the picture is blocked by another process which is obviously the process of my own application.

I hope that the memorystream can fix this because it is handled in the RAM. So i would like to load all the jpg files by a memorystream but i dont understand how to load anything with the memorystream, if that is a possible solution to my problem at all..

Edit: Basicly the code snippit this is about is this one :

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;
        }

    }

and i have the picture stored internal in a simple list as a bitmapimage by : new BitmapImage(new Uri(f.FullName.ToString().Remove(f.FullName.Length - 4, 4) + ".jpg",UriKind.RelativeOrAbsolute))

i hope that this helps to understand the problem better

EDIT 2: now iam doing the following in order to load the Picture:

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();

But it Keeps telling me that The Pictrue, iam trying to overwrite is already in use by another process.

Edit 3: I tried to use pennie Pet's solution and ended up with this, having the same problem with the locked file:

  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)));
                        }

See the GetImageFromByteArray methode in PenniePet's post.

Last Edit:

It was totally my fault and it really embarrass me, i forgot that i was Loading the Image at another point. Since i fixed it, the locked-problem does not exist anymore.

I picked PenniePete's Awnser as correct, because iam currently using it, as it was the last one i tried, and he also opened my eyes to my fail.

I hope you other guys wont be mad. Thanks for all of your help!

Marv
  • 119
  • 3
  • 14
  • It would help to see the code you're actually using. You'll need a `FileStream` to read the file regardless, but it sounds like you might be able to, yes, load it to a `MemoryStream` as a buffer. But I'm also not sure that's the best way to do what you're looking for. We really need to see your code and a better description of what you're trying to do. – Matthew Haugen Nov 20 '14 at 11:05
  • @MatthewHaugen there you go, i hope it makes any sence to you :/ – Marv Nov 20 '14 at 11:14
  • Do you dispose the bitmap? – CodeCaster Nov 20 '14 at 11:16
  • @CodeCaster not really, do i have to do it myself? i thought its done when all the references are gone – Marv Nov 25 '14 at 09:16
  • You say you still end up with the file locked, even though you only touch it with File.ReadAllBytes(JpgTarget)? That sounds really, really strange. Are you sure there isn't something else in your program that is touching the file? – RenniePet Nov 26 '14 at 12:40
  • Oh my god, you are right. I totally forgot that the preview frame is also loading the Bitmap, thats so embarrassing.. – Marv Nov 26 '14 at 13:51

3 Answers3

1

You have to use

bitmap.CacheOption = BitmapCacheOption.OnLoad;

otherwise your image file is locked.

Sinatr
  • 20,892
  • 15
  • 90
  • 319
  • I do use it now, you can see in my second edit. But its still locked, any ideas?:/ – Marv Nov 25 '14 at 09:16
  • You have to close original stream. Add `fsSource.Close();` at the end (after memory stream is closed). – Sinatr Nov 25 '14 at 10:50
  • ah seems that i missunderstood the using-thing. I added the close method call now, but i still have the same problem. – Marv Nov 25 '14 at 11:19
  • `using` will close `MemoryStream` at the end of `using` block, but I am not sure in underlying stream, therefore I suggest to close it explicitly. Can you edit your question to show where you put `fsSource.Close();`? – Sinatr Nov 25 '14 at 11:23
1

Be sure that you close the stream after saving the .jpg file.

When reading the file be sure that you set only Read access when open the stream.

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

Use f stream to read the bytes and create an instance of MemoryStream using the read bytes:

System.IO.MemoryStream x = new System.IO.MemoryStream(buffer)
alex.pulver
  • 2,107
  • 2
  • 31
  • 31
  • sorry but i dont really understand what the buffer is in this case, is it created by the filestream? and how can i access it? – Marv Nov 20 '14 at 14:14
  • Yes, by FileStream.Read method – alex.pulver Nov 20 '14 at 14:55
  • are you sure that this is the correct way to fill the memory stream? I use this, from MSDN (http://msdn.microsoft.com/de-de/library/system.io.filestream.read%28v=vs.110%29.aspx) and this (http://stackoverflow.com/questions/5346727/convert-memory-stream-to-bitmapimage) in order to load the bitmapimage. But when i try to overwrite the Jpg it still tells me that its already accessed by another process.. – Marv Nov 25 '14 at 09:08
  • the code from msdn link doesn't close the stream. Use fsSource.Close() after reading the bytes. – alex.pulver Nov 25 '14 at 09:33
  • I added the close-call but it still doesnt work, with the same error – Marv Nov 25 '14 at 11:20
  • please change your code sample to reflect the adding of close() method – alex.pulver Nov 25 '14 at 11:53
  • put fsSource.Close(); before creating the BitmapImage – alex.pulver Nov 25 '14 at 13:42
  • Do you close the stream when you create the image file on hdd? Check all the streams that points to your image file and see if they are closed. Look also for errors or if statements that might bypass the close of the stream. – alex.pulver Nov 26 '14 at 13:10
  • Thanks for your effort alex, but it wasnt an unclosed stream, it was my Image Preview control that had locked the image too. – Marv Nov 27 '14 at 13:12
1

If I understand right, you want to read the .jpg file, and convert it into a .Net Bitmap object in a way that guarantees that the .jpg file does not end up being locked. If so, here are some code snippets from a previous answer of mine: https://stackoverflow.com/a/16576471/253938

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

and

  /// <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;
  }
Community
  • 1
  • 1
RenniePet
  • 11,420
  • 7
  • 80
  • 106
  • That is almost correct, but i need a BitmapImage. I will try to use your solution and use the converter from : http://stackoverflow.com/questions/6484357/converting-bitmapimage-to-bitmap-and-vice-versa or http://stackoverflow.com/questions/94456/load-a-wpf-bitmapimage-from-a-system-drawing-bitmap im not quite sure yet. – Marv Nov 26 '14 at 08:52
  • I managed to converte it to a bitmapImage but it also gives me the same error – Marv Nov 26 '14 at 09:17