I have written a windows service to move a file from one location to another and,
then read the file in the new location and write the data to the database.
In the middle of the execution there is an error message:
IOException: The process cannot access the file 'file path' because it is being used by another process.
My code:
File move class
public void mysql()
{
string fileName = "Bargstedt.csv";
string sourcePath = #"\\192.168.1.2\Data\Company Files\";
string targetPath = #"C:\Users\source";
string sourceFile = System.IO.Path.Combine(sourcePath, fileName);
string destFile = System.IO.Path.Combine(targetPath, fileName);
if (!System.IO.Directory.Exists(targetPath))
{
System.IO.Directory.CreateDirectory(targetPath);
}
System.IO.File.Copy(sourceFile, destFile, true);
if (System.IO.Directory.Exists(sourcePath))
{
string[] files = System.IO.Directory.GetFiles(sourcePath);
fileName = System.IO.Path.GetFileName(fileName);
destFile = System.IO.Path.Combine(targetPath, fileName);
FileInfo info = new FileInfo(destFile);
bool exists = info.Exists;
if (exists == true)
{
try
{
int delay = 400;
File.Delete(#"C:\Users\Isuruh\source\Bargstedt.csv");
Thread.Sleep(delay);
System.IO.File.Copy(sourceFile, destFile, true);
Debug.WriteLine("file moved");
}
catch (IOException ex) { }
}
}
else
{
Console.WriteLine("Source path does not exist!");
}
Console.WriteLine("Press any key to exit.");
}
Insert Class
public void Insert()
{
if (this.OpenConnection() == true)
{
using(var reader = new StreamReader(#"C:\Users\source\Bargstedt.csv"))
//using (var stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.ReadWrite))
{
List<string> listA = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
string querynew = "INSERT INTO new_jobs"
+ "(board_code,status,code,no1,no2,thickness,dimension,material,root,variable,number,stable,constant)"
+ "VALUES (?jobNo, ?strClientName, ?strClientReference, ?strJobCategory, ?datCommisioned, ?datPromisedDelivery, ?division, ?date_assigned, ?root, ?variable, ?number, ?stable, ?constant)";
I did not mention the whole code for the service since it's too lengthy.
As given in Solution 01 I tried to use,
using (var stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.Read))
line instead of
using(var reader = new StreamReader(#"C:\Users\source\Bargstedt.csv"))
But that triggers errors in the below keywords I have used.
I am not sure is it possible to use a file open instead of a reader class?
Basically, what I need to do is start the Insert process after completing the file move process.
Any suggestions on how to do that?
PS: This is possibly a duplicate question of the question I have mentioned above. I tried my very best to make this question unique. Appreciate if not marked as duplicate. Thank you!
Related
My program goes through all files in a folder, reads them, and without altering their information moves them to another location under a different name. However I cannot use the File.Move method because I get the following IOException:
The process cannot access the file because it is being used by another
process.
This is how I am reading the file and adding all its lines to a List<string>:
List<string> lines = null;
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var sr = new StreamReader(fs, Encoding.Default))
{
lines = new List<string>();
while (!sr.EndOfStream)
lines.Add(sr.ReadLine());
}
And this is the function with which I move the file:
public static bool ArchiveFile(string filePath, string archiveFolderLocation)
{
if (!Directory.Exists(archiveFolderLocation))
Directory.CreateDirectory(archiveFolderLocation);
try
{
string timestamp = string.Format("{0:yyyy-MM-dd HHmmss}", DateTime.Now);
string newFileName = Path.GetFileNameWithoutExtension(filePath) + " " + timestamp;
string destination = string.Format("{0}\\{1}{2}", archiveFolderLocation, newFileName, Path.GetExtension(filePath));
File.Move(filePath, destination);
return true;
}
catch (Exception ex)
{
return false;
}
}
I thought using the using statement is supposed to garbage-collect and release the file after being used. How can I release the file so I can move it and why my file stays locked?
Solved:
Got it. Somewhere between these two calls I was opening a TextReaderobject without disposing it.
I thought using the using statement is supposed to garbage-collect and
release the file after being used. How can I release the file so I can
move it and why my file stays locked?
Not really. Using statement is nothing but :
try { var resource = new SomeResource(); }
finally { resource.Dispose(); // which is not GC.Collect(); }
It works fine so it looks like your file is opened from some other place in your code...
P.S.
By the way you can just do:
List<string> lines = File.ReadAllLines().ToList();
You could use:
string dpath = "D:\\Destination\\";
string spath = "D:\\Source";
string[] flist = Directory.GetFiles(spath);
foreach (string item in flist)
{
File.Move(item, dpath + new FileInfo(item).Name);
}
Replace D:\\Source & D:\\Destination\\ with the required source and destination paths, respectively.
So I got the IOException: Attempted to Seek before the beginning of the stream. But when I looked into it the seek statement was inside of a using statement. I might be missunderstanding the using() because as far as I knew this initializes the in this case filestream before running the encased code.
private string saveLocation = string.Empty;
// This gets called inside the UI to visualize the save location
public string SaveLocation
{
get
{
if (string.IsNullOrEmpty(saveLocation))
{
saveLocation = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + #"\Pastes";
Initializer();
}
return saveLocation;
}
set { saveLocation = value; }
}
And this is the function it calls
private void Initializer()
{
// Check if the set save location exists
if (!Directory.Exists(saveLocation))
{
Debug.Log("Save location did not exist");
try
{
Directory.CreateDirectory(saveLocation);
}
catch (Exception e)
{
Debug.Log("Failed to create Directory: " + e);
return;
}
}
// Get executing assembly
if (string.IsNullOrEmpty(executingAssembly))
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
executingAssembly = Uri.UnescapeDataString(uri.Path);
}
// Get the last received list
if (!string.IsNullOrEmpty(executingAssembly))
{
var parent = Directory.GetParent(executingAssembly);
if (!File.Exists(parent + #"\ReceivedPastes.txt"))
{
// empty using to create file, so we don't have to clean up behind ourselfs.
using (FileStream fs = new FileStream(parent + #"\ReceivedPastes.txt", FileMode.CreateNew)) { }
}
else
{
using (FileStream fs = new FileStream(parent + #"\ReceivedPastes.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
if (fs.Seek(-20000, SeekOrigin.End) >= 0)
{
fs.Position = fs.Seek(-20000, SeekOrigin.End);
}
using (StreamReader sr = new StreamReader(fs))
{
while (sr.ReadLine() != null)
{
storedPastes.Add(sr.ReadLine());
}
}
}
}
}
isInitialized = true;
}
Are the commentors have posted: the file is less than 20000 bytes. It seems like you assume that Seek will stay at position 0 if the file is not large enough. It doesn't. It throws ArgumentException in that case.
Another thing. Seek will move the position for you. No need to do both. Either use:
fs.Seek(-20000, SeekOrigin.End);
or set the position:
fs.Position = fs.Length - 20000;
So what you really wanted to write is:
if (fs.Length > 20000)
fs.Seek(-20000, SeekOrigin.End);
i got a file that is store in my appliction directory, and he got some site list.
i dont have any problem reading it, but when i want to write to it, i get
System.ArgumentException: Stream is not writeable
this is how i accsess the file:
FileStream theTextFileStream = new FileStream(Environment.CurrentDirectory + "/fourmlinks.txt",FileMode.OpenOrCreate);
and this is the function that throw me the expection:
public static void WriteNewTextToFile(string text, FileStream theFile)
{
string fileText = GetAllTextFromFile(theFile);
ArrayList fileLIst = populateListFromText(fileText);
using (StreamWriter fileWriter = new StreamWriter(theFile))
{
fileWriter.Write(String.Empty);
for (int i = 0; i < fileLIst.Count; i++)
{
fileWriter.WriteLine(fileLIst[i].ToString());
}
}
}
the function read the old and new text and add it to an arry. then i clean the file from every thing, and rewriting it with the old and new data from the arry i made.
i dont know if that will help but here is the file proprites:
Build Action: None
Copy To Out Put Directory: Copy always
why i cant rewrite the file?
this is the function i use to read the file content:
public static string GetAllTextFromFile(FileStream theFile)
{
string fileText = "";
using (theFile)
{
using (StreamReader stream = new StreamReader(theFile))
{
string currentLine = "";
while ((currentLine = stream.ReadLine()) != null)
{
fileText += currentLine + "\n";
}
}
}
return fileText;
}
You have to use Read/Write file access as third parameter -
FileStream theTextFileStream = new FileStream(Environment.CurrentDirectory + "/fourmlinks.txt",FileMode.OpenOrCreate, FileAccess.ReadWrite
);
Important - Remove using(theFile) statement:
public static string GetAllTextFromFile(FileStream theFile)
{
string fileText = "";
using (StreamReader stream = new StreamReader(theFile))
{
string currentLine = "";
while ((currentLine = stream.ReadLine()) != null)
{
fileText += currentLine + "\n";
}
}
return fileText;
}
Do not use using construct in your case as it will close the underlying stream as in your case you have to manually open and close stream objects.
This will allow you to write in the file as well.
For more information refer following links -
FileStream Constructor
FileAccess Enumeration
I have developed a windows application, which will read updated data from .jrn files(In an ATM Machine) and will be copy the text to a temporary text file "tempfile.txt".
There is another third party application called "POS Text Sender", which reads "tempfile.txt" and display the contents of it in a CCTV Camera.
The problem is that if I type directly something in the tempfile, the POS application will read it, but if my application writes text to "tempfile", I can see the same content as in the .jrn file in tempfile, but it is not reflected in the POS application when ever data is copied from newly generated file to tempfile.if restart the POS Text Sender after the first data copied to tempfile from newly generated file,POS Text sender will display the content til content from newly created file is written to tempfile
My application code is reading .jrn file using StreamReader and assigning it to a string variable and then writing it to a tempfile using StreamWriter. What is the difference between manually typing text on a file and .NET StreamWriter writing text to a file?
CODE:
DateTime LastChecked = DateTime.Now;
try
{
string[] files = System.IO.Directory.GetFiles(#"C:\Test", "*.jrn", System.IO.SearchOption.AllDirectories);
foreach (string file in files)
{
if (!fileList.Contains(file))
{
currentfilename = file;
fileList.Add(file);
copywarehouse(file);
//do_some_processing();
try
{
// Create an instance of StreamReader to read from a file.
// The using statement also closes the StreamReader.
using (StreamReader sr = new StreamReader(file))
{
currentcontent=sr.ReadToEnd();
// Read and display lines from the file until the end of
//// the file is reached.
//while ((currentcontent = sr.ReadLine()) != null)
//{
//}
sr.Close();
//sr.Dispose();
}
}
catch (Exception)
{
// Let the user know what went wrong.
}
}
}
//checking
try
{
using (StreamReader sr = new StreamReader(currentfilename))
{
string currentfilecontent = sr.ReadToEnd();
sr.Close();
//sr.Dispose();
if (currentfilecontent!=currentcontent)
{
if (currentfilecontent.Contains(currentcontent))
{
string originalcontent = currentfilecontent.Substring(currentcontent.Length);
System.IO.StreamWriter filenew = new System.IO.StreamWriter(#"C:\Test\tempfile.txt");
filenew.WriteLine(originalcontent);
filenew.Close();
currentcontent = currentfilecontent;
}
}
}
}
catch (Exception)
{
// Let the user know what went wrong.
}
copywarehouse method:
private void copywarehouse(string filename)
{
string sourcePath = #"C:\Test";
string targetPath = #"C:\Test";
try
{
string sourceFile = System.IO.Path.Combine(sourcePath, filename);
string destFile = System.IO.Path.Combine(targetPath, "tempfile.txt");
System.IO.File.Copy(sourceFile, destFile, true);
}
catch (Exception)
{
}
}
Can you check the following:
Is the generated file encoding same as the manually created file? (i.e. UTF-8/ANSI).
Are your constantly flushing the streamWriter's buffer? Or set the StreamWriter's AutoFlush property to true.
Is the StreamWriter opened with a WriteLock with no read allowed? In this case the other application may not be able to open your tempfile for read access.
EDIT:
Also, in the code you posted, you are comparing the tempFile data to current data, and if tempFile data is newer than current data, you are appending the temp file, which I think should be vice versa.
Main change:
using (StreamWriter filenew = new StreamWriter(fileDetail.TempFileName, true, Encoding.ASCII))
{
filenew.WriteLine(newContent);
}
To know the correct encoding, just create a new tempFile, write something in the editor and save it. Open the file in notepad and do a "save as". This will display the current encoding in the bottom. Set that encoding in .NET code.
If this does not work try (As recommended by shr):
using (StreamWriter filenew = new StreamWriter(fileDetail.TempFileName, true, Encoding.ASCII))
{
filenew.Write(newContent + "\r\n");
}
Long Version: (It may be a bit different than your code):
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
DateTime LastChecked = DateTime.Now;
IDictionary<string, FileDetails> fileDetails = new Dictionary<string, FileDetails>(StringComparer.OrdinalIgnoreCase);
IList<string> tempFileList = new List<string>();
try
{
string[] files = System.IO.Directory.GetFiles(#"C:\Test", "*.jrn", System.IO.SearchOption.AllDirectories);
foreach (string file in files)
{
string currentfilename = file;
string currentcontent = string.Empty;
if (!fileDetails.Keys.Contains(file))
{
fileDetails[file] = new FileDetails(copywarehouse(file));
//do_some_processing();
}
try
{
using (StreamReader sr = new StreamReader(file))
{
currentcontent = sr.ReadToEnd();
}
}
catch (Exception)
{
// Let the user know what went wrong.
}
fileDetails[file].AddContent(currentcontent);
}
//TODO: Check using the file modified time. Avoids unnecessary reading of file.
foreach (var fileDetail in fileDetails.Values)
{
//checking
try
{
string tempFileContent = string.Empty;
string currentcontent = fileDetail.GetContent();
using (StreamReader sr = new StreamReader(fileDetail.TempFileName))
{
tempFileContent = sr.ReadToEnd();
sr.Close();
}
if (!(0 == string.Compare(tempFileContent, currentcontent)))
{
if (currentcontent.Contains(tempFileContent))
{
string newContent = tempFileContent.Substring(currentcontent.Length);
using (StreamWriter filenew = new StreamWriter(fileDetail.TempFileName, true, Encoding.ASCII))
{
filenew.WriteLine(newContent);
}
}
}
}
catch (Exception)
{
// Let the user know what went wrong.
}
}
}
catch (Exception)
{
}
}
private static string copywarehouse(string filename)
{
string sourcePath = #"C:\Test";
string targetPath = #"C:\Test";
string sourceFile = System.IO.Path.Combine(sourcePath, filename);
string destFile = System.IO.Path.Combine(targetPath, filename+ "tempfile.txt");
try
{
System.IO.File.Copy(sourceFile, destFile, true);
}
catch (Exception)
{
}
return destFile;
}
internal class FileDetails
{
public string TempFileName { get; private set; }
private StringBuilder _content;
public FileDetails(string tempFileName)
{
TempFileName = tempFileName;
_content = new StringBuilder();
}
public void AddContent(string content)
{
_content.Append(content);
}
public string GetContent()
{
return _content.ToString();
}
}
}
}
EDIT 2:
Can you change the copywarehouse to this and see it the problem persists:
private void copywarehouse(string filename)
{
const string sourcePath = #"C:\Test";
const string targetPath = #"C:\Test";
try
{
string sourceFile = Path.Combine(sourcePath, filename);
string destFile = Path.Combine(targetPath, "tempfile.txt");
string currentcontent;
using (var sr = new StreamReader(sourceFile))
{
currentcontent = sr.ReadToEnd();
}
using (var wr = new StreamWriter(destFile, false, Encoding.ASCII))
{
wr.WriteLine(currentcontent);
}
}
catch (Exception)
{
}
}
Most likely this is a CR+LF issue.
The POS expects the file to have line endings with CR+LF (Carriage Return (0x0D) + New line (0x0A)) combination.
The filenew.WriteLine(originalcontent) appends only the new line character. When you type, I think, you editor must be creating the CR+LF combination for all line endings.
I suggest you try filenew.Write( originalcontent + "\r\n");
One difference is that your application does not write to tempfile.txt directly but to another file and then copies that file to tempfile.txt.
I am trying to upload a file in asp.net. File may be image or pdf. If the file already exist then I have to remove existing file and upload the new file. But if I try to delete existing file, it shows an error that "The process cannot access the file because it is being used by another process"
This is the code for my file upload.
if (FileUploadFollowUpUN.HasFile)
{
if (Request.QueryString.Count > 0 && Request.QueryString["PCD"] != null)
{
filename = System.IO.Path.GetFileName(FileUploadFollowUpUN.FileName.Replace(FileUploadFollowUpUN.FileName, Request.QueryString["PCD"] + " " + "D" + Path.GetExtension(FileUploadFollowUpUN.FileName)));
SaveFilePath = Server.MapPath("~\\ECG\\") + filename;
DirectoryInfo oDirectoryInfo = new DirectoryInfo(Server.MapPath("~\\ECG\\"));
if (!oDirectoryInfo.Exists)
Directory.CreateDirectory(Server.MapPath("~\\ECG\\"));
if (File.Exists(SaveFilePath))
{
File.SetAttributes(SaveFilePath, FileAttributes.Normal);
File.Delete(SaveFilePath);
}
FileUploadFollowUpUN.SaveAs(Server.MapPath(this.UploadFolderPath) + filename);
Session["FileNameFollowUpUN"] = filename;
if (System.IO.Path.GetExtension(FileUploadFollowUpUN.FileName) == ".pdf")
{
imgPhoto.ImageUrl = "~/Images/pdf.jpg";
ZoomImage.ImageUrl = "~/Images/pdf.jpg";
imgPhoto.Enabled = true;
}
else
{
imgPhoto.ImageUrl = "~/ECG/" + filename;
imgPhoto.Enabled = true;
ZoomImage.ImageUrl = "~/ECG/" + filename;
}
}
}
How can I get rid out of this error?
There is a similar question here on how to find what process is using a file
You should try to dispose any file methods before trying to delete.
You could stick it in a while loop if you have something which will block until the file is accessible
public static bool IsFileReady(String sFilename)
{
// If the file can be opened for exclusive access it means that the file
// is no longer locked by another process.
try
{
using (FileStream inputStream = File.Open(sFilename, FileMode.Open, FileAccess.Read, FileShare.None))
{
if (inputStream.Length > 0)
{
return true;
}
else
{
return false;
}
}
}
catch (Exception)
{
return false;
}
}