Open txt file and replace text in the first two lines (C#) - c#

I am writing this program that allows me to generate txt files that with an incremental number, however, i want each file serial number to be writting inside the txt file itself.
For example:
I generated 3 files, Mytext-000001.txt, Mytext-000002.txt, Mytext-000003.txt, and each file first line contains "Hello 000000" and the second line contains "My number is 000000", now i want to change each txt file to contain "Hello " + the incremental number that it is named with.
So the output of each file will be:
Mytext-000001.txt,
Hello 000001
My number is 000001
Mytext-000002.txt,
Hello 000002
My number is 000002
Mytext-000003.txt,
Hello 000002
My number is 000003
My Code
string path = System.IO.Path.GetDirectoryName(Application.ExecutablePath) + #"\path.txt";
string pth_input = null;
string pth_output = null;
using (StreamReader sx = File.OpenText(path))
{
pth_input = sx.ReadLine();
pth_output = sx.ReadLine();
}
Console.WriteLine("Number of Files?");
string number_of_files = Console.ReadLine();
int get_number_of_files = Int32.Parse(number_of_files) + 1;
string PathFiletoCopy = pth_input;
string Extension = System.IO.Path.GetExtension(PathFiletoCopy);
string PartialNewPathFile = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(PathFiletoCopy), System.IO.Path.GetFileNameWithoutExtension(PathFiletoCopy) + "-");
for (int i = 1; i < get_number_of_files; i++)
{
System.IO.File.Copy(PathFiletoCopy, PartialNewPathFile + i.ToString("D6") + Extension);
}
string[] txtfiles = Directory.GetFiles(pth_output, "*.txt");
foreach (var file in txtfiles)
{
string get_file_counter = System.IO.Path.GetDirectoryName(file.Substring(7,6));
FileStream fs = new FileStream(file, FileMode.Append, FileAccess.Write);
FileStream fi = new FileStream(file, FileMode.Open, FileAccess.Read);
using (StreamReader reader = new StreamReader(fi))
{
using (StreamWriter writer = new StreamWriter(fs))
{
string line = null;
while ((line = reader.ReadLine()) != null)
{
string replace_line_one = line.Replace("Hello 000001","Hello"+ "["+get_file_counter+"]");
string replace_line_two = line.Replace("My number is 000001", "My number is" + "[" + get_file_counter + "]");
}
writer.Close();
} reader.Close();
}
}
Console.Read();
I hope you can help
Appreciate your help guys

string[] files = Directory.GetFiles(directoryPath, "*.txt");
Regex regex = new Regex("\\d+(?=\\.txt)");
foreach (var file in files)
{
string[] lines = File.ReadAllLines(file);
string number = regex.Match(Path.GetFileName(file)).Value;
lines[0] = "Hello " + number;
lines[1] = "My number is " + number;
File.WriteAllLines(file, lines);
}
Regex makes this solution nonspecific.

This might do the trick for you
System.IO.Directory myDir = pth_output;
int count = (myDir.GetFiles().Length) + 1;
string thenumber = String.Format("0:000000", count);
string filename = "Mytext-" + thenumber + ".txt";
string filetext = "Hello " + thenumber + Environment.NewLine + "My number is " + thenumber;
File.WriteAllText(Path.Combine(myDir,filename) , createText);
In myDir I am expecting you can pull the path of the folder which contains all the txt files.
myDir.GetFiles().Length will give you the count of the files exists in the folder and as we want only txt files you can search it like Directory.GetFiles(path, "*.txt", SearchOption.AllDirectories).Length; instead
String.Format("0:000000", count); will give you the number in your format of preceding zeros.

Related

Passing the length and the value on a string format

I have the below code that i m reading from datagrid and i export to ascii file and work fine
FileInfo info = new FileInfo(#"C:\SqlExports\");
info.Directory.Create();
string fileName = condition + " " + date + ".txt";
FileStream stream = new FileStream(#"C:\SqlExports\" + fileName, FileMode.OpenOrCreate);
StreamWriter sw = new StreamWriter(stream, Encoding.Default);
for (int i = 0; i < Grid.Rows.Count; i++)
{
List<string> rowprint = new List<string>();
for (int f = 0; f < Grid.Columns.Count; f++)
{
if (Grid.Rows[i].Cells[f].Value != DBNull.Value)
{ rowprint.Add(Grid.Rows[i].Cells[f].Value.ToString()); }
else
{
rowprint.Add(" ");
}
}
sw.Write(string.Format("{0,-19}", rowprint[0]) + String.Format("{0,10}", rowprint[1]) + sw.NewLine, Encoding.Default);
}
sw.Close();
I need to make my code reusable so if the grid populated with other datas to read each time what i need.
i tried
sw.Write(string.Format("0, -(rowprint[0].length + 2)", rowprint[0]) + string.Format("{"0,rowprint[1].Length + 2"} + sw.Newlinn, Encoding.Default);
but of course not working so how can i have the length plus 2 blanks and the value?
of course i know that i need a var with the columns because its time maybe the columns is 2 or 3 or etc.

How to avoid duplicate files (of different extensions) when auto generating new files

I have created a program which cleans access and error logs and then outputs them in a new file in the same directory. The input is in format .txt and the output is in format .csv - however it is giving me two output files, one in .csv format and one in .txt format(.txt file is empty) instead of just the .csv file? I can't understand why this is happening.
Below is the two ouput files as shown in the directory:
Below is the code which generates the new file with the unique name:
static FileStream CreateFileWithUniqueName(string folder, string fileName, int maxAttempts = 1024)
{
var fileBase = Path.GetFileNameWithoutExtension(fileName);
var ext = Path.GetExtension(fileName);
// build hash set of filenames for performance
var files = new HashSet<string> (Directory.GetFiles(folder));
for (var index = 0; index < maxAttempts; index++)
{
// first try with the original filename, else try incrementally adding an index
var name = (index == 0)
? fileName
: String.Format("{0} ({1}){2}", fileBase, index, ext);
// check if exists
var fullPath = Path.Combine(folder, name);
if(files.Contains(fullPath))
continue;
// try to create the file
try
{
return new FileStream(fullPath, FileMode.CreateNew, FileAccess.Write);
}
catch (DirectoryNotFoundException) { throw; }
catch (DriveNotFoundException) { throw; }
catch (IOException)
{
}
}
throw new Exception("Could not create unique filename in " + maxAttempts + " attempts");
}
And finally the code below is the code which reads in the existing file and cleans it:
public static void readFile(string fileName)
{
using (var stream = CreateFileWithUniqueName(#"C:\Users\michael\Desktop\WindowsFormsApplication1\WindowsFormsApplication1\bin\Debug\", fileName))
{
Console.WriteLine("Created \"" + stream.Name + "\"");
newFileName = stream.Name;
Globals.CleanedErrorFileName = newFileName;
}
string CSVfileName = Path.ChangeExtension(newFileName, ".csv");
StreamReader reader = new StreamReader(fileName);
StreamWriter writer = new StreamWriter(CSVfileName);
string line;
string personalIdentifier = new string(fileName.Take(4).ToArray());
string gender = fileName.Substring(fileName.Length - 5, 1);
string classification = fileName.Substring(fileName.Length - 8, 2);
string text = string.Empty;
while ((line = reader.ReadLine()) != null)
{
string[] cleanArray;
cleanArray = new string[5];
var result = line.Split('[')
.Select((element, index) => index % 2 == 0
? element.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
: new string[] { element })
.SelectMany(element => element).ToList();
cleanArray[0] = personalIdentifier;
cleanArray[1] = gender;
cleanArray[2] = classification;
cleanArray[3] = result[0];
cleanArray[4] = result[2];
cleanArray[4] = cleanArray[4].Substring(7);
cleanArray[4] = cleanArray[4].Replace("]", " ");
cleanArray[4] = cleanArray[4].Insert(15, ",");
cleanArray[3] = cleanArray[3].Remove(cleanArray[3].Length - 2);
cleanArray[4] = cleanArray[4].Substring(0, cleanArray[4].IndexOf(":") + 1);
//re-formatting the date so that it can be accepted by machine learning
var dateString = cleanArray[3];
var date = DateTime.ParseExact(dateString, "ddd MMM dd HH:mm:ss yyyy", CultureInfo.InvariantCulture);
var newDateString = date.ToString("yyyy-MM-dd HH:mm:ss");
//inserting the new date and time into the array
cleanArray[3] = newDateString;
//push each clean array onto the file that has been automatically created at the top
writer.WriteLine(string.Join(", ", cleanArray.Select(v => v.ToString())));
writer.WriteLine();
}
I'm hoping the issue is something small but i can't seem to find it!
Thanks in advance!!
This line is the culprit:
return new FileStream(fullPath, FileMode.CreateNew, FileAccess.Write);
At this point, the file name in fullPath still has .txt extension, this creates the empty .txt file. Then you change extension to .csv and do this:
StreamWriter writer = new StreamWriter(CSVfileName);
which creates the new .csv file
Also, both streams are never closed in your code.

Convert .XYZ to .csv using c#

Hi i am using this method to replace " " to "," but is failing when i try to use it on data that have 32 millions lines. Is anyone knows how to modify it to make it running?
List<String> lines = new List<String>();
//loop through each line of file and replace " " sight to ","
using (StreamReader sr = new StreamReader(inputfile))
{
int id = 1;
int i = File.ReadAllLines(inputfile).Count();
while (sr.Peek() >= 0)
{
//Out of memory issuee
string fileLine = sr.ReadLine();
//do something with line
string ttt = fileLine.Replace(" ", ", ");
//Debug.WriteLine(ttt);
lines.Add(ttt);
//lines.Add(id++, 'ID');
}
using (StreamWriter writer = new StreamWriter(outputfile, false))
{
foreach (String line in lines)
{
writer.WriteLine(line+","+id);
id++;
}
}
}
//change extension to .csv
FileInfo f = new FileInfo(outputfile);
f.MoveTo(Path.ChangeExtension(outputfile, ".csv"));
I general i am trying to convert big .XYZ file to .csv format and add incremental field at the end. I am using c# for first time in my life to be honest :) Can you help me?
See my comment above - you could modify your reading / writing as follows :
using (StreamReader sr = new StreamReader(inputfile))
{
using (StreamWriter writer = new StreamWriter(outputfile, false))
{
int id = 1;
while (sr.Peek() >= 0)
{
string fileLine = sr.ReadLine();
//do something with line
string ttt = fileLine.Replace(" ", ", ");
writer.WriteLine(ttt + "," + id);
id++;
}
}
}

Is there a more efficient way of reading and writing a text fill at the same time?

I'm back at it again with another question, this time with regards to editing text files. My home work is as follow
Write a program that reads the contents of a text file and inserts the line numbers at the beginning of each line, then rewrites the file contents.
This is what I have so far, though I am not so sure if this is the most efficient way of doing it. I've only started learning on handling text files at the moment.
static void Main(string[] args)
{
string fileName = #"C:\Users\Nate\Documents\Visual Studio 2015\Projects\Chapter 15\Chapter 15 Question 3\Chapter 15 Question 3\TextFile1.txt";
StreamReader reader = new StreamReader(fileName);
int lineCounter = 0;
List<string> list = new List<string>();
using (reader)
{
string line = reader.ReadLine();
while (line != null)
{
list.Add("line " + (lineCounter + 1) + ": " + line);
line = reader.ReadLine();
lineCounter++;
}
}
StreamWriter writer = new StreamWriter(fileName);
using (writer)
{
foreach (string line in list)
{
writer.WriteLine(line);
}
}
}
your help would be appreciated!
thanks once again. :]
this should be enough (in case the file is relatively small):
using System.IO;
(...)
static void Main(string[] args)
{
string fileName = #"C:\Users\Nate\Documents\Visual Studio 2015\Projects\Chapter 15\Chapter 15 Question 3\Chapter 15 Question 3\TextFile1.txt";
string[] lines = File.ReadAllLines(fileName);
for (int i = 0; i< lines.Length; i++)
{
lines[i] = string.Format("{0} {1}", i + 1, lines[i]);
}
File.WriteAllLines(fileName, lines);
}
I suggest using Linq, use File.ReadLinesto read the content.
// Read all lines and apply format
var formatteLines = File
.ReadLines("filepath") // read lines
.Select((line, i) => string.Format("line {0} :{1} ", line, i+1)); // format each line.
// write formatted lines to either to the new file or override previous file.
File.WriteAllLines("outputfilepath", formatteLines);
Just one loop here. I think it will be efficient.
class Program
{
public static void Main()
{
string path = Directory.GetCurrentDirectory() + #"\MyText.txt";
StreamReader sr1 = File.OpenText(path);
string s = "";
int counter = 1;
StringBuilder sb = new StringBuilder();
while ((s = sr1.ReadLine()) != null)
{
var lineOutput = counter++ + " " + s;
Console.WriteLine(lineOutput);
sb.Append(lineOutput);
}
sr1.Close();
Console.WriteLine();
StreamWriter sw1 = File.AppendText(path);
sw1.Write(sb);
sw1.Close();
}

How to efficiently cross reference 2 text files? | Improve my code

Below an outline of what my code does:
Read TextFileA which has 150k lines.
Read TextFileB which has 150k lines and is a cross reference list for TextFileA.
.Split both text files and match specified elements.
Finally, output a 3rd text file which will contain values from both TextFileA and TextFileB.
The below code runs well until about 13,000 lines in and then the program becomes exceedingly slow.
Could someone explain why the program becomes exponentially slower and how I could improve on this code? Thanks.
private void BT_Xref_Click(object sender, EventArgs e)
{
//grabs file path from text box
string ManifestPath = TB_Manifest.Text;
//grabs parent directory from file path
string directoryName = Path.GetDirectoryName(ManifestPath);
//creates a new folder for the final output text file
string pathString = Path.Combine(directoryName, "Final Index");
Directory.CreateDirectory(pathString);
//list for matching text lines which will eventually be output to the final text file
List<string> NewData = new List<string>();
//initializes StreamReader for the first text file
StreamReader ManifestReader = new StreamReader(ManifestPath);
String[] ManifestArray = File.ReadAllLines(ManifestPath);
List<string> RemoveManifest = new List<string>(ManifestArray);
//initializes StreamReader for the second text file
StreamReader OutputReader = new StreamReader(TB_Complete.Text);
String[] OutputArray = File.ReadAllLines(TB_Complete.Text);
List<string> RemoveOutput = new List<string>(OutputArray);
//initializes a count which decides at what point a text file should be created
int shortcount = 0;
//.ReadLine is initialized to ignore the first line in both text files
string ManifestLine = ManifestReader.ReadLine();
string OutputLine = OutputReader.ReadLine();
foreach (string mfile in ManifestArray)
{
ManifestLine = ManifestReader.ReadLine();
string ManifestElement = ManifestLine.Split(',')[6];
string ManifestElement2 = ManifestLine.Split(',')[5];
//value to be retreived and output to final text file
string ManifestElementDate = ManifestElement2.Replace("/", "-");
//value to be compared with the other text file
string ManifestNoExt = Regex.Replace(ManifestElement, ("(\\.\\w+$)"),"");
//resets OutpuReader reader to ensure no lines are being skipped
OutputReader.BaseStream.Position = 0;
//counting the mfile position in the ManifestArray
//int removeIndex = Array.IndexOf(ManifestArray, mfile);
//remove by resising the array
//Array.Resize(ref ManifestArray, ManifestArray.Length - 1);
foreach (string ofile in OutputArray)
{
OutputLine = OutputReader.ReadLine();
//value to be comapred with other text file
string OutputElement = OutputLine.Split('|')[2];
//if values equal then add the specified line of text to the list.
if (ManifestNoExt.Equals(OutputElement))
{
NewData.Add(OutputLine + "|" + ManifestElementDate);
RemoveManifest.RemoveAll(item => item == ManifestLine);
if (NewData.Count == 1000)
{
//if youve reached the count then output files into a new text file
shortcount = shortcount + 1;
File.WriteAllLines(pathString + "\\test" + shortcount + ".txt", NewData);
NewData.Clear();
}
break;
}
}
}
//once all line of text have been searched combine all text files in directory
shortcount = shortcount + 1;
File.WriteAllLines(pathString + "\\test" + shortcount + ".txt", NewData);
String[] SplitTextFiles = Directory.GetFiles(pathString, "*.*", SearchOption.AllDirectories);
using (var FinalIndexFile = File.Create(pathString + "\\FinalIndex.txt"))
{
foreach (var file in SplitTextFiles)
{
using (var input = File.OpenRead(file))
{
input.CopyTo(FinalIndexFile);
}
File.Delete(file);
}
}
//File.WriteAllLines("\\test.txt", Directory.EnumerateFiles(pathString, #"*.txt").SelectMany(file => File.ReadLines(file)));
}
You have an O(nm) algorithm here, and assuming that n and m are the same, its actually an O(n^2). That's not so good and is why its slowing to a crawl (for 150k rows in each file, you are looking at 22500000000 iterations of the inner loop. Not entirely certain what your code is trying to do, but based on the condition if (ManifestNoExt.Equals(OutputElement)), I think you can reduce the complexity drastically as follows:
Read in TextFileA, store values into a Dictionary based on ManifestNoExt as Key and mFile as value.
Next read in TextFileB and iterate over all rows in B and do a lookup in the dictionary that was constructed.
This will give you an algorithm that is O(n) + O(m), which will be fast.
Also, I am not sure why you are reading in the entire files and then reading them in again inside the loops (the contents of ManifestArray and OutputArray is the same as the files). That is certainly a cause for slow down as well since you are going to end up hammering the file system.
A completely untested version of this idea:
private void BT_Xref_Click(object sender, EventArgs e)
{
//grabs file path from text box
string ManifestPath = TB_Manifest.Text;
//grabs parent directory from file path
string directoryName = Path.GetDirectoryName(ManifestPath);
//creates a new folder for the final output text file
string pathString = Path.Combine(directoryName, "Final Index");
Directory.CreateDirectory(pathString);
//list for matching text lines which will eventually be output to the final text file
List<string> NewData = new List<string>();
String[] ManifestArray = File.ReadAllLines(ManifestPath);
List<string> RemoveManifest = new List<string>(ManifestArray);
String[] OutputArray = File.ReadAllLines(TB_Complete.Text);
List<string> RemoveOutput = new List<string>(OutputArray);
//initializes a count which decides at what point a text file should be created
int shortcount = 0;
//.ReadLine is initialized to ignore the first line in both text files
string ManifestLine = ManifestReader.ReadLine();
string OutputLine = OutputReader.ReadLine();
Dictionary<string, Tuple<string, string>> ManifestMap = new Dictionary<string, Tuple<string, string>>();
foreach (string mfile in ManifestArray.Skip(1))
{
string ManifestLine = mfile;
string ManifestElement = ManifestLine.Split(',')[6];
string ManifestElement2 = ManifestLine.Split(',')[5];
//value to be retreived and output to final text file
string ManifestElementDate = ManifestElement2.Replace("/", "-");
//value to be compared with the other text file
string ManifestNoExt = Regex.Replace(ManifestElement, ("(\\.\\w+$)"),"");
ManifestMap.Add(ManifestNoExt, Tuple.Create(ManifestElementDate, ManifestLine));
//counting the mfile position in the ManifestArray
//int removeIndex = Array.IndexOf(ManifestArray, mfile);
//remove by resising the array
//Array.Resize(ref ManifestArray, ManifestArray.Length - 1);
}
foreach (string ofile in OutputArray.Skip(1))
{
//value to be compared with other text file
string OutputElement = OutputLine.Split('|')[2];
//if values equal then add the specified line of text to the list.
if (ManifestMap.ContainsKey(OutputElement))
{
NewData.Add(OutputLine + "|" + ManifestMap[OutputElement].Item1);
RemoveManifest.RemoveAll(item => item == ManifestMap[OutputElement].Item2);
if (NewData.Count == 1000)
{
//if youve reached the count then output files into a new text file
shortcount = shortcount + 1;
File.WriteAllLines(pathString + "\\test" + shortcount + ".txt", NewData);
NewData.Clear();
}
break;
}
}
//once all line of text have been searched combine all text files in directory
shortcount = shortcount + 1;
File.WriteAllLines(pathString + "\\test" + shortcount + ".txt", NewData);
String[] SplitTextFiles = Directory.GetFiles(pathString, "*.*", SearchOption.AllDirectories);
using (var FinalIndexFile = File.Create(pathString + "\\FinalIndex.txt"))
{
foreach (var file in SplitTextFiles)
{
using (var input = File.OpenRead(file))
{
input.CopyTo(FinalIndexFile);
}
File.Delete(file);
}
}
//File.WriteAllLines("\\test.txt", Directory.EnumerateFiles(pathString, #"*.txt").SelectMany(file => File.ReadLines(file)));
}

Categories