I am trying to create 2 XML files in the same folder.
For some reason it does create the first one, but does not create the second one.
Could it be that the first one is still being created when an attempt to create the second file is made, and therefore the latter fails?
I don't get any errors with the code:
if (File.Exists(FileNameTextBox.Text + ".AA.xml"))
{
MessageBox.Show("Already exists. renaming to *.old" + Environment.NewLine +
"if there is already an *.old file, this will be deleted.");
if (File.Exists(FileNameTextBox.Text + ".AA.xml.old"))
{
File.Delete(FileNameTextBox.Text + ".AA.xml.old");
}
File.Move(FileNameTextBox.Text + ".AA.xml", FileNameTextBox.Text + ".AA.xml.old");
}
if (!File.Exists(FileNameTextBox.Text + ".AA.xml"))
{
XmlTextWriter textWritter = new XmlTextWriter(FileNameTextBox.Text + ".AA.xml", null);
textWritter.WriteStartDocument();
textWritter.WriteStartElement("Data");
textWritter.WriteEndElement();
textWritter.Close();
}
if (File.Exists("BB.xml"))
{
if (File.Exists("BB.xml.old"))
{
File.Delete("BB.xml.old");
}
File.Move("BB.xml", "BB.xml.old");
}
if (!File.Exists("BB.xml"))
{
XmlTextWriter textWritterPC3 = new XmlTextWriter("BB.xml", null);
textWritterPC3.WriteStartDocument();
textWritterPC3.WriteStartElement("Data");
textWritterPC3.WriteEndElement();
textWritterPC3.Close();
}
Whats in FileNameTextBox.Text? Does it specify a directory path?
Your second file is created without saying which directory. So it will be created in the current directory - which is not necessarily the directory specified by FileNameTextBox.Text
You are not specifying an absolute path for your file names, so you are using whatever the current directory happens to be, which is not reliable. Also you may need to call DirectoryInfo.Refresh() or FileInfo.Refresh() to make sure you are seeing the latest directory information (whether the file exists or not).
The comment is only making the last if case execute the first row.. The last if should look like this. I don't know if it's only in your example.
Your example
if (!File.Exists("BB.xml")) // {
XmlTextWriter textWritterPC3 = new XmlTextWriter("BB.xml", null);
should be
if (!File.Exists("BB.xml")) //
{
XmlTextWriter textWritterPC3 = new XmlTextWriter("BB.xml", null);
textWritterPC3.WriteStartDocument();
textWritterPC3.WriteStartElement("Data");
textWritterPC3.WriteEndElement();
textWritterPC3.Close();
}
Related
Just a quick question if you can help me, please.
In C#, I am creating a directory, if it does not exist. In the next command, I am checking if the directory exists, I will copy some files.
The Problem is, to creating a new directory or Deleting it, takes time and slower than next code execution time.
The software gives an error of "The folder does not exist ".
I used Thread.Sleep(5000); to wait 5 seconds before copying the content to the directory.
It seems to be working but I feel like that this is not how it's supposed to be done. Does anyone know better coding?
string logDirectoryPath = Directory.GetCurrentDirectory() + "\\LogFiles";
if (!Directory.Exists(logDirectoryPath))
{
Directory.CreateDirectory(Directory.GetCurrentDirectory() + "\\LogFiles");
Thread.Sleep(5000);
}
if (Directory.Exists(Directory.GetCurrentDirectory() + "\\LogFiles"))
{
var s = logDirectoryPath + "\\Log_" + DateTime.Now.ToString("dd_MM_yyyy") + ".txt";
using (StreamWriter w = File.AppendText(s))
{
w.WriteLine("--");
w.Write("\r\nLog Entry : ");
w.WriteLine($"{DateTime.Now.ToLongTimeString()} {DateTime.Now.ToLongDateString()}");
}
}
//EDIT
JUST thought maybe I should use a loop?
While(!Directory.Exists(logDirectoryPath))
{
Directory.CreateDirectory(Directory.GetCurrentDirectory() + "\\LogFiles");
}
Use DirectoryInfo
DirectoryInfo di = new DirectoryInfo(#{PATHSTRING});
and use di.Exists to check it exists / di.Create() to create folder
and I'd like to recommend to use logDirectoryPath which you defined already.
like this
DirectoryInfo di = new DirectoryInfo(logDirectoryPath);
if ( !di.Exists ) {
di.Create();
}
I am attempting to change the icon of a folder. The code below does all what I found online says to do but the icon never changes. Am I maybe not "Applying" the change?
string createdFile = Path.Combine(#"C:\Users\np\Desktop\PUTEST", "desktop.ini");
if (File.Exists(createdFile))
{
var di = new DirectoryInfo(createdFile);
di.Attributes &= ~FileAttributes.ReadOnly;
File.Delete(createdFile);
File.Create(createdFile).Dispose();
}
else
{
File.Create(createdFile).Dispose();
}
//string iconPath = #"%SystemRoot%\system32\SHELL32.dll";
string iconPath = Environment.ExpandEnvironmentVariables(#"%SystemRoot%\system32\SHELL32.dll");
string iconIndex = "-183";
using (TextWriter tw = new StreamWriter(createdFile))
{
tw.WriteLine("[.ShellClassInfo]");
tw.WriteLine("IconResource=" + iconPath + "," + iconIndex);
//tw.WriteLine("IconFile=" + iconPath);
//tw.WriteLine("IconIndex=" + iconIndex);
}
File.SetAttributes(createdFile, System.IO.FileAttributes.ReadOnly);
File.SetAttributes(createdFile, System.IO.FileAttributes.System);
File.SetAttributes(createdFile, System.IO.FileAttributes.Hidden);
When crafting a file like this it's always good to do so using Explorer or Notepad first, then write/adjust your code to match whatever was produced. Otherwise, it's harder to figure out if the problem is with your file or your code.
I believe the minimum requirements to make this work is Desktop.ini must be marked System and the parent directory must be marked ReadOnly (System may work there as well, but I know ReadOnly definitely does). So, your code is working with the right attributes, but there are still a few problems.
Your if ... else ... block is saying "If a file exists at this path, create a directory at that path, then delete the file at that path, then create a file at that path." Of course, the directory should not and cannot have the same path as the file. I assume you are deleting and recreating the file to clear the contents when it already exists, however File.Create() overwrites (truncates) existing files, making the calls to both File.Delete() and File.Exists() unnecessary.
More importantly is this line...
di.Attributes &= ~FileAttributes.ReadOnly;
...with which there are two problems. First, you are ANDing the directory's attributes with the negation of ReadOnly, which has the effect of removing ReadOnly and keeping the other attributes the same. You want to ensure ReadOnly is set on the directory, so you want to do the opposite of the code you used: OR the directory's attributes with ReadOnly (not negated)...
di.Attributes |= FileAttributes.ReadOnly;
Also, you need that attribute set regardless of whether you created the directory or not, so that line should be moved outside of the if ... else ....
Another issue is the successive calls to File.SetAttributes(). After those three calls the file's attributes will be only Hidden, since that was the value of the last call. Instead, you need to combine (bitwise OR) those attributes in a single call.
A couple of other minor tweaks...
As you know since you are calling Dispose() on it, File.Create() returns a FileStream to that file. Instead of throwing it away, you could use it to create your StreamWriter, which will have to create one, anyways, under the covers. Better yet, call File.CreateText() instead and it will create the StreamWriter for you.
Environment variables are supported in Desktop.ini files, so you don't have to expand them yourself. This would make the file portable between systems if, say, you copied it from one system to another, or the directory is on a network share accessed by multiple systems with different %SystemRoot% values.
Incorporating all of the above changes your code becomes...
// Create a new directory, or get the existing one if it exists
DirectoryInfo directory = Directory.CreateDirectory(#"C:\Users\np\Desktop\PUTEST");
directory.Attributes |= FileAttributes.ReadOnly;
string filePath = Path.Combine(directory.FullName, "desktop.ini");
string iconPath = #"%SystemRoot%\system32\SHELL32.dll";
string iconIndex = "-183";
using (TextWriter tw = File.CreateText(filePath))
{
tw.WriteLine("[.ShellClassInfo]");
tw.WriteLine("IconResource=" + iconPath + "," + iconIndex);
//tw.WriteLine("IconFile=" + iconPath);
//tw.WriteLine("IconIndex=" + iconIndex);
}
File.SetAttributes(filePath, FileAttributes.ReadOnly | FileAttributes.System | FileAttributes.Hidden);
One catch is that the above code throws an exception if you run it twice in succession. This is because the File.Create*() methods fail if the input file is Hidden or ReadOnly. We could use new FileStream() as an alternative, but that still throws an exception if the file is ReadOnly. Instead, we'll just have to remove those attributes from any existing input file before opening it...
// Create a new directory, or get the existing one if it exists
DirectoryInfo directory = Directory.CreateDirectory(#"C:\Users\np\Desktop\PUTEST");
directory.Attributes |= FileAttributes.ReadOnly;
string filePath = Path.Combine(directory.FullName, "desktop.ini");
FileInfo file = new FileInfo(filePath);
try
{
// Remove the Hidden and ReadOnly attributes so file.Create*() will succeed
file.Attributes = FileAttributes.Normal;
}
catch (FileNotFoundException)
{
// The file does not yet exist; no extra handling needed
}
string iconPath = #"%SystemRoot%\system32\SHELL32.dll";
string iconIndex = "-183";
using (TextWriter tw = file.CreateText())
{
tw.WriteLine("[.ShellClassInfo]");
tw.WriteLine("IconResource=" + iconPath + "," + iconIndex);
//tw.WriteLine("IconFile=" + iconPath);
//tw.WriteLine("IconIndex=" + iconIndex);
}
file.Attributes = FileAttributes.ReadOnly | FileAttributes.System | FileAttributes.Hidden;
I changed from using File to FileInfo since that makes this a little easier.
I am moving files from source folder to destination folder. Before moving files, I am checking that directory exists or not which is working fine. The issue is with my second check where I want to make sure that folder is not empty before moving files but it is not giving me correct result.
public void MoveFilesFromTempToSourceTbl()
{
//Moving all files from temp folder to orig folder.
string sourceFolder = (twitterDO.Path + "\\" + msgDate.Year.ToString() + "\\" + msgDate.Month.ToString() + "\\" + msgDate.Day.ToString() + "_Temp").Replace("\\", #"\");
string destinationFolder = (twitterDO.Path + "\\" + msgDate.Year.ToString() + "\\" + msgDate.Month.ToString() + "\\" + msgDate.Day.ToString()).Replace("\\", #"\");
string pattern = "*.txt";
if (Directory.Exists(sourceFolder))
{
if (File.Exists(pattern))
{
foreach (var file in new DirectoryInfo(sourceFolder).GetFiles(pattern))
{
file.MoveTo(Path.Combine(destinationFolder, file.Name));
}
}
if (Directory.GetFiles(sourceFolder).Length == 0) //Before deleting make sure that Temp folder is empty.
Directory.Delete(sourceFolder, true); // Delete Temp folder after moving all the contents.
}
}
I know I am making some small mistake but not sure what it is. Following is the screenshot of the result which I got in immediate window.
http://imgur.com/FZvo9cj
There's a bit of redundancy in your current code. Starting with the if-checks, here's how I would approach this:
var sourceDirectory = new DirectoryInfo(sourceFolder); // remember this, it is reused
if (sourceDirectory.Exists)
{
// Look for the files in the directory, if none found, will be empty array
foreach (var file in sourceDirectory.GetFiles(pattern))
{
file.MoveTo(Path.Combine(destinationFolder, file.Name));
}
// Re-check the directory for any remaining files
if (sourceDirectory.GetFiles(pattern).Length == 0) //Before deleting make sure that Temp folder is empty.
sourceDirectory.Delete(); // Delete Temp folder after moving all the contents.
}
As a small performance improvement, you could replace sourceDirectory.GetFiles() with sourceDirectory.EnumerateFiles() in the for-loop. This will allow you to start moving them as the method finds them, not after they have all been found.
You are passing "*.txt" into the File.Exists() call when you need to be passing a path.
You can read the Documentation here
Alternatively you could use something like this:
Directory.GetFiles(destinationFolder).Contains(filename)
I agree with David here but also I think the flow of you logic should be adjusted a bit. The File.Exixts(filename); should occur inside the foreach.
That will allow you to iterate each file and if it exists do something.
Try adding the following to check if any files exist in the location:
bool exist = Directory.EnumerateFiles(sourceFolder, "*.txt").Any();
string profile = "\\" + txtProfileLoad.Text + ".txt";
profile = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + profile;
The variable profile is receiving the correct file path, but when I run it the File.Exists comes up false every time.
if (System.IO.File.Exists(profile) == true)
{
System.IO.StreamReader profileReader;
profileReader = new System.IO.StreamReader(profile);
do
{
profileLevel = profileLevel + profileReader.ReadLine() + "\r\n";
} while (profileReader.Peek() != -1);
loadName(profileLevel);
wordBeingUsed.finalWord = loadedName;
Close();
}
else
{
MessageBox.Show("Invalid file name. Please try again.");
}
There aren't any permissions stopping it from seeing the file.
Any help with this would be appreciated. It's been driving me crazy.
Is this a pre-existing file that you are trying to read? Or is this a new file that you are hoping to create? What is the value inside txtProfileLoad.Text, issue most likely is within this property.
Run a sanity check:
var profile = "mytestfile.txt";
var myFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), profile);
File.WriteAllText(myFile, "Testing file write");
if (File.Exists(myFile))
{
// Access works.
}
else
{
//Didn't work
}
If above code works, then it is most likely that the name you create from txtProfileLoad.Text is different from actual file on the drive. On the other hand, if this is a file that doesn't exist yet; then of course it would return false when you check Exists.
You can use a string variable and pass the file name to it:
string tempFile = txtProfileLoad.Text;
string profile = #"C:\temp\tempfile.txt";
Also check out if you could use the file open method instead of File.Exist.
As per MSDN:
true if the caller has the required permissions and path contains the name of an existing file; otherwise, false. This method also
returns false if path is Nothing, an invalid path, or a zero-length
string. If the caller does not have sufficient permissions to read the
specified file, no exception is thrown and the method returns false
regardless of the existence of path.
Have you tried running as an administrator? Try do "right click" on the Visual Studio icon and select "Run as Administrator", and see if you still encounter the same behaviour.
What I am trying to do is to read in a file to a richTextBox automatically with the OnSelectedIndexChange method. There arent any errors, it just flat out doesnt work. Heres the code that I am working with
public void comboBox1_OnSelectedIndexChanged(object sender, EventArgs e)
{
string selectedPath = comboBox1.SelectedItem.ToString();
if (File.Exists(#"C:\\Mavro\\MavBridge\\" + selectedPath + "\\ " + "Comment" + ".txt"))
{
try
{
Thread.Sleep(0500);
System.IO.StreamReader textFile = new System.IO.StreamReader(#"C:\\Mavro\\MavBridge\\" + selectedPath + "\\ " + "Comment" + ".txt");
richTextBox1.Text = textFile.ReadToEnd();
textFile.Close();
}
catch
{
MessageBox.Show("Error: File cannot be opened!", "Error");
}
}
else
{
MessageBox.Show("No comment was found in this folder", "Alert");
}
}
Just for fun, lets have you try something. First, replace the following line:
if (File.Exists(#"C:\\Mavro\\MavBridge\\" + selectedPath + "\\ " + "Comment" + ".txt"))
with this:
if(File.Exists(string.Format("C:\\Mavro\\MavBridge\\{0}\\Comment.txt", selectedPath)))
It looks like you had an extra space ("\\ " + "Comment"), so I'm sure that's why it never hits this block of code. Also, anytime you have an object that needs to be closed/disposed, more often than not it implements IDisposable, meaning you should encapsulate the object within a using block:
Thread.Sleep(0500);
try
{
using(System.IO.StreamReader textFile = new System.IO.StreamReader(string.Format("C:\\Mavro\\MavBridge\\{0}\\Comment.txt", selectedPath)))
{
richTextBox1.Text = textFile.ReadToEnd();
}
}
catch
{
MessageBox.Show("Error: File cannot be opened!", "Error");
}
However, this can be simplified even further by bypassing the StreamReader entirely and using System.IO.File.ReadAllText instead:
richTextBox1.Text = System.IO.File.ReadAllText(string.Format("C:\\Mavro\\MavBridge\\{0}\\Comment.txt", selectedPath));
Well, one problem comes from the fact that you have:
#"C:\\Mavro\\MavBridge\\" + selectedPath + "\\ " + "Comment" + ".txt"
Since you are using a verbatim string (the # at the beginning), you do not need to put double slashes.
For the rest, make sure your file exists.
Later edit: also I am not sure if you copy/pasted in a rush or something like that, but did you actually put the catch block inside the try ?
1) What is the error you see?
2) Are you positive the file exists?
3) Are you positive the path created by your code is the path you are expecting?
4) Why are you sleeping the thread?
5) Why not just use File.ReadAllText?
6) File.Exists will return false if the code is running with permissions that do not have access to a file, even if the file does exist. Does the user your code is running as, have permissions?
true if the caller has the required permissions and path contains the
name of an existing file; otherwise, false. This method also returns
false if path is null, an invalid path, or a zero-length string. If
the caller does not have sufficient permissions to read the specified
file, no exception is thrown and the method returns false regardless
of the existence of path.
and
The Exists method returns false if any error occurs while trying to
determine if the specified file exists. This can occur in situations
that raise exceptions such as passing a file name with invalid
characters or too many characters, a failing or missing disk, or if
the caller does not have permission to read the file.
Get rid of # before each string. Your directory as it currently is uses actual double slashes instead of C:\Mavro\MavBridge. Use single slashes with \ or go with # at the beginning, but don't use both.
Also, I would strongly suggest using Path.Combine instead of concatenating pieces together like that.