1

With the following piece of code, i read a file and keep the stream open.

    static void Main(string[] args)
    {
        FileStream fileStream = new FileStream(@"C:\temp\test1.txt", FileMode.Open);
        Console.ReadLine();
    }

If i now try to rename this file, the message "File in use" is shown. file in use

It looks like the rename of a file should be possible(on os level), even if it is in use: Why does rename a loaded .net assembly work?

Why can't a file be renamed when it is loaded in a stream by .net?

Community
  • 1
  • 1
Manuel
  • 1,985
  • 3
  • 31
  • 51
  • 6
    Because streams have handles to the files, assemblies are loaded into memory and the location becomes irrelevant (post-discovery). – Grant Thomas Feb 08 '13 at 15:45
  • But as far as i did understand from http://stackoverflow.com/questions/14774099/why-does-rename-a-loaded-net-assembly-work, the filename should not matter anyway. Why does it matter if a handle to the file exist? It would change only directory entries. – Manuel Feb 08 '13 at 16:10
  • @GrantThomas And what happens when the assembly is loaded into the `AppDomain`. Will you able to delete the assembly file? – Matías Fidemraizer Feb 08 '13 at 16:33

2 Answers2

2

About assemblies, .NET should open the assembly using something like FileShare.ReadWrite so, even if it's loaded into the domain, any other process can write or rename the whole file.

AFAIK, .NET doesn't have a managed FileShare enum value for allowing or disallowing renaming the file share (something like FileShare.Rename), but Win32 should have thus assembly loading would be creating the file stream with a mask like FileShare.ReadWrite | FileShare.Rename (FileShare.Delete includes renaming but also removing the whole file...).

For demonstrating this, I've tried the following code:

    FileStream a = File.Open(@"C:\blah.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
    a.Dispose();

While the file stream was opened and until it's disposed, I couldn't delete the whole file but I could rename it.

Note that assemblies are loaded into the AppDomain when they're needed, meaning that maybe you can write, delete or rename an assembly because it's not loaded yet.

Try to delete an assembly already loaded into the AppDomain: you can't (I've tried myself just now, the test code runs in a console app and I couldn't remove the executable while running it). Now try to rename it: it works.

Summary

It's all about how a file is opened and which file mask configuration was used when the file stream was opened: this is why your file can't be renamed but you can rename an already loaded assembly.

Modify your code like the next one and you'll be able to rename the whole file (even delete it!):

    FileStream fileStream = File.Open(@"C:\temp\test1.txt", FileMode.Open, FileShare.ReadWrite | FileShare.Delete);
    Console.ReadLine();
Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
  • Does the downvoter has any reason to downvote? I believe that's a reasonable answer for the OP. It's not about diposing or not disposing streams but why some opened streams allow renaming a file and other no. – Matías Fidemraizer Feb 08 '13 at 16:27
1

When you create a FileStream you don't load it's data to the memory. when you are seeking the stream, the file content is still read from the disk - a good thing to do when you need to read big files.

If all you want to do is to load the whole content to memory you can use File.ReadAllBytes. You can read more about it here: http://msdn.microsoft.com/en-us/library/system.io.file.readallbytes.aspx.

Note: If you want to use a stream and not a byte array, you can use MemoryStream and pass the read file content to it.

eyossi
  • 4,230
  • 22
  • 20
  • 1
    For a text file, use File.ReadAllText (to get all the text in the file as a single string) or File.ReadAllLines (to get all the text in the file into an array of strings, one element per line in the file). – Polyfun Feb 08 '13 at 16:01
  • I'm aware about reading a file, but i don't understand why i can rename an assembly which is executed, but not rename a file which has a handle on it. both actions should change only the directory entries of the effective file. – Manuel Feb 08 '13 at 16:12
  • @Manuel Check my answer, I believe that, after some investigation, I found why you can or not. – Matías Fidemraizer Feb 08 '13 at 16:17
  • You can see the exact answer here (Read the comments too): http://superuser.com/a/488130 – eyossi Feb 08 '13 at 16:19