File is created once, then stops - c#

I am trying to read from a folder, and delete a specified file from inside.
I am able to do this one time without any issues.
However after doing it the first time, I am no longer able to Create the new file. The old one is still deleted, but the new file is no longer being created as it should. My question is; From the code provided why would the task work once, but not after that? It's being deleted after the first time but won't re-create.
EDIT:
The issue was in permissions.
I changed the folder security settings to allow reading/writing and I am now able to do it as I wanted.
However, I need it to automatically set the security settings if possible as other users may not know how to do so.
if (Directory.Exists(path1))
{
if (File.Exists(path1 + "\\launchinfo.txt"))
{
File.Delete(path1 + "\\launchinfo.txt");
using (FileStream fs = File.Create(path1 + "\\launchinfo.txt"))
{
Byte[] info = new UTF8Encoding(true).GetBytes("[Connection]\n" + Form1.ipaddress + "\nport=0000\nclient_port=0\n[Details]\n" + Form1.playername);
fs.Write(info, 0, info.Length);
}
}
else
{
using (FileStream fs = File.Create(path1 + "\\launchinfo.txt"))
{
Byte[] info = new UTF8Encoding(true).GetBytes("[Connection]\n" + Form1.ipaddress + "\nport=0000\nclient_port=0\n[Details]\n" + Form1.playername);
fs.Write(info, 0, info.Length);
}
}
}

You've not posted any possible exception you may be running into - if you do have one, please post it.
That being said, it's possible that you're encountering File in use by another process when trying to delete the file - especially if you're calling your function moments after creating a file.
A method to get around this is to check if a process is using the file before you try to delete it.
string fullPath = Path.Combine(path1, "launchinfo.txt");
if (Directory.Exists(path1))
{
if (File.Exists(fullPath))
{
// Call a method to check if the file is in use.
if (IsFileLocked(new FileInfo(fullPath)){
// do something else because you can't delete the file
} else {
File.Delete(fullPath);
}
}
using (FileStream fs = File.Create(fullPath))
{
Byte[] info = new UTF8Encoding(true).GetBytes("[Connection]\n" + Form1.ipaddress + "\nport=0000\nclient_port=0\n[Details]\n" + Form1.playername);
fs.Write(info, 0, info.Length);
}
}
A method to check if the file is in use by another process
protected virtual bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None);
}
catch (IOException)
{
return true;
}
finally
{
if (stream != null)
stream.Close();
}
//file is not locked
return false;
}

Related

C#: System.UnauthorizedAccessException: Access to path is denied When File.Move or File.Delete [duplicate]

This question already has an answer here:
File.Delete the process cannot access the file because it is being used by another process
(1 answer)
Closed 2 years ago.
I need to create small console application to move files into separate folders. Everything works fine, I can copy file, until I try to File.Move or File.Delete file, I catch System.UnauthorizedAccessException. What I've tried
changing folder permission from code
switching from .Net Core to .Net Framework
Manually adding permission to folder by rightclicking->Security->Advance
tried to change Folder's Read-only attribute (it always reverts back to readonly, I can't solve this)
I don't know what else I can try and how to solve this problem. The code I wrote is below
var pngFiles = Directory.GetFiles(#"C:\Users\MSI_PC\Desktop\Test", "*.png",
SearchOption.AllDirectories);
foreach (var pngFile in pngFiles)
{
Console.WriteLine(pngFile);
var fileName = Path.GetFileName(pngFile);
var newFolder = Path.Combine(#"C:\Users\MSI_PC\Desktop\Test",
Path.GetFileNameWithoutExtension(fileName));
Directory.CreateDirectory(newFolder);
var newFileName = Path.Combine(#"C:\Users\MSI_PC\Desktop\Test",
Path.GetFileNameWithoutExtension(fileName), fileName);
File.Copy(pngFile, newFileName, true); //yes, I can use move and have 1 line of code instead of 2. But I need file to be copied, and this line of code works fine
File.Delete(pngFile); // System.UnauthorizedAccessException. File.Move throws the same exception
}
try this code
private void Copy()
{
var pngFiles = Directory.GetFiles(#"C:\Users\Administrator\Desktop", "*.png", SearchOption.AllDirectories);
foreach (var pngFile in pngFiles)
{
Console.WriteLine(pngFile);
var fileName = Path.GetFileName(pngFile);
var newFolder = Path.Combine(#"D:\NewPic\");
Directory.CreateDirectory(newFolder);
string DestPath = newFolder + "\\" + fileName;
byte[] buffer = new byte[2014 * 1024];
using (FileStream source = new FileStream(pngFile, FileMode.Open, FileAccess.Read, FileShare.Delete))
{
using (FileStream dest = new FileStream(DestPath, FileMode.CreateNew, FileAccess.Write, FileShare.Delete))
{
int currentBlockSize = 0;
while ((currentBlockSize = source.Read(buffer, 0, buffer.Length)) > 0)
{
dest.Write(buffer, 0, currentBlockSize);
}
dest.Close();
}
source.Close();
}
File.Delete(pngFile); // System.UnauthorizedAccessException. File.Move throws the same exception
}
}

Open file for Appending with is new indication

I need to append data to a file, but if the file does not exist I need to add a header before appending.
If I open the file with FileMode.Append, I cannot see a way to work out if the file is new or not.
If I open the file with
FileStream file;
boolean isNew;
try
{
file = File.Open(path, FileMode.CreateNew);
isNew = true;
}
catch (IOException ex)
{
file = File.Open(path, FileMode.Append);
isNew = false;
}
I run into the risk of another process deleting the file between the the 2 open calls and not detecting the creation of the new file.
What is the recommended way of opening for appending and detecing if create or append?
Does this do what you need?
try
{
var file = File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite);
if (file.Length == 0)
{
// do header stuff
}
// do the rest
}
catch (IOException ex)
{
// handle io ex.
}
Try something like this:
if (!File.Exists(path))
{
file = File.Open(path, FileMode.CreateNew);
isNew = true;
return;
}
// otherwise append to existing file
file = File.Open(path, FileMode.Append);
isNew = false;

I cant copy files using FileStream

I am trying to read/write files using FileStream. Code is working but After copied files all I get an empty file. String data inside the file is not copied.
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
if(saveFileDialog1.ShowDialog()==DialogResult.OK)
{
FileStream streamR = new FileStream(openFileDialog1.FileName, FileMode.Open);
byte[] buffer = new byte[streamR.Length];
streamR.Read(buffer, 0, buffer.Length);
FileStream streamW = new FileStream(saveFileDialog1.FileName,FileMode.Create);
int read_byte = 0;
while ((read_byte = streamR.Read(buffer, 0, buffer.Length)) > 0)
{
streamW.Write(buffer, 0, read_byte);
}
}
}
When using streams, you should use the 'using' command:
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
if(saveFileDialog1.ShowDialog()==DialogResult.OK)
{
using (FileStream streamR = new FileStream(openFileDialog1.FileName, FileMode.Open))
{
using (FileStream streamW = new FileStream(saveFileDialog1.FileName,FileMode.Create))
{
byte[] buffer = new byte[streamR.Length];
int read_byte = 0;
while ((read_byte = streamR.Read(buffer, 0, buffer.Length)) > 0)
{
streamW.Write(buffer, 0, read_byte);
}
}
}
}
}
It will automatically flush, close and dispose the streams for you.
What actually stops your code from working, is the flush() and close() command.
However, it's still recommended to use the 'using' command.
A second way is to wrap everything in a try finally block and dispose the stream in the finally block:
using statement FileStream and / or StreamReader - Visual Studio 2012 Warnings
Anyway, I would suggest reading some more information about streams before continuing.
On the other hand ... if it's just for copying files, it would be simpler to use the Fil.Copy method.
Edit: Also ... loading the original file completely into a byte-array can cause some extra problems when your file is quite large.
The buffer is there to read chunks from the original file and process them.
I just corrected your code to make it work ... but it's far from perfect.
I would do something along these lines:
if (openFileDialog1.ShowDialog() == DialogResult.OK
&& saveFileDialog1.ShowDialog() == DialogResult.OK){
try {
if (File.Exists(saveFileDialog1.FileName)) {
File.Delete(saveFileDialog1.FileName);
}
File.Copy(openFileDialog1.FileName, saveFileDialog1.FileName);
} catch (Exception e){
//handle or throw e
}
}

Extract zip entries to another Zip file

Can anyone tell me why the following code doesnt work? I am using the SharpZipLib API for the Zip streams, latest version DL'ed today from their site. Im attempting to use this logic to merge the contents of one zip file into another, without having to perform IO on the disk, as the intended zip files may contain reserved file names for windows. I have tried this with multiple different source and destination zip files (those that contain reserved names and those that dont). The code does not throw any exception, and if you inspect the buffer prior to each write operation, you can see that it contains real data, yet after the entire operation finishes the size of the target zip file has not changed, and you can explore it to confirm that no new files (the ones the code is supposed to add) have actually been added to the destination file. :(
public static void CopyToZip(string inArchive, string outArchive)
{
ZipOutputStream outStream = null;
ZipInputStream inStream = null;
try
{
outStream = new ZipOutputStream(File.OpenWrite(outArchive));
outStream.IsStreamOwner = false;
inStream = new ZipInputStream(File.OpenRead(inArchive));
ZipEntry currentEntry = inStream.GetNextEntry();
while (currentEntry != null)
{
byte[] buffer = new byte[1024];
ZipEntry newEntry = new ZipEntry(currentEntry.Name);
newEntry.Size = currentEntry.Size;
newEntry.DateTime = currentEntry.DateTime;
outStream.PutNextEntry(newEntry);
int size = 0;
while ((size = inStream.Read(buffer, 0, buffer.Length)) > 0)
{
outStream.Write(buffer, 0, size);
}
outStream.CloseEntry();
currentEntry = inStream.GetNextEntry();
}
outStream.IsStreamOwner = true;
}
catch (Exception e)
{
throw e;
}
finally
{
try { outStream.Close(); }
catch (Exception ignore) { }
try { inStream.Close(); }
catch (Exception ignore) { }
}
}
I ended up doing this using a different API. DotNet zip from http://dotnetzip.codeplex.com/. Here is the implementation:
public static void CopyToZip(string inArchive, string outArchive, string tempPath)
{
ZipFile inZip = null;
ZipFile outZip = null;
try
{
inZip = new ZipFile(inArchive);
outZip = new ZipFile(outArchive);
List<string> tempNames = new List<string>();
List<string> originalNames = new List<string>();
int I = 0;
foreach (ZipEntry entry in inZip)
{
if (!entry.IsDirectory)
{
string tempName = Path.Combine(tempPath, "tmp.tmp");
string oldName = entry.FileName;
byte[] buffer = new byte[4026];
Stream inStream = null;
FileStream stream = null;
try
{
inStream = entry.OpenReader();
stream = new FileStream(tempName, FileMode.Create, FileAccess.ReadWrite);
int size = 0;
while ((size = inStream.Read(buffer, 0, buffer.Length)) > 0)
{
stream.Write(buffer, 0, size);
}
inStream.Close();
stream.Flush();
stream.Close();
inStream = new FileStream(tempName, FileMode.Open, FileAccess.Read);
outZip.AddEntry(oldName, inStream);
outZip.Save();
}
catch (Exception exe)
{
throw exe;
}
finally
{
try { inStream.Close(); }
catch (Exception ignore) { }
try { stream.Close(); }
catch (Exception ignore) { }
}
}
}
}
catch (Exception e)
{
throw e;
}
}
One issue that I see is that you are opening the output zip file using File.OpenWrite(), which will replace the existing output file rather than merging new entries into it.
There is an example on the SharpDevelop Wiki that gives an example of updating a zip file using memory streams. It can be found at http://wiki.sharpdevelop.net/SharpZipLib_Updating.ashx#Updating_a_zip_file_in_memory_1
The following is some simpler code that will read from the input zip and write to the output zip, which potentially already exists. It does not require writing temporary data to the filesystem.
public static void CopyToZip(string inArchive, string outArchive)
{
using (inZip = new ZipFile(inArchive),
outZip = new ZipFile(outArchive))
{
Func<String,Func<String,Stream>> getInStreamReturner = (name) => {
return new Func<String,Stream>(a){ return inZip[a].OpenReader(); };
};
foreach (ZipEntry entry in inZip)
{
if (!entry.IsDirectory)
{
string zipEntryName = entry.FileName;
outZip.AddEntry(zipEntryName,
getInStreamReturner(zipEntryName),
(name, stream) => stream.Close() );
}
}
outZip.Save();
}
}
Notes:
This approach uses the ZipFile.AddEntry overload that accepts two delegates: an opener and a closer. These functions get called at the time of ZipFile.Save. The former delegate needs to open and return the stream that contains the data to be zipped. The latter delegate needs to just close the stream.
It is necessary to define the getInStreamReturner Func , in order to open the right stream at the time of ZipFile.Save. Bear in mind that the zipEntryName changes value each time through the loop. Also ZipEntry.OpenReader() opens a stream on the actual zip data, which reads-and-decompresses as it goes. You can have only one of those open, at any one time, per ZipFile. getInStreamReturner creates a new function each time through the loop, thereby creating a closure to retain the value of the zipEntryName for reference at the time of ZipFile.Save.
This approach will fail if there are name clashes between the inArchive and outArchive. To avoid that you'd need to check for that and somehow avoid it. Either contrive a new, unique name, or skip adding entries with duplicate names into the outarchive.
I haven't tested this.
While this approach does not write to the filesystem, it does decompress and recompress file data. There is an open request to provide a feature to DotNetZip to migrate entries without that decompress/recompress jump. I haven't implemented that yet.

BinaryWriter in loop causes "file is being used by another process" error even though it is closed and 'using'

Title sais it all really.
private bool addToBinary(byte[] msg, string filepath)
{
bool succ = false;
do
{
try
{
using (Stream fileStream = new FileStream(filepath, FileMode.Append, FileAccess.Write, FileShare.None))
{
using (BinaryWriter bw = new BinaryWriter(fileStream))
{
bw.Write(msg);
bw.Flush();
fileStream.Flush();
bw.Close();
}
}
succ = true;
}
catch (IOException ex) { Console.WriteLine("Write Exception (addToBinary) : " + ex.Message); }
catch (Exception ex) { Console.WriteLine("Some Exception occured (addToBinary) : " + ex.Message); return false; }
} while (!succ);
return true;
}
(bw.close also closes the underlying stream)
Using this in any loop causes an output such as;
A first chance exception of type 'System.IO.IOException' occurred in mscorlib.dll
Write Exception (addToBinary) : The process cannot access the file 'C:\test\test.png' because it is being used by another process.
The bigger the file gets, the more of these errors pop up. It does get through eventually but it significantly reduces file writing speed. It's the Stream fileStream = bit that causes the exception.
What did I do wrong?
Example usage;
do
{
serverStream = clientSocket.GetStream();
bytesRead = serverStream.Read(inStream, 0, buffSize); //How many bytes did we just read from the stream?
recstrbytes = new byte[bytesRead]; //Final byte array
Array.Copy(inStream, recstrbytes, bytesRead); //Copy from inStream to the final byte array
addToBinary(recstrbytes, #"C:\test\test.png"); //Append final byte array to binary
received += recstrbytes.Length; //Increment bytes received
}while (received < filesize);
You need to first check if you can access the file before using Stream to read the file.
You can have a look at this link :
Best way to handle errors when opening file
Have a look at the answers
Although I posted my answer
https://stackoverflow.com/a/9503939/448407 but you can look at the post marked as answer.
Only read the file contents if you can access the file and I think it will then work.
Some good advice style wise for those stacked using statements. When you start using more than one it is often neater to use the following style:
using (Stream fileStream = new FileStream(filepath, FileMode.Append, FileAccess.Write, FileShare.None))
using (BinaryWriter bw = new BinaryWriter(fileStream))
{
bw.Write(msg);
bw.Flush();
fileStream.Flush();
bw.Close();
}
I'm afraid I can't solve your question though, but I'm not sure how much of a good an idea it is to repeatedly try and write to the stream if it isn't successful the first time round.

Categories