After I created a file in a directory the directory is locked as long as my program which created the file is running. Is there any way to release the lock? I need to rename the directory couple of lines later and I always get an IOException saying "Access to the path "..." denied".
Directory.CreateDirectory(dstPath);
File.Copy(srcPath + "\\File1.txt", dstPath + "\\File1.txt"); // no lock yet
File.Create(dstPath + "\\" + "File2.txt"); // causes lock
File.Create(string path) Creates a file and leaves the stream open.
you need to do the following:
Directory.CreateDirectory(dstPath);
File.Copy(srcPath + "\\File1.txt", dstPath + "\\File1.txt");
using (var stream = File.Create(dstPath + "\\" + "File2.txt"))
{
//you can write to the file here
}
The using statement asures you that the stream will be closed and the lock to the file will be released.
Hope this helps
Have you tried closing your FileStream? e.g.
var fs = File.Create(dstPath + "\\" + "File2.txt"); // causes lock
fs.Close();
i suggest you use a using statement:
using (var stream = File.Create(path))
{
//....
}
but you should also be aware of using object initializers in using statements:
using (var stream = new FileStream(path) {Position = position})
{
//....
}
in this case it will be compiled in:
var tmp = new FileStream(path);
tmp.Position = position;
var stream = tmp;
try
{ }
finally
{
if (stream != null)
((IDisposable)stream).Dispose();
}
and if the Position setter throw exception, Dispose() will not being called for the temporary variable.
Related
I have an image file in Canvas element that I get in code behind in asp.net. now I want to save it to a folder in my project but file stream always saves it to c drive. What do I do?
[WebMethod()]
public void SaveUser(string imageData)
{
//Create image to local machine.
string fileNameWitPath = path + "4200020789506" + ".png";
using (FileStream fs = new FileStream(fileNameWitPath, FileMode.Create))
{
using (BinaryWriter bw = new BinaryWriter(fs))
{
byte[] data = Convert.FromBase64String(imageData);
bw.Write(data);
bw.Close();
}
}
// Save fileNameWitPath variable to Database.
}
Here is an example of how I save files to an Images folder in my project directory.
var fileName = "4200020789506.png";
var base64String = SOME_REALLY_LONG_STRING;
using (var s = new MemoryStream(Convert.FromBase64String(base64String)))
using (var f = new FileStream(Path.Combine(Server.MapPath("~/Images"), fileName), FileMode.Create, FileAccess.Write))
{
s.CopyTo(f);
}
Here's what I do and it works well. For you, filePath/filename = fileNameWitPath. Do this for each file you have. Hope it works for you. If you need further info, Id be glad to help.
using (var stream = File.Create(filePath + filename))
{
attachment.ContentObject.DecodeTo(stream, cancel.Token);
}
I can only imagine your path variable points to your C:\ drive.
You need to set the path variable equal to the location you want, for instance:
public void SaveUser(string imageData)
{
path = #"C:\YourCustomFolder\"; // your path needs to point to the Directory you want to save
//Create image to local machine.
string fileNameWitPath = path + "4200020789506" + ".png";
//chekc if directory exist, if not, create
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
using (FileStream fs = new FileStream(fileNameWitPath, FileMode.Create))
{
using (BinaryWriter bw = new BinaryWriter(fs))
{
byte[] data = Convert.FromBase64String(imageData);
bw.Write(data);
bw.Close();
}
}
// Save fileNameWitPath variable to Database.
}
I also included a Check to see if your directory exists, and if it does not, it will create a folder called 'YourCustomFolder' on your C drive, where it will save images.
If you would like to save your image to a folder in your project, I would recommend using Server.MapPath(~/YourFolderInApplication)
I'm trying to read and write to the same file in a way such that no other program can access the file in between:
FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
StreamReader sr = new StreamReader(fs);
StreamWriter sw = new StreamWriter(fs);
newString = sr.ReadToEnd() + "somethingNew";
sw.Write(newString);
fs.Close();
The file is never written to. If I debug I can see that the reader manages to fetch the contents of the file, but the writer does not seem to be able to write to the file. Nothing happens.
I've been looking at this question which seems to be the same as mine. However I'm not able to get it to work.
Just Flush your changes to file, Have sw.Flush(); before closing the stream. like:
string filePath = "test.txt";
FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
StreamReader sr = new StreamReader(fs);
StreamWriter sw = new StreamWriter(fs);
newString = sr.ReadToEnd() + "somethingNew";
sw.Write(newString);
sw.Flush(); //HERE
fs.Close();
You may see this post simultaneous read-write a file in C# (open multiple streams for reading and writing)
As mentioned above - just add the Flush() to force the data held in the stream to be written to the file. In a comment you mentioned that you had previously used a 'using' statement but this hadn't worked.
Briefly here's why:
A using statement automatically calls Flush() so you don't have
to.
When you dispose of a StreamReader (or StreamWriter) - like by using a 'using' statement - the inner stream object is also disposed and you lose the handle to the stream.
#EJS a simple static method that you can use to create a new file if it does not exist as well as write to the same file if it does exist
Simple usage
string path = #"C:\SomePath\Name.txt";
if (!System.IO.File.Exists(path))
{
WriteAndOrAppendText(path, "File Created");
}
else if (System.IO.File.Exists(path))
{
WriteAndOrAppendText(path, "New Boot.");
}
private static void WriteAndOrAppendText(string path, string strText)
{
if (!File.Exists(path))
{
using (StreamWriter fileStream = new StreamWriter(path, true))
{
fileStream.WriteLine(strText);
fileStream.Flush();
fileStream.Close();
}
}
else
{
using (StreamWriter fileStream2 = new StreamWriter(path, true))
{
fileStream2.WriteLine(strText);
fileStream2.Flush();
fileStream2.Close();
}
}
}
For being able to create a file, append to it, and read the data in it while still allowing an application to write to it, as I believe you are trying to do, here's a set up I created:
string path = #"C:\SomePath\MyLogFile.txt";
public static string Log(string Message)
{
try
{
if (File.Exists(path) == false)
File.Create(path).Close(); // need this .Close()!!!
logCounter++;
string logString = logCounter + " " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString() + ": " + Message + Environment.NewLine;
using (FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
{
using (StreamWriter sw = new StreamWriter(fs))
{
sw.Write(logString);
}
}
return logString; // only necessary so we can return an error in the Exception block
}
catch (Exception ex)
{
return "Logger: Cannot log data. " + ex.ToString();
}
}
It's actually required to use FileAccess.Write if you do FileMode.Append - instead of being able to use FileAccess.ReadWrite - but I found that didn't matter because whatever had been written would have been closed and flushed to the file, and I could still open the file and read it (it wouldn't be locked & blank) using these. I have sw.Write() because I have Environment.NewLine that I added into my logString, but I could've done sw.WriteLine() and removed that, if I had wanted to.
One caveat: File.Exists() has issues if the path is long - can't remember the limit, but just know that there is one, so don't put your file you're writing to several layers deep. Less is always better.
I simply want to merge all text files in a given directory, similar to the following command prompt command:
cd $directory
copy * result.txt
I've written the following code, which almost accomplishes what I want, but it's doing something strange. When the StreamWriter writes the first file (or when i = 0), it doesn't actually write any content - the file size remains 0 bytes, despite the first file being ~300 KB. However, the other file writes execute successfully.
If I compare the output from the command prompt to the output from the C# code in diff, you can see that a large block of text is missing. Additionally, the command prompt result is 1,044 KB where the C# result is 700 KB.
string[] txtFiles = Directory.GetFiles(filepath);
using (StreamWriter writer = new StreamWriter(filepath + "result.txt"))
{
for (int i = 0; i < txtFiles.Length; i++)
{
using (StreamReader reader = File.OpenText(txtFiles[i]))
{
writer.Write(reader.ReadToEnd());
}
}
}
Am I using the StreamWriter / StreamReader incorrectly?
Minimalistic implementation, reading the bytes and writing them instead of using a stream for reading - please note, that you should handle the IOException correctly to avoid misbehavior:
var newline = Encoding.ASCII.GetBytes(Environment.NewLine);
var files = Directory.GetFiles(filepath);
try
{
using (var writer = File.Open(Path.Combine(filepath, "result.txt"), FileMode.Create))
foreach (var text in files.Select(File.ReadAllBytes))
{
writer.Write(text, 0, text.Length);
writer.Write(newline, 0, newline.Length);
}
}
catch (IOException)
{
// File might be used by different process or you have insufficient permissions
}
Here, hope it helps you. Note: By copying from a stream to another you save some ram and greatly improve performance.
class Program
{
static void Main(string[] args)
{
string filePath = #"C:\Users\FunkyName\Desktop";
string[] txtFiles = Directory.GetFiles(filePath, "*.txt");
using (Stream stream = File.Open(Path.Combine(filePath, "result.txt"), FileMode.OpenOrCreate))
{
for (int i = 0; i < txtFiles.Length; i++)
{
string fileName = txtFiles[i];
try
{
using (Stream fileStream = File.Open(fileName, FileMode.Open, FileAccess.Read))
{
fileStream.CopyTo(stream);
}
}
catch (IOException e)
{
// Handle file open exception
}
}
}
}
}
I wrote your code , it works properly! only change the line :
using (StreamWriter writer = new StreamWriter(filepath + "result.txt"))
to:
using (StreamWriter writer = new StreamWriter(filepath + "/result.txt"))
i guess you can't see the file because it is saved in another folder .
using System.IO;
class test
{
public static void Main()
{
string path=#"c:\mytext.txt";
if(File.Exists(path))
{
File.Delete(path);
}
FileStream fs=new FileStream(path,FileMode.OpenOrCreate);
StreamWriter str=new StreamWriter(fs);
str.BaseStream.Seek(0,SeekOrigin.End);
str.Write("mytext.txt.........................");
str.WriteLine(DateTime.Now.ToLongTimeString()+" "+DateTime.Now.ToLongDateString());
string addtext="this line is added"+Environment.NewLine;
File.AppendAllText(path,addtext); //Exception occurrs ??????????
string readtext=File.ReadAllText(path);
Console.WriteLine(readtext);
str.Flush();
str.Close();
Console.ReadKey();
//System.IO.IOException: The process cannot access the file 'c:\mytext.txt' because it is //being used by another process.
// at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
}
}
Try This
string path = #"c:\mytext.txt";
if (File.Exists(path))
{
File.Delete(path);
}
{ // Consider File Operation 1
FileStream fs = new FileStream(path, FileMode.OpenOrCreate);
StreamWriter str = new StreamWriter(fs);
str.BaseStream.Seek(0, SeekOrigin.End);
str.Write("mytext.txt.........................");
str.WriteLine(DateTime.Now.ToLongTimeString() + " " +
DateTime.Now.ToLongDateString());
string addtext = "this line is added" + Environment.NewLine;
str.Flush();
str.Close();
fs.Close();
// Close the Stream then Individually you can access the file.
}
File.AppendAllText(path, addtext); // File Operation 2
string readtext = File.ReadAllText(path); // File Operation 3
Console.WriteLine(readtext);
In every File Operation, The File will be Opened and must be Closed prior Opened. Like wise in the Operation 1 you must Close the File Stream for the Further Operations.
You are writing to the file prior to closing your filestream:
using(FileStream fs=new FileStream(path,FileMode.OpenOrCreate))
using (StreamWriter str=new StreamWriter(fs))
{
str.BaseStream.Seek(0,SeekOrigin.End);
str.Write("mytext.txt.........................");
str.WriteLine(DateTime.Now.ToLongTimeString()+" "+DateTime.Now.ToLongDateString());
string addtext="this line is added"+Environment.NewLine;
str.Flush();
}
File.AppendAllText(path,addtext); //Exception occurrs ??????????
string readtext=File.ReadAllText(path);
Console.WriteLine(readtext);
The above code should work, using the methods you are currently using. You should also look into the using statement and wrap your streams in a using block.
File.AppendAllText does not know about the stream you have opened, so will internally try to open the file again. Because your stream is blocking access to the file, File.AppendAllText will fail, throwing the exception you see.
I suggest you used str.Write or str.WriteLine instead, as you already do elsewhere in your code.
Your file is created but contains nothing because the exception is thrown before str.Flush() and str.Close() are called.
using (var fs = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
using (var sw = new StreamWriter(fs))
{
sw.WriteLine(message);
}
IsolatedStorageFile.FileExists(string path) works but StreamReader(string samePath) doesn't?
I have validated both paths are equal. I have no idea why the StreamReader explodes
List<ProjectObj> ret = new List<ProjectObj>();
IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication();
if (!file.DirectoryExists("/projects/")) //trying to validate the dir exists
return ret;
string[] fileNames = file.GetFileNames("/projects/");
foreach (string filename in fileNames)
{
if (!file.FileExists("/projects/" + filename)) //validate just one more time..
continue;
ProjectObj tempProj = new ProjectObj();
//Even with the validation it still breaks right here with the bellow error
StreamReader reader = new StreamReader("/projects/"+filename);
An exception of type 'System.IO.DirectoryNotFoundException' occurred
in mscorlib.ni.dll but was not handled in user code
Message:Could not find a part of the path
'C:\projects\Title_939931883.txt'.
Path is not same in both cases. In first case you are getting User store for application and then search for file in it. But in later case you are simply searching in base directory.
StreamReader constructor expects absolute path of file.
You need to create IsolatedStorageFileStream and pass it on to StreamReader -
using (IsolatedStorageFileStream fileStream = new IsolatedStorageFileStream
("/projects/" + filename, FileMode.Open, file))
{
using (StreamReader reader = new StreamReader(fileStream ))
{
}
}
Give this one a try. Reading and writing files in IsolatedStorage has a different path and should be used like that. You should consider reading How to: Read and Write to Files in Isolated Storage.
public static List<ProjectObj> getProjectsList()
{
List<ProjectObj> ret = new List<ProjectObj>();
IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication();
if (!file.DirectoryExists("/projects/")) //trying to validate the dir exists
return ret;
string[] fileNames = file.GetFileNames("/projects/");
foreach (string filename in fileNames)
{
if (!file.FileExists("/projects/" + filename)) //validate just one more time...
continue;
ProjectObj tempProj = new ProjectObj();
using (var isoStream = new IsolatedStorageFileStream("/projects/" + filename, FileMode.Open, FileAccess.Read, FileShare.Read, file))
{
using (StreamReader reader = new StreamReader(isoStream))
{
}
}
This was the solution I came up with
List<ProjectObj> ret = new List<ProjectObj>();
IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication();
if (!file.DirectoryExists("/projects/"))
return ret;
foreach (String filename in file.GetFileNames("/projects/"))
{
IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFileStream fileStream = myIsolatedStorage.OpenFile("/projects/"+filename, FileMode.Open, FileAccess.Read);
using (StreamReader reader = new StreamReader(fileStream))
{
String fileInfo = reader.ReadToEnd();
}
}
I don't know why I was getting the illegal operation on boot of app but I know why it was happening later on. I guess when you try and access the same file to quickly it causes errors. So I added in a fileshare and also I made sure to dispose of other accesses before this ran.