How to replace characters in a string while looping? - c#

I would like to verify if a file exists on multiple servers. The only thing that's different on the servers is the number on the server, ex. Server1, Server2, Server3, etc.
How would I write a loop that replaces each number with the next highest number up until, say Server 10?
Here is what I have so far:
var fileLocation = #"\\Server1\documents\File.txt";
var newFileInfoTest = fileLocation.Replace("Server1", "Server2");
if (File.Exists(newFileInfoTest))
txtTextBox.Text = "Server1 -- File copy successful.";
else
txtTextBox.Text = "Server1 -- File copy unsuccessful";

"How would I write a loop that replaces each number with the next highest number up until, say Server 10?"
You can set the server name in a loop, using the loop iterator value as part of the server name
for(int i = 1; i <= 10; i++)
{
txtTextBox.Text = File.Exists($#"\\Server{i}\documents\File.txt")
? $"Server{i} -- File copy successful."
: $"Server{i} -- File copy unsuccessful";
}
Note that the code above will overwrite the txtTextBox.Text value on each iteration. You may instead want to capture all the statuses in the loop and then display them at the end:
txtTextBox.Text = string.Join(Environment.NewLine, Enumerable.Range(1, 10)
.Select(i => File.Exists($#"\\Server{i}\documents\File.txt")
? $"Server{i} -- File copy successful."
: $"Server{i} -- File copy unsuccessful."));
In the comments you asked:
"How would you do this if the file location was in a variable?"
One way to do this is to use a format string with a placeholder ({0}) where the number would go, and then use string.Format to fill in that placeholder inside the loop.
We can extract the server name from this string using string.Split on the \ character and grabbing the first item.
For example:
var serverPath = #"\\Server{0}\documents\File.txt";
txtTextBox.Text = string.Join(Environment.NewLine, Enumerable.Range(1, 10)
.Select(i =>
{
var thisPath = string.Format(serverPath, i);
var serverName = thisPath.Split(new[] { '\\' },
StringSplitOptions.RemoveEmptyEntries).First();
return File.Exists(thisPath)
? $"{serverName} -- File copy successful."
: $"{serverName} -- File copy unsuccessful.";
}));

You can do something like this, make sure your message will not get over write, you can use string builder instead of concatenation. hope you can get the logic
var msg = string.Empty;
for(int i = 1; i < 11; i++) {
var fileLocation = $"\\Server{i}\documents\File.txt";
if (File.Exists(fileLocation))
{
msg += $"Server{i} -- File copy successful.";
}
else
{
msg += $"Server{i} -- File copy unsuccessful.";
}
}
txtTextBox.Text = msg;

Try this:
for (int i = 0; i < 11; i++){
var fileLocation = $#"\\Server{i}\documents\File.txt";
if (File.Exists(fileLocation))
txtTextBox.Text = $"Server{i} -- File copy successful.";
else
txtTextBox.Text = $"Server{i} -- File copy unsuccessful";
}
}

"How would I write a loop that replaces each number with the next highest number up until, say Server 10?"
var numberofServers = 10;
for(int i =0; i <= numberOfServers; i++){
var fileLocation = $"\\Server{i}\\documents\\File.txt";
if(File.Exists(fileLocation)){
//Success
}
else{
//UnSuccessful
}
}

Related

Building a new path-like string from an existing one

I'd like to modify a source string which is looking like
"one.two.three"
and transfer it into a string with slashes to use it as a folder string which has the following structure:
"one\one.two\one.two.three"
Do you know more elegant ways to realize this, than my solution below? I'm not very satisfied with my for-loops.
var folder = "one.two.three";
var folderParts = folder.Split('.');
var newFolder = new StringBuilder();
for (int i = 0; i < folderParts.Length; i++)
{
for (int j = 0; j < i; j++)
{
if (j == 0)
{
newFolder.Append("\\");
}
newFolder.Append($"{folderParts[j]}.");
}
newFolder.Append(folderParts[i]);
}
You can do this quite tersely with Regex
var newFolder = Regex.Replace(folder, #"\.", #"\$`.");
This matches on each period. Each time it finds a period, it inserts a backslash and then the entire input string before the match ($`). We have to add the period in again at the end.
So, steps are (< and > indicate text inserted by the substitution at that step):
Match on the 1st period. one<\one>.two.three
Match on the 2nd period. one\one.two<\one.two>.three
Result: one\one.two\one.two.three
For bonus points, use Path.DirectorySeparatorChar for cross-platform correctness.
var newFolder = Regex.Replace(folder, #"\.", $"{Path.DirectorySeparatorChar}$`.")
Here's another linqy way:
var a = "";
var newFolder = Path.Combine(folder.Split('.')
.Select(x => a += (a == "" ? "" : ".") + x).ToArray());
You can try Linq:
string folder = "one.two.three";
string[] parts = folder.Split('.');
string result = Path.Combine(Enumerable
.Range(1, parts.Length)
.Select(i => string.Join(".", parts.Take(i)))
.ToArray());
Console.Write(newFolder);
Outcome:
one\one.two\one.two.three
You can go forward-only in one loop like this:
var folder = "one.two.three";
var newFolder = new StringBuilder();
int index = -1;
while (index + 1 < folder.Length) {
index = folder.IndexOf('.', index + 1);
if (index < 0) {
newFolder.Append(folder);
break;
}
else {
newFolder.Append(folder, 0, index);
newFolder.Append(Path.DirectorySeparatorChar);
}
}
You can try it out here.
Instead of splitting the string first, I find it more elegant to start with what you have and reduce it:
var folder = "one.two.three";
var newFolder = string.Empty;
for (var f = folder; f.Any(); f = f.Remove(Math.Max(f.LastIndexOf('.'), 0)))
newFolder = Path.Combine(f, newFolder);
Console.WriteLine(newFolder);
Output:
one\one.two\one.two.three

C# - Foreach two line in Text File

I am developing in C#.
I have a text file containing the following:
Sam
NYC
Mii
Peru
LEO
Argentina
I want to iterate through this file two line by two line, then print to the console the first line, second line (the Name and the Country) of each couple, so the output would be:
Sam, NYC
Mii, Peru
Here is what I have tried:
int linenum = 0;
foreach (string line in File.ReadLines("c:\\file.txt"))
{
string word = line;
string s = "";
string j = "";
linenum = linenum + 1;
if(linenum % 2 != 0) //impaire
{
s = line;
}
else
{
j = line;
}
Console.WriteLine((string.Concat(s, j));
}
But that's not working, I want to do:
int linenum = 0;
foreach( two lines in File.ReadLines("c:\\file.txt"))
{
linenum = linenum + 1;
//get the first line (linenum = 1) and store it in a string s
// then get the second line (linenum = 2) and store it in a string j
// then print the two strings together to the console like that
Console.WriteLine((string.Concat("S: " + s,"J: " j));
}
How can I do that ?
Use File.ReadAllLines to return an array of strings:
var lines = File.ReadAllLines(filePath);
for (int i = 0; i < lines.Length; i+=2)
{
var s = lines[i];
var j = lines[i+1];
Console.WriteLine($"S: {s} J: {s}");
}
You do your output with Console.WriteLine in every line, but you also should do that only for every second line. Furthermore, your variables s and j live inside the loop's scope, so they are recreated with every iteration and loose their prior value.
int i = 0; string prev = "";
foreach (string line in File.ReadLines("c:\\file.txt")) {
if (i++ % 2 == 0) prev = line;
else Console.WriteLine($"{prev}, {line}");
}
Another approach would be iterating the array you get from File.ReadAllLines with an for loop instead of foreach and increase the index by 2
var lines = File.ReadAllLines("c:\\file.txt");
//make sure, you have an even number of lines!
if (lines.Length% 2 == 0) for (int i = 0; i < lines.Length; i+=2) {
Console.WriteLine($"{lines[i]}, {lines[i+1]}");
}
You can write yourself a little helper method to return batches of lines.
This implementation handles files that are not a multiple of the batch size (2 in your case) by returning "" for the missing lines at the end of the file.
public static IEnumerable<string[]> BatchedLinesFromFile(string filename, int batchSize)
{
string[] result = Enumerable.Repeat("", batchSize).ToArray();
int count = 0;
foreach (var line in File.ReadLines(filename))
{
result[count++] = line;
if (count != batchSize)
continue;
yield return result;
count = 0;
result = Enumerable.Repeat("", batchSize).ToArray();
}
if (count > 0)
yield return result;
}
Note that this also returns a separate array for each result, in case you make a copy of it.
Given that code, you can use it like so:
foreach (var batch in BatchedLinesFromFile(filename, 2))
{
Console.WriteLine(string.Join(", ", batch));
}
Actually, you can use LINQ to get two lines in a time using Take
var twoLines = File.ReadLines(#"YourPath").Take(2));
As you can use Skip to skip the two lines you took and take the next two lines like :
var twoLines = File.ReadLines(#"YourPath").Skip(2).Take(2));
EDIT : Thanks for #derpirscher there were a performance issue so changed the code to the following :
first read the whole file and store it in a string array
then loop through it using LINQ to take two elements from the array in a time.
string[] myStringArray = File.ReadAllLines(#"YourFile.txt");
for (int i = 0; i < myStringArray.Length ; i+=2)
{
var twoLines = myStringArray.Skip(i).Take(2).ToArray();
}
Another one, using Enumerable.Repeat() and an interger selector incremented a [NumberOfLines / 2] times.
Could be interesting for the LINQ addicted (a for / foreach solution is probably better anyway).
string[] input = File.ReadAllLines([SourcePath]);
int Selector = -1;
string[] output = Enumerable.Repeat(0, input.Length / 2).Select(_ => {
Selector += 2;
return $"{input[Selector - 1]} {input[Selector]}";
}).ToArray();
The output is:
Sam NYC
Mii Peru
LEO Argentina
Use the right tool for the job. foreach() is not the right tool here.
Without giving up the memory efficiency of ReadLines() over ReadAll():
using (var lines = File.ReadLines("c:\\file.txt").GetEnumerator())
{
while (lines.MoveNext())
{
string firstLine = lines.Current;
if (!lines.MoveNext())
throw new InvalidOperationException("odd nr of lines");
string secondLine = lines.Current;
// use 2 lines
Console.WriteLine("S: " + firstLine ,"J: " + secondLine);
}
}

C# String Query how many / characters it contains

I would like to inquire how many / are in a string.
When I get the number how can I get all folders now (So how can I separate them)?
For Example: Folder/Cats (1 / = 2 folders) String1 Folder, String2 Cats
I first ask whether there is any / in the string
Regex myRegex = new Regex(#"[/]{1}", RegexOptions.IgnoreCase);
Match matchSuccess = myRegex.Match(string);
if (matchSuccess.Success)
{
// Create several folders
// Folder/Cats....
}
else
{
// Create only one folder
// Folder
}
String Examples:
• Folder/UnderFolder/Cat/Pics
• NewFolder/Cats
• Folder
• NewFolder
To count the number of occurrence of /, what you can do is use the Split.Length
int count = folderString.Split('/').Length - 1;
As for the name of the folders, you can get them by calling the index
folderString.Split('/')[index]
Here's the whole console app code for that:
string folderString = #"Folder/UnderFolder/Cat/Pics";
int count = folderString.Split('/').Length - 1;
for(int x = 0; count >= x; x++)
{
Console.WriteLine(folderString.Split('/')[x]);
}
Console.WriteLine("Count: {0}", count);
The output would be:
Folder
UnderFolder
Cat
Pics
Count: 3
Hope it helps!
Just use standart CreateDirectory method.
Directory.CreateDirectory(#"C:\folder1\folder2\folder3\folder4")
Why do you want to go for regex. Finding any characters in a string or splitting a string is very easy. Sample code for your case :
string input = #"Folder/UnderFolder/Cat/Pics";
string[] values = input.Split('/');
int numOfSlashes = values.Length - 1;
Console.WriteLine("Number of Slashes = " + numOfSlashes);
foreach (string val in values)
{
Console.WriteLine(val);
}
//Your folder path
string yourFolderPath= #"C:/Folder/UnderFolder/Cat/Pics";
//If you want to count number of folders in the given folder path
int FolderCount = yourFolderPath.Count(s => s == '/');
//If you want to create folder you can use directly below code
Directory.CreateDirectory(yourFolderPath);

Merge 2 text files ASP.NET

I want to merge 2 .txt files into one text file. Let's say I have 2 text files. First one contains 100 rows only "Try Again". Like this one in the picture:
And the second text file contains bunch of random codes:
I want to merge these 2 text files, like this one in the picture below:
I have one week and I have not figured it out yet.
Just open both files and, in a loop, read four lines from the first and one line from the second. Output each line as it's read.
using (var outputFile = File.CreateText("OutputFile.txt"))
{
using (var input1 = File.OpenText("TryAgain.txt"))
using (var input2 = File.OpenText("File2.txt"))
{
while (!input1.EndOfStream && !input2.EndOfStream))
{
int i;
for (i = 0; i < 4 && !input1.EndOfStream; ++i))
{
var s1 = input1.ReadLine();
outputFile.WriteLine(s1);
}
if (i != 4) break; // end of first file
// now read one line from the other file, and output it
var s2 = input2.ReadLine();
outputFile.WriteLine(s2);
}
}
}
This has the advantage of not having to read both files into memory all at once, and you don't have to build the entire output in memory. Each line is output immediately after it's written.
Edit: I edit the code via Jim, he warned me and now it's working.
First you need to read both files and store all lines to string array. Then loop them like down bellow. Every fifth item you need to check and write from second file.
PS: I did not try the code but prob it will work without an error.
string[] first = System.IO.File.ReadAllLines("path of first txt file");
string[] second = System.IO.File.ReadAllLines("path of second txt file");
var sb = new StringBuilder();
var k = 0;
var m = 0;
for (int i = m; i < second.Length; i++)
{
m = i + 1;
for (int j = k; j < first.Length; j++)
{
k = j + 1;
if (j != 0 && j % 4 == 0)
{
sb.Append(second[i] + "\n");
break;
}
else
{
sb.Append(first[j] + "\n");
continue;
}
}
}
// create new txt file
var file = new System.IO.StreamWriter("path of third txt file");
file.WriteLine(sb.ToString());

Moving in text file with C#

I have a problem with C#.
I am writing code to search a text file until it finds a certain word, then the code should move three lines and read the fourth, then continue the search to find the certain word again.
Now I don't know how to navigate through the file (forward and backward) to the line I want.
Can anybody help?
You can do something like this:
var text = File.ReadAllLines("path"); //read all lines into an array
var foundFirstTime = false;
for (int i = 0; i < text.Length; i++)
{
//Find the word the first time
if(!foundFirstTime && text[i].Contains("word"))
{
//Skip 3 lines - and continue
i = Math.Min(i+3, text.Length-1);
foundFirstTime = true;
}
if(foundFirstTime && text[i].Contains("word"))
{
//Do whatever!
}
}
// read file
List<string> query = (from lines in File.ReadLines(this.Location.FullName, System.Text.Encoding.UTF8)
select lines).ToList<string>();
for (int i = 0; i < query.Count; i++)
{
if (query[i].Contains("TextYouWant"))
{
i = i + 3;
}
}
Your requirements state that you are searching for a specific word. If that is true and you are not instead looking for a specific string, then the checked answer on this is wrong. Instead you should use:
string[] lines = System.IO.File.ReadAllLines("File.txt");
int skip = 3;
string word = "foo";
string pattern = string.Format("\\b{0}\\b", word);
for (int i = 0; i < lines.Count(); i++)
{
var match = System.Text.RegularExpressions.Regex.IsMatch(lines[i], pattern);
System.Diagnostics.Debug.Print(string.Format("Line {0}: {1}", Array.IndexOf(lines, lines[i], i) + 1, match));
if (match) i += skip;
}
If you use the string.contains method and the word you are searching for is "man", while your text somewhere contains "mantle" and "manual", the string.contains method will return as true.

Categories

Resources