I am currently writing a .csv to client browser using Response object, which was/is a fairly easy job.
But now the requirement has been changed to create this file at a network location from where any time the job will pick it.
I am not sure how can I achieve this, any suggestions would be helpful.
Existing Code:
Response.ClearContent();
Response.AddHeader("content-disposition", "attachment;filename=" + GenerateFileName(publishToViewModel[0].ProjectId));
Response.ContentType = "text/csv";
StreamWriter writer = new StreamWriter();
try
{
string CSVFriendlyData = this.GetCSV(publishToViewModel);
writer.Write(CSVFriendlyData);
Response.Write(writer.ToString());
Response.End();
}
since it is hard to guarantee that a write to a network file will be successful (your old file might still be there, and the timed job might have a lock on it, etc) it's a good idea to build a mechanism that will retry writing to the file several times.
void WriteToNetworkFile()
{
int retries = 3;
while(retries > 0)
{
if(tryWriteFile())
{
break;
}
retries--;
// you could add a timeout here to make sure your attempts are a little more
//spaced out.
//it could be in the form of a Thread.Sleep, or you could extract a method and
//call it using a timer.
if(retries < 1)
{
//log that we failed to write the file and gave up on trying.
}
}
}
protected void tryWriteFile()
{
try
{
//you could pass this path as a parameter too.
var fileLoc = "\\server\folder\file.ext";
//open and obtain read/write lock on the file
//using FileMode.CreateNew will ensure that a new file is created.
//alternatively, you can use FileMosw.Create to create a new file
//or overwrite the old file if it is there.
using (var fs = File.Open(fileLoc, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None))
{
var sw = new StreamWriter(fs);
sw.Write("file contents go here");
sw.Flush();
sw.Close();
return true;
}
}
catch(Exception e)
{
//you might want to log why the write failed here.
return false;
}
}
Related
I'm writing an application in visual studio using c#. I want to check if readalltext finds the file correctly, if not it needs to create the file and put a zero in it. In pseudocode:
if(x=File.ReadAllText("file.txt")==NULL)
{
File.WriteAllText("file.txt", "0");
x=File.ReadAllText("file.txt");
}
How can I do this? Thanks in advance, I tried some google but I may be inputting the wrong keywords
You can check whether a file exists with the File.Exists() method.
string path = "file.txt";
if (!File.Exists(path))
{
File.WriteAllText(path, "0");
}
The problem with using File.Exist() is that there is a risk the file is created or deleted after the check was made. The risk may be small, but may still need to be handled. One way to handle this would be with a try/catch inside a loop:
while (true)
{
try
{
if (!File.Exists(path))
{
File.WriteAllText(path, "0");
return "0";
}
else
{
return File.ReadAllText(path);
}
}
catch (IOException)
{
// try again
}
}
Another way would be to skip ReadAllText and instead open a fileStream. If that succeeds you know you have exclusive access to the file, to either read or write to it:
try
{
using var fs = File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
if (fs.Length == 0)
{
using var sw = new StreamWriter(fs);
sw.Write('0');
return "0";
}
else
{
using var sr = new StreamReader(fs);
return sr.ReadToEnd();
}
}
catch (Exception)
{
// Handle the various types of exception that may occur.
}
I'm trying to detect if a file exists at runtime, if not, create it. However I'm getting this error when I try to write to it:
The process cannot access the file 'myfile.ext' because it is being used by another process.
string filePath = string.Format(#"{0}\M{1}.dat", ConfigurationManager.AppSettings["DirectoryPath"], costCentre);
if (!File.Exists(filePath))
{
File.Create(filePath);
}
using (StreamWriter sw = File.AppendText(filePath))
{
//write my text
}
Any ideas on how to fix it?
File.Create(FilePath).Close();
File.WriteAllText(FileText);
I want to update this answer to say that this is not really the most efficient way to write all text. You should only use this code if you need something quick and dirty.
I was a young programmer when I answered this question, and back then I thought I was some kind of genius for coming up with this answer.
The File.Create method creates the file and opens a FileStream on the file. So your file is already open. You don't really need the file.Create method at all:
string filePath = #"c:\somefilename.txt";
using (StreamWriter sw = new StreamWriter(filePath, true))
{
//write to the file
}
The boolean in the StreamWriter constructor will cause the contents to be appended if the file exists.
When creating a text file you can use the following code:
System.IO.File.WriteAllText("c:\test.txt", "all of your content here");
Using the code from your comment. The file(stream) you created must be closed. File.Create return the filestream to the just created file.:
string filePath = "filepath here";
if (!System.IO.File.Exists(filePath))
{
System.IO.FileStream f = System.IO.File.Create(filePath);
f.Close();
}
using (System.IO.StreamWriter sw = System.IO.File.AppendText(filePath))
{
//write my text
}
FileStream fs= File.Create(ConfigurationManager.AppSettings["file"]);
fs.Close();
File.Create returns a FileStream. You need to close that when you have written to the file:
using (FileStream fs = File.Create(path, 1024))
{
Byte[] info = new UTF8Encoding(true).GetBytes("This is some text in the file.");
// Add some information to the file.
fs.Write(info, 0, info.Length);
}
You can use using for automatically closing the file.
I updated your question with the code snippet. After proper indenting, it is immediately clear what the problem is: you use File.Create() but don't close the FileStream that it returns.
Doing it that way is unnecessary, StreamWriter already allows appending to an existing file and creating a new file if it doesn't yet exist. Like this:
string filePath = string.Format(#"{0}\M{1}.dat", ConfigurationManager.AppSettings["DirectoryPath"], costCentre);
using (StreamWriter sw = new StreamWriter(filePath, true)) {
//write my text
}
Which uses this StreamWriter constructor.
I know this is an old question, but I just want to throw this out there that you can still use File.Create("filename")", just add .Dispose() to it.
File.Create("filename").Dispose();
This way it creates and closes the file for the next process to use it.
This question has already been answered, but here is a real world solution that
checks if the directory exists and adds a number to the end if the text file
exists. I use this for creating daily log files on a Windows service I wrote. I
hope this helps someone.
// How to create a log file with a sortable date and add numbering to it if it already exists.
public void CreateLogFile()
{
// filePath usually comes from the App.config file. I've written the value explicitly here for demo purposes.
var filePath = "C:\\Logs";
// Append a backslash if one is not present at the end of the file path.
if (!filePath.EndsWith("\\"))
{
filePath += "\\";
}
// Create the path if it doesn't exist.
if (!Directory.Exists(filePath))
{
Directory.CreateDirectory(filePath);
}
// Create the file name with a calendar sortable date on the end.
var now = DateTime.Now;
filePath += string.Format("Daily Log [{0}-{1}-{2}].txt", now.Year, now.Month, now.Day);
// Check if the file that is about to be created already exists. If so, append a number to the end.
if (File.Exists(filePath))
{
var counter = 1;
filePath = filePath.Replace(".txt", " (" + counter + ").txt");
while (File.Exists(filePath))
{
filePath = filePath.Replace("(" + counter + ").txt", "(" + (counter + 1) + ").txt");
counter++;
}
}
// Note that after the file is created, the file stream is still open. It needs to be closed
// once it is created if other methods need to access it.
using (var file = File.Create(filePath))
{
file.Close();
}
}
I think I know the reason for this exception. You might be running this code snippet in multiple threads.
you can just use using keyword around File.Create(path) to finalize the process
using(File.Create(path));
Try this: It works in any case, if the file doesn't exists, it will create it and then write to it. And if already exists, no problem it will open and write to it :
using (FileStream fs= new FileStream(#"File.txt",FileMode.Create,FileAccess.ReadWrite))
{
fs.close();
}
using (StreamWriter sw = new StreamWriter(#"File.txt"))
{
sw.WriteLine("bla bla bla");
sw.Close();
}
I am trying to export the strings in a nested list to a txt or csv file of the users choice and everything seems to be working but when I actually go to check the file after I have exported it the file is absolutely blank. I went and did it on a separate test program to mock my problem and it worked on that program but when I moved the code over it would still not export anything.
This is just my initialized nested list in case its needed.
List<List<string>> aQuestion = new List<List<string>>();
This is the problem area for the code.
static void writeCSV(List<List<string>> aQuestion, List<char> aAnswer)
{
StreamWriter fOut = null;
string fileName = "";
//export questions
//determine if the file can be found
try
{
Console.Write("Enter the file path for where you would like to export the exam to: ");
fileName = Console.ReadLine();
if (!File.Exists(fileName))
{
throw new FileNotFoundException();
}
}
catch (FileNotFoundException)
{
Console.WriteLine("File {0} cannot be found", fileName);
}
//writes to the file
try
{
fOut = new StreamWriter(fileName, false);
//accesses the nested lists
foreach (var line in aQuestion)
{
foreach (var value in line)
{
fOut.WriteLine(string.Join("\n", value));
}
}
Console.WriteLine("File {0} successfully written", fileName);
}
catch (IOException ioe)
{
Console.WriteLine("File {0} cannot be written {1}", fileName, ioe.Message);
}
So if any of you guys can help me with this problem that would be great because it seems like such a small problem but I can't figure it out for the life of me.
It may happen that the buffer was not flushed to the disk. You should dispose the stream writer and it will push everything out to disk:
using (StreamWriter writer = new StreamWriter(fileName, false)) // <-- this is the change
{
//accesses the nested lists
foreach (var line in aQuestion)
{
foreach (var value in line)
{
writer.WriteLine(string.Join("\n", value));
}
}
}
On a more elaborate level, streams that may cause performance loss are normally buffered. File streams are definitely buffered, because it would be very inefficient to push each separate piece of data to the IO immediately.
When you're working with file streams, you can flush their content explicitly using the StreamWriter.Flush() method - that is useful if you want to debug code and wish to see how far it has gone writing the data.
However, you normally do not flush the stream yourself but just let its internal mechanisms choose the best moment to do that. Instead, you make sure to dispose the stream object, and that will force buffer to be flushed before closing the stream.
Use this simple method instead, it is much easier and it will take care of creating and disposing StreamWriter.
File.WriteAllLines(PathToYourFile,aQuestion.SelectMany(x=>x));
More reference on File.WriteAllLines Here
Also, in your code your not disposing StreamWrite. Enclose it in a Using block. Like this..
using(var writer = new StreamWriter(PathToYourFile,false)
{
//Your code here
}
I am doing the following very basic task in SSH.NET/C# to download a file from a remote server to a local path:
ConnectionInfo c = new PasswordConnectionInfo(remoteIP, port, username, password);
var sftp = new SftpClient(c);
sftp.Connect();
using (var stream = new FileStream(destinationFile, FileMode.Create))
{
//download the file to our local path
sftp.DownloadFile(fileName, stream);
stream.Close();
}
sftp.Disconnect();
Now to determine if the file completely downloaded successfully, would that just be if the code block reached stream.Close()? Or is there a more concrete way to determine if everything was written okay?
EDIT: This post could be helpful to some if you want to see how many bytes have been downloaded. It also makes a primitive progress bar, which is convenient. I tested the code in the post and it does work.
Looking at the source code for SSH.NET, DownloadFile() is a blocking operation and will not return until the file is written fully.
Additionally, calling stream.Close() inside of the using block is not needed, as the object will be Disposed when exiting the block.
When I was working with SSH.NET a while back, for some reason I didn't know about or didn't like the fact that .DownloadFile had no return value. Either way, this was the route I took at the time.
StringBuilder sb = new StringBuilder();
ConnectionInfo c = new PasswordConnectionInfo(remoteIP, port, username, password);
var sftp = new SftpClient(c);
try
{
using (StreamReader reader = sftp.OpenText(fileName))
{
string line;
while ((line = reader.ReadLine()) != null)
{
sb.AppendLine(line);
}
}
File.WriteAllText(destinationFile, sb.ToString());
}
catch(Exception ex)
{
// procress exception
}
I'm trying to detect if a file exists at runtime, if not, create it. However I'm getting this error when I try to write to it:
The process cannot access the file 'myfile.ext' because it is being used by another process.
string filePath = string.Format(#"{0}\M{1}.dat", ConfigurationManager.AppSettings["DirectoryPath"], costCentre);
if (!File.Exists(filePath))
{
File.Create(filePath);
}
using (StreamWriter sw = File.AppendText(filePath))
{
//write my text
}
Any ideas on how to fix it?
File.Create(FilePath).Close();
File.WriteAllText(FileText);
I want to update this answer to say that this is not really the most efficient way to write all text. You should only use this code if you need something quick and dirty.
I was a young programmer when I answered this question, and back then I thought I was some kind of genius for coming up with this answer.
The File.Create method creates the file and opens a FileStream on the file. So your file is already open. You don't really need the file.Create method at all:
string filePath = #"c:\somefilename.txt";
using (StreamWriter sw = new StreamWriter(filePath, true))
{
//write to the file
}
The boolean in the StreamWriter constructor will cause the contents to be appended if the file exists.
When creating a text file you can use the following code:
System.IO.File.WriteAllText("c:\test.txt", "all of your content here");
Using the code from your comment. The file(stream) you created must be closed. File.Create return the filestream to the just created file.:
string filePath = "filepath here";
if (!System.IO.File.Exists(filePath))
{
System.IO.FileStream f = System.IO.File.Create(filePath);
f.Close();
}
using (System.IO.StreamWriter sw = System.IO.File.AppendText(filePath))
{
//write my text
}
FileStream fs= File.Create(ConfigurationManager.AppSettings["file"]);
fs.Close();
File.Create returns a FileStream. You need to close that when you have written to the file:
using (FileStream fs = File.Create(path, 1024))
{
Byte[] info = new UTF8Encoding(true).GetBytes("This is some text in the file.");
// Add some information to the file.
fs.Write(info, 0, info.Length);
}
You can use using for automatically closing the file.
I updated your question with the code snippet. After proper indenting, it is immediately clear what the problem is: you use File.Create() but don't close the FileStream that it returns.
Doing it that way is unnecessary, StreamWriter already allows appending to an existing file and creating a new file if it doesn't yet exist. Like this:
string filePath = string.Format(#"{0}\M{1}.dat", ConfigurationManager.AppSettings["DirectoryPath"], costCentre);
using (StreamWriter sw = new StreamWriter(filePath, true)) {
//write my text
}
Which uses this StreamWriter constructor.
I know this is an old question, but I just want to throw this out there that you can still use File.Create("filename")", just add .Dispose() to it.
File.Create("filename").Dispose();
This way it creates and closes the file for the next process to use it.
This question has already been answered, but here is a real world solution that
checks if the directory exists and adds a number to the end if the text file
exists. I use this for creating daily log files on a Windows service I wrote. I
hope this helps someone.
// How to create a log file with a sortable date and add numbering to it if it already exists.
public void CreateLogFile()
{
// filePath usually comes from the App.config file. I've written the value explicitly here for demo purposes.
var filePath = "C:\\Logs";
// Append a backslash if one is not present at the end of the file path.
if (!filePath.EndsWith("\\"))
{
filePath += "\\";
}
// Create the path if it doesn't exist.
if (!Directory.Exists(filePath))
{
Directory.CreateDirectory(filePath);
}
// Create the file name with a calendar sortable date on the end.
var now = DateTime.Now;
filePath += string.Format("Daily Log [{0}-{1}-{2}].txt", now.Year, now.Month, now.Day);
// Check if the file that is about to be created already exists. If so, append a number to the end.
if (File.Exists(filePath))
{
var counter = 1;
filePath = filePath.Replace(".txt", " (" + counter + ").txt");
while (File.Exists(filePath))
{
filePath = filePath.Replace("(" + counter + ").txt", "(" + (counter + 1) + ").txt");
counter++;
}
}
// Note that after the file is created, the file stream is still open. It needs to be closed
// once it is created if other methods need to access it.
using (var file = File.Create(filePath))
{
file.Close();
}
}
I think I know the reason for this exception. You might be running this code snippet in multiple threads.
you can just use using keyword around File.Create(path) to finalize the process
using(File.Create(path));
Try this: It works in any case, if the file doesn't exists, it will create it and then write to it. And if already exists, no problem it will open and write to it :
using (FileStream fs= new FileStream(#"File.txt",FileMode.Create,FileAccess.ReadWrite))
{
fs.close();
}
using (StreamWriter sw = new StreamWriter(#"File.txt"))
{
sw.WriteLine("bla bla bla");
sw.Close();
}