I have a text file with a specific order of lines and content. I need to write a code that gets the values in rows numbers 3, 4 and 5 then it pushes those values to the file name and save the file by giving the new name and keep a the original file without any changes.
Example:
File name: Default.txt
- ABC
- DEF
- ValueNo1
- ValueNo2
- ValueNo3
- fdf
- FDFDFD
- The new file name will be Default-ValueNo1ValueNo1-ValueNo2ValueNo2-ValueNo3ValueNo3
Sunny SharmaPosted Aug 20, 2013, 12:30 AM
Sorry for responding a little late.
Just declare those the variables as static outside your procedure/method and assign them from within the procedure/method, like:
---------------------------------------------------------
static string[] Files;
static string oldPath;
static string newPath; // assign them from inside the methods:
Button1:
oldPath = GetOldFilePath ();
Files = SelectFiles(oldPath);
Button 2:
newPath = GetNewFilePath();
Button 3:
Myfunction(oldPath,NewPath,Files);
-----------------------------------------------------------
Hope it helps :)
Rano AHPosted Aug 20, 2013, 8:37 AM
I managed to solve the problem :-)
I just set
Files = openFileDialog1.FileNames; // instead of openFileDialog1.SafeFileName
Rano AHPosted Aug 20, 2013, 8:22 AM
Yes, it returns the selected files, but the application now doesn't continue processing the rest of the code. it keeps getting "File doesn't exist" I tried to debug found that it stops here:
using (var reader = new StreamReader(file))
and then it jumps to Catch (Exception ex) block.. Why?
is it because I'm passing (file). What is wrong in my code?
string[] files = Files;();
if (Files.Length > 0)
{
foreach (string file in files)
{
try
{
var list = new List
using (var reader = new StreamReader(file))
{
for (int i = 0; i < 26; i++)
{
list.Add(reader.ReadLine());
}
}
Sunny SharmaPosted Aug 20, 2013, 5:57 AM
in the mentioned code below, I see it's doing good on it's own:
-------------------------------------------------------------------------
private string[] SelectFiles(string oldPath)
{
string file = openFileDialog1.FileName;
openFileDialog1.InitialDirectory = oldPath;
openFileDialog1.Filter = "Txt files*.txt";
openFileDialog1.Multiselect = true;
openFileDialog1.RestoreDirectory = true;
System.Windows.Forms.DialogResult dr = openFileDialog1.ShowDialog();
if (dr == DialogResult.OK)
{
foreach (string fileName in openFileDialog1.SafeFileNames)
{
textBox1.Text += fileName + Environment.NewLine;
}
}
Files = Directory.GetFiles(oldPath,"*.txt"); // it gets all files from the directory of type Txt.
return Files;
}
-------------------------------------------------------------------------------
Inside this method, it only iterates through an array of selected filenames and does nothing except that. It returns no array of selected files. The last two lines are responsible to return all the text files inside a selected folder.
You can simply use:
return openFileDialog1.SafeFileNames;
in order to return the list of selected files.
Hope you got the point.
Rano AHPosted Aug 20, 2013, 5:29 AM
I'm writing to you again since it's related issue :-)
The below method returns string array which contains all the text files from type "txt", however, what if I need to return only the selected files (not all of them) for example if I selected 10 files out of 100 txt files, then it should return only the 10 selected files. I'm trying to write a code to assign all the selected files to an array, but still no success :-(
private string[] SelectFiles(string oldPath)
{
string file = openFileDialog1.FileName;
openFileDialog1.InitialDirectory = oldPath;
openFileDialog1.Filter = "Txt files*.txt";
openFileDialog1.Multiselect = true;
openFileDialog1.RestoreDirectory = true;
System.Windows.Forms.DialogResult dr = openFileDialog1.ShowDialog();
if (dr == DialogResult.OK)
{
foreach (string fileName in openFileDialog1.SafeFileNames)
{
textBox1.Text += fileName + Environment.NewLine;
}
}
Files = Directory.GetFiles(oldPath,"*.txt"); // it gets all files from the directory of type Txt.
return Files;
}
Sunny SharmaPosted Aug 20, 2013, 4:38 AM
You're always welcome to write me though I would suggest to post as a new question if it's a different subject for the sake of segregation.
Happy to help :)
Rano AHPosted Aug 20, 2013, 3:31 AM
Oh God. Life is simple.. :-)
Can I still write to you if I face some problems. (since this marked as correct answer) Or should I post my question as new question?
Rano AHPosted Aug 19, 2013, 8:24 AM
Button1:
string oldPath = GetOldFilePath ();
string [] Files = SelectFiles(oldPath);
Button 2:
GetNewFilePath();
Button 3:
// it should perform the rest of the code for the text files
string oldPath = GetOldFilePath();
string NewPath = GetNewFilePath();
string[]Files = SelectFiles(oldPath);
Myfunction(oldPath,NewPath,Files);
I don't need to ask the user again to select (input, output directories in addition to the files). But how to do this, I need button 3 to execute only myFunction since Button1 and button 2 each has its code.
Rano AHPosted Aug 18, 2013, 9:24 AM
I've tried similar code before, but actually this is not what I really
want.
Browsing for files to open from a specific directory needs to be done/chosen
separately by clicking on one button (I've done that already)
Browsing for folder to save the new files on needs to be done/chosen separately
by clicking on another button (I've done that also)
The rest of the code needs to be executed once I click on (start) button. But I cannot pass the directories to set the current path and the new path of the files.
Another thing, even by calling getOldPath() and getNewPath in button1 and button2 this will
not allow also the user select the files. Is there a way to select the files and read
the directory of the files on one command button, instead of asking the user to choose twice?
Sunny SharmaPosted Aug 17, 2013, 3:36 PM
Here I've attached a sample code on how you do it, please go through.
Thanks.
Rano AHPosted Aug 17, 2013, 7:27 AM
I need to modify the code again! I will ask the user to select the directory of files instead of setting it "fixed" and select also the folder to save/copy the files to:
See my codes below:
Open file Code:
string file = openFileDialog1.FileName;
openFileDialog1.Filter = "TXT|".txt";
openFileDialog1.Multiselect = true;
openFileDialog1.RestoreDirectory= true;
System.Windows.Forms.DialogResult dr = openFileDialog1.ShowDialog();
if (dr == DialogResult.OK)
{
for each (string filename in openFileDialog1.SafeFileNames)
{
OpenFile.Txt += filename+ Environment.NewLine;
}
}and the output folder code is:
{
folderBrowserDialog1.Description = "Select a folder to save file(s): ";
folderBrowserDialog1.ShowNewFolderButton = true;
folderBrowserDialog1.SelectedPath = OpenFile.Text;
folderBrowserDialog1.RootFolder = System.Environment.SpecialFolder.MyComputer;
DialogResult result = folderBrowserDialog1.ShowDialog();
if (result == DialogResult.OK)
OutPut.Text = folderBrowserDialog1.SelectedPath;
}
But still, I cannot use this in my code, so that I can use both directories that the user selected to set the oldPath and the newPath.
Sunny SharmaPosted Aug 14, 2013, 3:16 PM
Please mark the post as answer.
Thanks.
Rano AHPosted Aug 14, 2013, 12:45 PM
Sunny SharmaPosted Aug 13, 2013, 1:44 AM
Your code looks all good and is optimal. The solution to your question in last is very simple, just copy the old file with the new name in new location:
Here is the modified code:
---------------------------------
foreach (string file in files)
{
try
{
var list = new List<string>();
using (var reader = new StreamReader(file))
{
for (int i = 0; I < 26; i++)
{
list.Add(reader.ReadLine());
}
}
string newFileName = string.Concat(newPath,
Path.GetFileNameWithoutExtension(file), "-", list[23], "-", list[24],"-",
list[25], ".txt");
string newFile = string.Concat(newPath,
"\\", regex.Replace(newFileName, string.Empty), ".txt");
File.Copy(file, newFile);
-------------------------------------------------------------
The single line at bottom only needs to be modified as mentioned above.
Hope you find it useful.
Thanks.
Rano AHPosted Aug 12, 2013, 1:39 PM
I did a small modification on the previous code to read only 26 lines instead of hundreds. Plz see my code below:
foreach (string file in files)
{
try
{
var list = new List<string>();
using (var reader = new StreamReader(file))
{
for (int i = 0; I < 26; i++)
{
list.Add(reader.ReadLine());
}
}
string newFileName = string.Concat(newPath,
Path.GetFileNameWithoutExtension(file), "-", list[23], "-", list[24], "-",
list[25], ".txt");
string newFile = string.Concat(newPath,
"\\", regex.Replace(newFileName, string.Empty), ".txt");
File.WriteAllLines(newFile, list);
Rano AHPosted Aug 11, 2013, 1:29 PM
Sunny SharmaPosted Aug 11, 2013, 2:47 AM
I've modified the code in my previous post it required to remove special characters. Regex is used to achieve this purpose. I'm attaching the code file here as the code in reply may look a bit ugly and hard to find the modified part.
Rano AHPosted Aug 11, 2013, 1:24 AM
Rano AHPosted Aug 11, 2013, 1:12 AM
Sunny SharmaPosted Aug 10, 2013, 11:46 PM
Sorry for not getting your last point correctly in first go. Try this snippet, will work, tested.
------------------------------------------------------------------------------
public void RenameAndCreateFile()
{
string oldPath = @"D:\"; //set current path here
string newPath = @"D:\test"; //set new path here
if (!Directory.Exists(oldPath))
{
Console.WriteLine("Given directory doesn't exist.");
return;
}
string[] files = Directory.GetFiles(oldPath,"*.txt");
if (files.Length > 0)
{
if (!Directory.Exists(newPath))
{
Directory.CreateDirectory(newPath);
}
Regex r = new Regex("(?:[^a-z0-9 ]|(?<=['\"])s)", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
foreach (string file in files)
{
try
{
string[] lines = File.ReadAllLines(file);
string newFileName = string.Concat(Path.GetFileNameWithoutExtension(file), "-",
lines[3], "-",lines[4], "-", lines[5]);
string newFile = string.Concat(newPath, "\\", r.Replace(newFileName, string.Empty),".txt");
File.WriteAllLines(newFile, lines);
}
catch (IndexOutOfRangeException ex)
{
Console.WriteLine("Files seems to have no content on line # 3,4 & 5. Skipping this file...");
}
catch (Exception ex)
{
Console.WriteLine("Error occured while processing: " + file + ". "+ex.Message+"\n Skipping this file...");
}
}
}
else
{
Console.WriteLine("No files found in Given directory.");
}
}
----------------------------------------------------------------------------------------
Hope it helps :)
Rano AHPosted Aug 10, 2013, 2:49 PM
I believe the code that you implement is working, but unfortunately it throws unhandled exception. It says "FileNotFoundException was unhandled" :-(
A question: the code shouldn't move the newFile to the newPath? I tried this also, but didn't work
Sunny SharmaPosted Aug 10, 2013, 3:39 AM
try this: (following assumes that the file has no blank lines, each file has values at line 3,4 & 5 and no line numbers are present in files)
-------------------------------
public void RenameAndMoveFiles()
{
string oldPath=@"D:\";
string newPath = @"D:\\test";
string[] files = Directory.GetFiles(oldPath);
foreach (string file in files)
{
string[] lines = File.ReadAllLines(file);
string newFile = string.Concat(newPath, "\\", Path.GetFileName(file), "-", lines[3], "-",
lines[4], "-", lines[5], ".txt");
File.Move(file, newFile);
}
}
--------------------------------
Hope it helps :)
Cheers!
Rano AHPosted Aug 10, 2013, 3:15 AM
Hello again Vulpes.
Based on your assumption, the code works perfectly. However, I think I didn't
give the right clarification for the problem.
My text file contains several lines and each line expresses the relative
value. Suppose I have (n) numbers of text files in my folder and I need to
dynamically let me code to read those files at one go. For each file it
will go to line 3, line 4 and line five to read the correspondence values to
each line and push them in the file name in order to save the file.
For example: one of the original file called: "File1.txt", // where file1.txt is one of (n) files.txt.
and my code finds the values :VAL1, VAL2, VAL3 in the lines 3,4 and 5 from this
file. In this case the new file name would be: File1-VAL1-VAL2-VAL3.txt and it
will be saved in the same or other directory in my computer. This should
be done to all of the files in this folder at one go without changing the
entire contents of the original/old and the new files.
So basically my code will work like copying this file to another or same location and give a new file name by pushing/adding the three values to the old file name by separating the values by any separator.
I managed to write the following methods, but still incomplete:
//Manual process:
public void RenameFileAndCopy()
{
string oldPath = @"C:\TXT_files\File1.txt"; //suppose it's one file out
of 70 files.
string newpath = @"C:\TXT_UpdatedFiles\";
string newFileName = "new file name"; // I gave the new file name (but
not based on the values on the lines.
FileInfo f1 = new FileInfo(oldPath);
if(f1.Exists)
{
if(!Directory.Exists(newpath))
{
Directory.CreateDirectory(newpath);
}
f1.CopyTo(string.Format("{0}{1}{2}", newpath, newFileName, f1.Extension));
MessageBox.Show("Creation completed");
}
}
public void RenameFile()
{
DirectoryInfo DI = new DirectoryInfo("C:\\TXT_Files");
FileInfo [] FI = DI.GetFiles("*.txt");
foreach (FileInfo file in FI)
{
// Do the renaming here
File.Move(file.FullName,
Path.Combine(file.DirectoryName, "1" + file.Name));
}
public void ReadNumberOfLines()
{
//Load my text file(s)
TextReader tr = new StreamReader("File1.txt");
//No of lines to be loaded
int NumberOfLines = 70; // it will read from the start to end of the file.
//Array for each line:
string[] LinesList = new string[NumberOfLines];
//Read the number of lines and add them into array
for (int i=1; i< NumberOfLines;i++)
{
LinesList[i] = tr.ReadLine();
}
//This will write the 3rd, 4th and 5th lines into the
old file name: Example: Default1-VA1-VA2-Val3.txt
? ??????????????
VulpesPosted Aug 9, 2013, 5:56 PM
1. There are no blank lines in the actual file.
2. The line numbers actually appear in the file.
3. The output file name is in the 8th line.