When I run the following code to test copying a directory, I get a System.IO.IOException when fileInfo.CopyTo method is being called. The error message is: "The process cannot access the file 'C:\CopyDirectoryTest1\temp.txt' because it is being used by another process."
It seems like there's a lock on file1 ("C:\CopyDirectoryTest1\temp.txt") which is created a few lines above where the error is occurring, but I don't know how to release this if so. Any ideas?
using System;
using System.IO;
namespace TempConsoleApp
{
class Program
{
static void Main(string[] args)
{
string folder1 = #"C:\CopyDirectoryTest1";
string folder2 = #"C:\CopyDirectoryTest2";
string file1 = Path.Combine(folder1, "temp.txt");
if (Directory.Exists(folder1))
Directory.Delete(folder1, true);
if (Directory.Exists(folder2))
Directory.Delete(folder2, true);
Directory.CreateDirectory(folder1);
Directory.CreateDirectory(folder2);
File.Create(file1);
DirectoryInfo folder1Info = new DirectoryInfo(folder1);
DirectoryInfo folder2Info = new DirectoryInfo(folder2);
foreach (FileInfo fileInfo in folder1Info.GetFiles())
{
string fileName = fileInfo.Name;
string targetFilePath = Path.Combine(folder2Info.FullName, fileName);
fileInfo.CopyTo(targetFilePath, true);
}
}
}
}
File.Create returns an open FileStream - you need to close that stream.
Just
using (File.Create(file1)) {}
should do the trick.
Related
I have a Save ActionResult in my Controller that is set up to use StreamWriter. The code works perfectly, for saving to a file that exists.
Save Action
[HttpPost]
[ValidateInput(false)]
public ActionResult Save(string fileName, string startTemplateUrl, string html)
{
string directoryname = Path.GetDirectoryName(fileName);
string filename = Path.GetFileName(fileName);
var lines = html;
var helper = (Server.MapPath(directoryname));
using (StreamWriter outputFile = new StreamWriter(Path.Combine(helper, filename)))
{
outputFile.WriteLine(lines);
return View();
}
}
I am now working on a file creation and from what i have read you can do this with StreamWriter although when I try to implement it, it says it cannot be found. Which tells me it is looking for a file instead of creating it.
So I tried to implement this using FileInfo. It appears that it has everything it needs but just doesn't save it. Below is my latest code. It does not like the
fs.Write(lines);
I had a try catch block. on this and it had the same results. That it cannot find it.
[HttpPost]
[ValidateInput(false)]
public ActionResult Create (string fileName, string startTemplateUrl, string html)
{
string directoryname = Path.GetDirectoryName(fileName);
string filename = Path.GetFileName(fileName);
var lines = html;
var helper = (Server.MapPath(directoryname));
var file = "Test\\" + filename;
var pathString = System.IO.Path.Combine(helper, "Test\\", filename);
FileInfo fi = new FileInfo(pathString);
if (fi.Exists)
{
fi.Delete();
}
using (FileStream fs = fi.Create())
{
fs.Write(lines);
return View();
}
}
Thanks for your help!
Update:
This is the message I get. Below the message I have the actual string to the directory copied from folder explorer..
Exception thrown: 'System.IO.DirectoryNotFoundException' in mscorlib.dll
An exception of type 'System.IO.DirectoryNotFoundException' occurred in mscorlib.dll but was not handled in user code
Could not find a part of the path 'C:\Users\Scott\source\repos\HMIBuilder\HMIBuilder\Files\HMIBuider\Test\Test2.html'.
C:\Users\Scott\source\repos\HMIBuilder\HMIBuilder\Files\HMIBuilder\Test
Update:
I need to look at my code better! This is fixed.. The code at the very top works perfectly for both save and create. The problem was in the javascript code variables that i was feeding it. A Typo... If you look at the above comparison, which I did not catch myself, too many long nights I suppose, HMIBuilder is spelled HMIBuider... in the error.
using (StreamWriter outputFile = new StreamWriter(Path.Combine(path, "filename.txt")))
would create a new file, if needed.
Your problem may be the Test directory and CreateDirectory is here to help.
DirectoryInfo di = Directory.CreateDirectory(path);
If we put the writing to the file and creating directories together it could look like the following snippet.
var path = "./MyFiles/SpecialFiles";
var filename = "thisIsAVerySpecialFile.txt";
Directory.CreateDirectory(path);
//Create a new file or overwrite existing (i.e. *not* append)
using (var f = new StreamWriter(Path.Combine(path, filename)))
{
f.WriteLine("Hello world!");
}
Without Directory.CreateDirectory the code results in System.IO.DirectoryNotFoundException with 'Could not find a part of the path '(...)'.
i try to write line in file when this exists:
My code is next:
string strRuta = "C:\File.txt"
if (!Directory.Exists(strRuta))
Directory.CreateDirectory(strRuta);
string psContenido = "Hola";
if (!(File.Exists(strRuta + strNombreArchivo)))
{
swArchivo = File.CreateText(strRuta + strNombreArchivo);
}
if (!psContenido.ToLower().Contains("error"))
{
swArchivo.WriteLine(psContenido);
swArchivo.Flush();
swArchivo.Close();
swArchivo.Dispose();
File.SetCreationTime(strRuta + strNombreArchivo, DateTime.Now);
}
but when run this program i have a error in WriteLine, i donĀ“t undertand which is the reason, could you help me?
I would like to know how to write in the file(in the next line the word)
There are a couple of problems, I think. First, you're specifying what looks like a file name and creating a directory with that name (not sure if this is intentional or not). Second, you can use the static helper method AppendAllText of the File class to both create the file if it doesn't exist, and to write the contents to the end of the file. It handles all the streamwriter stuff for you, so you don't have to worry about calling close and dispose.
private static void Main(string[] args)
{
string directory = #"C:\private\temp";
string fileName = "MyFile.txt";
string filePath = Path.Combine(directory, fileName);
string fileContents = "This will be written to the end of the file\r\n";
// This will create the directory if it doesn't exist
Directory.CreateDirectory(directory);
// This will create the file if it doesn't exist, and then write the text at the end.
File.AppendAllText(filePath, fileContents);
File.SetCreationTime(filePath, DateTime.Now);
}
I have written a c# code to copy a csv file to a new location.
If the file already exists in the target location file should be deleted and paste the new file back.
This process should be recurring and runs in the background since the csv file is updating every 5 minutes.
The current issue is even the file was deleted in the target path the new file won't be written back.
My code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
namespace filemove
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
}
public void Start()
{
mysql();
}
static void mysql()
{
string fileName = "data.csv";
string sourcePath = #"\\192.168.16.12\Users";
string targetPath = #"C:\Users\Admin\source";
// Use Path class to manipulate file and directory paths.
string sourceFile = System.IO.Path.Combine(sourcePath, fileName);
string destFile = System.IO.Path.Combine(targetPath, fileName);
// To copy a folder's contents to a new location:
// Create a new target folder, if necessary.
if (!System.IO.Directory.Exists(targetPath))
{
System.IO.Directory.CreateDirectory(targetPath);
}
// To copy a file to another location and
// overwrite the destination file if it already exists.
System.IO.File.Copy(sourceFile, destFile, true);
// To copy all the files in one directory to another directory.
// Get the files in the source folder. (To recursively iterate through
// all subfolders under the current directory, see
// "How to: Iterate Through a Directory Tree.")
// Note: Check for target path was performed previously
// in this code example.
if (System.IO.Directory.Exists(sourcePath))
{
string[] files = System.IO.Directory.GetFiles(sourcePath);
// Copy the files and overwrite destination files if they already exist.
foreach (string s in files)
{
// Use static Path methods to extract only the file name from the path.
fileName = System.IO.Path.GetFileName(s);
destFile = System.IO.Path.Combine(targetPath, fileName);
FileInfo info = new FileInfo(destFile);
bool exists = info.Exists;
if (exists == true)
{
File.Delete(#"C:\Users\Admin\source\Bargstedt.csv");
}
else
{
System.IO.File.Copy(s, destFile, true);
}
}
}
else
{
Console.WriteLine("Source path does not exist!");
}
// Keep console window open in debug mode.
Console.WriteLine("Press any key to exit.");
//Console.ReadKey();
}
public void OnStop()
{
}
}
}
Can anyone figure out what's the error is?
File.Delete actually doesn't throw any exception if file doesn't exists. So, I will just remove a check for exists entirely.
try {
int delay = 400;
File.Delete(#"C:\Users\Admin\source\Bargstedt.csv");
Thread.Sleep(delay); // to prevent delete and copy happening at the
// same time.
System.IO.File.Copy(s, destFile, true);
}catch (IOException ex) {}
You can also check at this post:
FileStream and a FileSystemWatcher in C#, Weird Issue "process cannot access the file"
and user EventHorizon's answer checking for if file is closed.
Its also advisable to check whether directory has permissions (FileIOPermissionAccess.Write)
I think you mean to write the file even if there was a file.
You're using:
bool exists = info.Exists;
if (exists == true)
{
File.Delete(#"C:\Users\Admin\source\Bargstedt.csv");
}
else
{
System.IO.File.Copy(s, destFile, true);
}
Remove the else:
bool exists = info.Exists;
if (exists == true)
{
File.Delete(#"C:\Users\Admin\source\Bargstedt.csv");
}
System.IO.File.Copy(s, destFile, true);
Use this to copy a file when it is existing in target path and with a backup plan for that existing file.
// To copy a file to another location and
// overwrite the destination file if it already exists.
if (!File.Exists(destFile))
{
System.IO.File.Copy(sourceFile, destFile, true);
}
else
{
System.IO.File.Move(destFile, existingFilePath); //if file is existing and then move it to specific folder
try
{
System.IO.File.Copy(sourceFile, destFile, true);
}
catch (Exception)
{
System.IO.File.Move(existingFilePath, destFile); //If anythig went wrong, old file is relocated correctly
}
System.IO.File.Delete(existingFilePath); // Delete old file, all is ok now.
}
I am struggling to configure a script to unzip all .zip archives in a directory and place the extracted files into a different directory. I am wanting to schedule this script to run on a schedule to handle incoming .zip archives.
For each .zip file in the source directory, I need it to extract those files to the destination, then repeat until all .zip files have been processed.
Here is my horrible attempt.
using System;
using System.IO;
using System.IO.Compression;
namespace Unzipper
{
class Program
{
static void Main(string[] args)
{
string startPath = #"C:\zipdirectory\";
foreach(String file in Directory.GetFiles(startPath, "*.zip", SearchOptions.AllDirectories)){allFiles.Add(file);
string zipPath = #"(output from above??)
string extractPath = #"C:\unzipdirectory\";
ZipFile.ExtractToDirectory(zipPath, extractPath);
}
}
}
Firstly, you get all .zip file in the startPath
For each path, unzip it to a new folder created by a combination like C:\unzipdirectory\<zip_file_name_without_extension_zip>
static void Main(string[] args)
{
string startPath = #"C:\zipdirectory\";
string extractPath = #"C:\unzipdirectory\";
Directory.GetFiles(startPath, "*.zip", SearchOptions.AllDirectories).ToList()
.ForEach(zipFilePath => {
var extractPathForCurrentZip = Path.Combine(extractPath, Path.GetFileNameWithoutExtension(zipFilePath));
if(!Directory.Exists(extractPathForCurrentZip))
{
Directory.CreateDirectory(extractPathForCurrentZip);
}
ZipFile.ExtractToDirectory(zipFilePath, extractPathForCurrentZip);
});
}
I got this error "Cannot access a closed file" when I save more than one file in zip.
This is the code. Error at zip.Save(NewZipPath);
internal static string UpdateZipFile(string PdfPath, string ZipPath,
string NewZipPath, string docPath)
{
try
{
using (ZipFile zip = ZipFile.Read(ZipPath))
{
FileStream fs = new FileStream(PdfPath, FileMode.Open, FileAccess.Read);
DirectoryInfo Dir = new DirectoryInfo(docPath);
FileInfo[] FileList = Dir.GetFiles("*.*", SearchOption.AllDirectories);
foreach (FileInfo FI in FileList)
{
zip.AddEntry(FI.FullName, fs);
}
// Error at this line if more than one
// files in above directory.
zip.Save(NewZipPath);
fs.Close();
fs.Dispose();
return "- ZIP Generated Successfully !";
}
}
catch (Exception ex)
{
return ex.Message;
}
}
Full exception
System.ObjectDisposedException: Cannot access a closed file.
at System.IO.__Error.FileNotOpen()
at System.IO.FileStream.get_Length()
at Ionic.Zip.ZipEntry.SetInputAndFigureFileLength(Stream& input)
at Ionic.Zip.ZipEntry._WriteEntryData(Stream s)
at Ionic.Zip.ZipEntry._EmitOne(Stream outstream)
at Ionic.Zip.ZipEntry.Write(Stream s)
at Ionic.Zip.ZipFile.Save()
at Ionic.Zip.ZipFile.Save(String fileName)
at RideShare.Utility.UpdateZipFile(String PdfPath,
String ZipPath, String NewZipPath, String docPath) in
Thanks.
I think what's going on here is that the use of the stream "FS" is tangled up. You can spend time trying to untangle it, or you can use the simpler "AddFiles" method:
Search for "Create a zip containing all the files in a folder." at
http://dotnetzip.codeplex.com/wikipage?title=CS-Examples&referringTitle=Examples
the exception happens because AddEntry uses the FileStram and after it is finished with the FileStream it closes it automatically.. so it is closed during Save after the first file... when there is one file it is ok - but your code adds the same FileStream fs for every file... not sure that this is what you really want... I think you would want to open one separate stream per file you add via AddEntry...
change your code to:
foreach (FileInfo FI in FileList)
{
zip.AddFile(FI.FullName);
}
OR replace the foreach loop by
zip.AddFiles((from FI in Dir.GetFiles("*.*", SearchOption.AllDirectories) select FI.FullName).ToArray());