I have a folder with a certain number of text files named 1.txt, 2.txt 3.txt etc.
My goal is that when one of them is deleted, to rename any of the files greater than the file deleted down one.
Ex. if 1.txt is deleted, 2 should be renamed to 1, and 3 renamed to 2, so on and so forth.
Here is my attempt so far:
private void deletequestionbtn_Click(object sender, EventArgs e)
{
string fileDel = testfolderdialog.SelectedPath.ToString() + #"\" + questionCountint.ToString() + ".txt";
DirectoryInfo d = new DirectoryInfo(testfolderdialog.SelectedPath.ToString() + #"\");
File.Delete(fileDel);
questionCountint++;
foreach (var file in d.GetFiles("*.txt"))
{
string fn = file.Name;
string use = fn.Replace(".txt", "");
int count = int.Parse(use);
if (count > questionCountint)
{
File.Move(fileDel, testfolderdialog.SelectedPath.ToString() + #"\" + questionCountint--.ToString() + ".txt");
}
}
}
The issue is occuring on the File.Move line, it's saying it cannot locate the file in fileDel, though I am incrementing questionCountint after deleting fileDel
Am I approaching this the wrong way? Is there a more effective way to write the foreach statement? I only want to rename the files greater than the file deleted.
Where am I going wrong?
The problem is that you are trying to rename fileDel, which is the file that you have deleted. You should rename file instead.
However, you will quickly run into the next problem. If you don't get the files in the exact order that you expect, you will try to rename a file to a name that already exists.
If the GetFiles method returns the files in the order "3.txt", "2.txt", you will first try to rename "3.txt" to "2.txt", but "2.txt" already exists.
You should first loop through the files and gather all files that should be renamed. Then you should sort the files on the number so that you can rename them in the correct order.
As the format of the file names is so simple to recreate from the number, you can just get the numbers in a list:
List<int> files = new List<int>();
foreach (var file in d.GetFiles("*.txt")) {
string fn = file.Name;
string use = fn.Replace(".txt", "");
int count = int.Parse(use);
if (count > questionCountint) {
files.Add(count);
}
}
string path = testfolderdialog.SelectedPath.ToString();
foreach (int count in files.Ordery(n => n)) {
File.Move(String.Concat(path, count.ToString() + ".txt"), String.Concat(path, (count - 1).ToString() + ".txt");
}
Related
I have some doubts about how to approach a problem of renaming a set of pdf files according to the information present in a txt file. For example, imagine that in the txt file the following data are separated by tabs:
"2222" "_" "Z1" "001" "E" "07"
"2222" "_" "C1" "002" "F" "08"
"2222" "_" "D1" "003" "F" "09"
The number of pdf files in a given folder always corresponds to the number of lines in the txt file.
How to change the names of * pdf files using this information in the txt file that is in the same folder where the pdfs are, withou the quotes?
You could use the following code as a starting point, and make it more complex if necessary. I have comments to help follow along. Remember to include "using System.IO;".
class Program
{
static void Main(string[] args)
{
string directory = #"E:\TempFiles\"; //Name of directory containing text files and PDFs
//Get text file with names for PDFs...
string filenames = File.ReadAllText(directory + "names.txt");
//Removed quotes, but can be done differently, and split by space, which may not work for all your cases, but gets going in the right direction...
string[] listFilenames = filenames.Replace("\"", "").Split('\t');
int i = 0; //Used to access list of filnames...
foreach (string file in Directory.GetFiles(directory))
{
//Skip text file...
if (!file.EndsWith(".txt"))
{
//Rename file...
File.Move(file, directory + listFilenames[i] + ".pdf");
i++;
}
}
}
}
I have developed a small tool that will be used to display data discrepancy in c#, what I do is explained point wise below,
fetch data from database and write list of file names in text file based on date criteria -output 1
take dir of path 1 and write into text file- output2
take dir of path2, path3 and path4 similarly and write into text files separately for each path- output 3/4/5
compare option: compare output1 and 2 and write down the difference in text file, this difference is then compared to output3 and again the difference is written in another file, and so on...
my issue is : my last path has more than 2.5 million records of files, whenever I try writing it in text file it hangs the application and it never provides output, I did try filtering it with date criteria but even for a single day where records could be around 30 thousands it hangs
I have searched many sites but did not get solution that I can understand or able to implement it. Below is my attempted code.
if (!txtpath3.Text.Equals(String.Empty) && System.IO.Directory.GetFiles(txtpath3.Text).Length > 0)
{
var directory = txtpath3.Text;
var from_dt = this.dtpickerstart.Value;
var end_dt = this.dtpickerend.Value;
DateTime from_date = from_dt;
DateTime to_date = end_dt;
DirectoryInfo di = new DirectoryInfo(directory);
FileSystemInfo[] files = di.GetFileSystemInfos();
var op = di.GetFiles()
.Where(file => file.LastWriteTime >= from_date && file.LastWriteTime <= to_date);
foreach (string file in System.IO.Directory.GetFiles(txtpath3.Text, "*.*"))
{
TextWriter tw = new StreamWriter(dirfile3, true);
tw.WriteLine("" + file + "");
tw.Close();
}
}
else
{
}
Your foreach-loop opens and closes the file for all lines. You should open and close the file outside of the loop.
using(var tw = new StreamWriter(dirfile3, true))
{
foreach (string file in System.IO.Directory.GetFiles(txtpath3.Text, "*.*"))
{
tw.WriteLine("" + file + "");
}
}
Even easier would be using the already existing functions to do this:
File.AppendAllLines(dirfile3, System.IO.Directory.GetFiles(txtpath3.Text, "*.*"));
As 2.5 million filesnames are a lot to keep in RAM at the same time, you might be better off with just enumerating them:
File.AppendAllLines(dirfile3, System.IO.Directory.EnumerateFiles(txtpath3.Text, "*.*"));
I think that the problem is in the foreach
foreach (string file in System.IO.Directory.GetFiles(txtpath3.Text, "*.*"))
{
TextWriter tw = new StreamWriter(dirfile3, true);
tw.WriteLine("" + file + "");
tw.Close();
}
For each and every one of the many, many files, you are opening a file, appending a line, and closing the file, only to open it again, write another line, etc, etc...
You should just prepare everything in a string first, and then just insert all the text in one go, something like:
StringBuilder sb = new StringBuilder();
foreach (string file in System.IO.Directory.GetFiles(txtpath3.Text, "*.*"))
{
sb.AppendLine(file);
}
File.WriteAllText(dirfile3, sb.ToString());
I am trying to move multiple files in a directory to an archive sub folder. I used a foreach loop to do the idea. Unfortunately, It can only move a file if there is only one file in the directory. But when I put multiple in the directory the Directory.move(); won't work. Can anyone help me?
static string antJsonSerializer(){
#region KDI SALES
string[] allfiles = Directory.GetFiles(#"C:\xml\"); // Put all file names in root directory into array.
string sourceDirectory = #"C:\xml\";
string destinationDirectory = #"C:\xml\Archive\";
// Check if directories are existing -- Working
bool xmlRoot = System.IO.Directory.Exists(sourceDirectory);
if (!xmlRoot) System.IO.Directory.CreateDirectory(sourceDirectory);
bool xmlArchive = System.IO.Directory.Exists(destinationDirectory);
if (!xmlArchive) System.IO.Directory.CreateDirectory(destinationDirectory);
AntHelpers drone = new AntHelpers();
foreach (string name in allfiles)
{
try
{
drone.xmltosql(#name.Trim());
//File.Move(#name, destinationDirectory + (DateTime.Now.Year).ToString() + (DateTime.Now.Month).ToString().PadLeft(2, '0') + (DateTime.Now.Day).ToString().PadLeft(2, '0') + (DateTime.Now.Hour).ToString().PadLeft(2, '0') + ".html"); //Not working
Directory.Move(#name, destinationDirectory + (DateTime.Now.Year).ToString() + (DateTime.Now.Month).ToString().PadLeft(2, '0') + (DateTime.Now.Day).ToString().PadLeft(2, '0') + (DateTime.Now.Hour).ToString().PadLeft(2, '0') + ".html");
//Directory.Move(sourceDirectory, destinationDirectory); //Not working
}
catch (Exception e)
{
//Console.WriteLine("Main Process Catch ERR: " + e.Message);
//ErrLogtoDB(string TRNTYPE, string extserial, string texttowrite, string logfilename)
AntHelpers.ErrLogtoDB("SALES", #name, "Ant JSON Serializer Failed: " + e.Message,
"LeafCutterLogFile_JSONSerializer_" + (DateTime.Now.Year).ToString() + (DateTime.Now.Month).ToString().PadLeft(2, '0') + (DateTime.Now.Day).ToString().PadLeft(2, '0') + (DateTime.Now.Hour).ToString().PadLeft(2, '0') + ".html");
}
//drone.ExtractSQLSendAntHill(); //For testing: OFF
#endregion
return " !!!! Work Complete !!!! ";
}
You are trying to save a file with year + month + day + hour.html as "NAME". If multiple files are there, then how can you save it with same file name? Instead you should add seconds and/or milliseconds, or use something else to distinguish the file and make it a unique name. Otherwise, take file name without the extension then add year, month, day, and hour. That is why you are not able to move multiple files at a time, because when try to move the second file an exception will be thrown say "unable to move an existing file."
Directory.Move takes a source and destination directory, not a file path. Try this:
Directory.Move(sourceDirectory, destinationDirectory);
Also, it can be run at the very end - after the foreach loop.
This is the loop i'm using today:
for (int i = 0; i < dateTime.Count; i++)
{
string result = dateTime[i].ToString("yyyyMMddHHmm");
link = "http://www.sat24.com/image2.ashx?region=" + selectedregion + "&time=" + result + "&ir=" +
infraredorvisual;
string filePath = Path.Combine(satimagesdir, "SatImage" + (i + last) + ".GIF");
try
{
client1.DownloadFile(link, filePath);
}
catch (Exception e)
{
DannyGeneral.Logger.Write(e.ToString());
}
}
This way now i'm not getting the last file and the variable last is not in use so it's all the time 0 so in the end it will allways create new 0 to 8 files and will overwrite existing files.
What i need to do is two things:
To find the last file by name by it's part of the number like i explained above.
The next new 9 files should be by the numbers from the last file.
So if i know for example that the last existing file is SatImage845.gif then the next file i know should be SatImage846.gif and then i need to make that in the loop it will create SatImage846.gif,SatImage846.gif....untill SatImage854.gif
This should be the rule.
Each time the loop should create the next 9 files according to the last file name.
Try with this before your for loop, so last is the highest number of the files in that same directory.
var regex = new Regex("SatImage([0-9]+).gif", RegexOptions.IgnoreCase);
var last =
Directory.GetFiles(satimagesdir)
.Select(Path.GetFileName)
.Select(x => regex.Match(x))
.Where(x => x.Success)
.Select(x => int.Parse(x.Groups[1].Value))
.OrderByDescending(x => x)
.First();
I have a directory in which 'wav' files are stored. These files's names are sequential in order ie 1.wav, 2.wav, 3.wav.... etc.
I have to find out the missing wav file, like if 3.wav is missing then I have to find out that and the name '3' should given to a variable.
How can I do this?
You could use a simple loop and assign the variable to the loop counter and use File.Exists:
List<yourType> missingFiles = new List<yourType>();
string path;
for (var i = 0; i<length; i++) {
path = "path\" + i + ".wav";
if (!File.Exists(path) {
missingFiles.Add(path);
}
}
http://msdn.microsoft.com/en-us/library/system.io.file.exists.aspx