This question already has answers here:
Adding a Line to the Middle of a File with .NET
(6 answers)
Closed 1 year ago.
I'd just like to start by saying the I am extremely new to C# and coding in general so please excuse the newbie mistakes.
I have a text document that looks something like this (inserted manually)
[VIDEO]
[!VIDEO]
And I want to be able to write some text in between these 2 "tags" without erasing them.
The current code I have to write things in the document is:
private void ReadVideoFiles()
{
string[] files =Directory.GetFiles(#"Z:\APP_LANX\VIDEOS", "*.mp4"); //Goes to the specific location of the file and gets the whole location
videoID = 0;
for (int i = 0; i < files.Length; i++)
{
videoID++;
files[i] = videoID.ToString() + ": " + files[i]; //changes the previous string so that it now contains the ID and the location
}
foreach (string file in files)
{
sw.WriteLine(file); //Uses the StreamWriter, declared previously
}
sw.Close();
}
But as you can imagine this just fully replaces everything in the document and adds the code, and the result is something like this:
1: Z:\APP_LANX\VIDEOS\vid1.mp4
2: Z:\APP_LANX\VIDEOS\vid2.mp4
3: Z:\APP_LANX\VIDEOS\vid3.mp4
4: Z:\APP_LANX\VIDEOS\vid4.mp4
instead of this
[VIDEO]
1: Z:\APP_LANX\VIDEOS\vid1.mp4
2: Z:\APP_LANX\VIDEOS\vid2.mp4
3: Z:\APP_LANX\VIDEOS\vid3.mp4
4: Z:\APP_LANX\VIDEOS\vid4.mp4
[!VIDEO]
Is there any way to check for these tags in specific so that I can write in between? Thank you!
Edit*: Later on I'll be adding new things to this text file, for example after the [!VIDEO] line I'll have other lines with something like EX1: 4 and multiple other lines that shouldn't be overwritten, only the part in between those tags can be changed.
TL:DR - Basically I want to be able to add text between those two tags (overwriting whatever is in between) while the rest of the text file remains unchanged
Assuming that your method ReadVideoFiles is called only, you could do something like this:
private void ReadVideoFiles()
{
string[] files =Directory.GetFiles(#"Z:\APP_LANX\VIDEOS", "*.mp4"); //Goes to the specific location of the file and gets the whole location
videoID = 0;
for (int i = 0; i < files.Length; i++)
{
videoID++;
files[i] = videoID.ToString() + ": " + files[i]; //changes the previous string so that it now contains the ID and the location
}
// Add header to file
sw.WriteLine($"[VIDEO]{Environment.NewLine}{Environment.NewLine}");
foreach (string file in files)
{
sw.WriteLine(file); //Uses the StreamWriter, declared previously
}
// Add footer to file
sw.WriteLine($"{Environment.NewLine}{Environment.NewLine}[!VIDEO]");
sw.Close();
}
Instead of inserting your input between the "tags", this code produces the complete file from scratch including the tags.
Maybe this is already sufficient for you? 🤔
If you don't want to spend too much time on it, you can just change :
sw.WriteLine(file);
by :
sw.WriteLine("[VIDEO]\n\n" + file + "\n\n[!VIDEO]");
You'll have the expected result.
You can insert your text at the index of the end tag in your list without overwriting any previous text you had in the file.
using System.IO;
using System.Linq;
endTag = "[!VIDEO]"
foreach (string file in files)
{
sw.Insert(sw.IndexOf(endTag), "text you want to add");
// You can replace "text you want to add" with your file variable
}
sw.Close();
Related
In my Unity3D project I have several text fields. I saved my text in some text files.
When I test my project on the computer everything works fine, and my code reads the text files. But if I upload to my iPad it won't work and the text fields stay empty.
In the image you can see where I have saved my text files.
To read my text files I use the following code:
public Text infoText;
void Update()
{
readTextFile("FileName", "StepNumber")
}
public void readTextFile(string fileName, string stepNumber)
{
StreamReader txt_Reader = new StreamReader("Assets/Resources/Text_Files/" + fileName + ".txt");
while(!txt_Reader.EndOfStream)
{
string txt_String = txt_Reader.ReadLine();
if(txt_String.Contains(stepNumber))
{
string[] separator = { "_" };
string[] strList = txt_String.Split(separator, System.StringSplitOptions.RemoveEmptyEntries);
infoText.text = string.Join("\n", strList.Skip(1));
}
}
}
What do I have to change that my iPad can read from the text files?
EDIT:
My text files looks like this:
Step 1:
* Some Text
* Some Text
Step 2:
* Some Text
* Some Text
* Some Text
Step 3:
* Some Text
Step 4:
* Some Text
So each * should be a new line in my text field. With my old c# code this was no problem, but with
var lines = textFiles.text.Split(new char[] { `*` });
foreach(var line in lines)
{
...
}
i do not know how I can do that, that my text field shows all two lines for step one.
First of all from the Best Practices for the Resources folder
**Don't use it!
Please read the reasons there.
In general for system paths do never use simple string concatenation + "/" +!
Rather use Path.Combine which automatically uses the correct path separators according to the executing platform
Path.Combine(Application.dataPath, "Resources", "Text_Files", fileName + ".txt");
However, you don't/can't simply use a StreamReader to access the Resources folders (See Resources API since it is packed into the build so you have to go through Resources.Load like
// Here you can use / since this is how Unity stores internal paths
// for load you omit the suffix
TextAsset textFile = Resources.Load<TextAsset>("Text_Files/" + filename);
string fileContent = textFile.text;
Or also have a look at Resources.LoadAsync to not block the main thread meanwhile.
BUT
Speaking about blocking the main thread: What you definitely do not want to do is using any of these within Update thus doing heavy FileIO/Loading every frame!
Store the content of that file once as it won't change afterwards anyway!
Depending on your needs you could also simply put your file in any other folder inside the Assets and simply use a TextAsset field directly and drag it into according slot via the Inspector
public TextAsset textFile;
Finally you can then go through the lines one by one using e.g.
var lines = textFile.text.Split(new char[]{'/n'});
foreach(var line in lines)
{
...
}
Note that also that Split is a quite heavy operation since it has to parse every single character in the string and create new substrings so even store these results somewhere in a field of you need them multiple times during runtime!
Typed on smartphone but I hope the idea gets clear
In your case, StreamReader txt_Reader = new StreamReader("Assets/Resources/Text_Files/" + fileName + ".txt"); points to a file on your computer. Assets/Resources/Text_Files/ only exists on your computer.
You need to access a folder that exists on your iPad. It's likely you also didn't save your data to a folder existing on your IPad.
For other devices you could use : Application.persistentDataPath + "/" + fileName
Source: https://docs.unity3d.com/ScriptReference/Application-dataPath.html
So I'm making a program to type what's in my clipboard into a text file, I plan on later transporting this information into an AHK script, but I want to do this all in one program, so if possible it will append to the .ahk file, but instead of it appending to the very last line, I need it to append to the line before return, which is the final line of the file.
Send ::redeem N4E2vzCEp {enter}
Sleep 1000
return
That's the end of the file, if possible I want my program to do something like:
string pasted = Clipboard.GetText();
sw.WriteLine.SecondLastLine("Send ::redeem " + pasted + " {enter}");
sw.WriteLine.SecondLastLine("Sleep 1000"); //Fully aware that secondlastline is not a valid command
But I don't know what the proper way of actually coding this would be.
Current code:
private void paste_Click(object sender, EventArgs e)
{
string path = #"c:\users\john\desktop\auths.txt";
using (StreamWriter sw = File.AppendText(path))
{
string pasted = Clipboard.GetText();
sw.WriteLine("Send ::redeem " + pasted + " {enter}");
sw.WriteLine("Sleep 1000");
}
}
What you can do is reading all lines into a List and then insert the new line at a specific position and write the lines back to the file.
List<string> lines = File.ReadAllLines("your file").ToList();
lines.Insert(lines.Count - 2, "new line");
File.WriteAllLines("your file", lines);
I'm changing a value within my text, but instead, it's overwriting my whole .txt file with nothing.
static void editClassMates(classMates[] classMateInfo)
{
StreamWriter sw = new StreamWriter(#"C:\Users\Callum\Documents\class.txt");
Console.Write("Who's number would you like to change? ");
string classMateInput = Console.ReadLine();
for (int i = 0; i < classMateInfo.Length; i++)
{
if (classMateInfo[i].last.Equals(classMateInput))
{
Console.Write("Enter new number: ");
string temp = Console.ReadLine();
int classMateNumber = Convert.ToInt32(temp);
classMateInfo[i].ID = classMateNumber;
}
}
sw.Close();
}
My code asks for a name within my .txt file. Once I have specified the name, it loops through until my input matches the same exact name in my .txt file. I now want to change his/her number. After I input a number, I then have a method that displays the list and the change I have made. That works, it shows me my original data along with the value I've edited.
However, I go into my class.txt file and it's completely blank now.
My question is, what part of my code is overwriting my whole file? Also, how can I properly change/edit/replace a specific value inside my .txt file?
Thanks
new StreamWriter(#"C:\Users\Callum\Documents\class.txt", true)
You are not using the overload to append. This is easily viewed in Intellisense as you type.
Hint: The File.Open-Method is even more easy to use. Topic in this SO article
I am a little stuck. I have to use the getItems method and output it to PrintItems.txt, but I am not sure how to appoach this problem.
This is my GetItems method:
public string getItems()
{
string strout = "stock items " + "\n";
foreach (Stock s in stock)
{
strout = strout + s.ToString() + "\n";
}
return strout;
}
This is my PrintItems method:
string filename = "printitems.txt";
int count = 0;
using (StreamWriter sw = new StreamWriter(filename))
{
while (count < 5 && count < stock.Count)
{
Stock t = stock[count];
sw.WriteLine(t);
count++;
}
}
It doesn't work because it doesn't write to a file at all.
You code generally should work.
But since you haven't specified full path to the text file - it will be created in the same folder where your executable file is.
If you running it from Visual Studio - it should be in your_project\bin\Debug or your_project\bin\Release folder.
You could use:
File.WriteAllText(#"C:\dummy.txt", strout);
(As long as you don't expect the string to be massive - i.e. 10MB)
'File' uses System.IO
If you made no copy & paste error then there are 4 possibilities for your pheonomenon:
string filename = "printitems.txt";
int count = 0;
using (StreamWriter sw = new StreamWriter(filename))
{
while (count < 5 && count < stock.Count)
{
Stock t = stock[count];
sw.WriteLine(t.ToString());
count++;
}
}
You had no { after the streamwriter using line was something I saw first. The second thing is that Stock t normally can't be written directly but instead you need to do the same thing as when printing it out to the console.
Third: your code does not say anything about if stock is filled or not.
Fourth: The file: You should specify a directory (not only the filename) as else it can be that it is tried to create the file in a location where you have no permissions to create a file in (normally if you put no additional path info in the same path as where the application runs in is used [if you start from the visual studio itself then the appropraite bin path] as location where the file would be created).
Additionally: You should put a try catch block around the whole thing as there can be unexpected phenomenons which result in an exception.
Getting a bit stuck on a piece of code I'm trying to write and was hoping for a helping hand if anyone knows where I'm going wrong!
I have a simple Windows Form where I have a folder browser. The user will browse to a folder and any sub-folders within will then be searched for a text file that has the word "Passed" in the title (not the body of the text file itself). There will be files with "Passed" in from many different folders, and I want the functionality of the app to search through all sub-folders and return the all the files that have this in their name.
At present I have the following code:
private void searchButton_Click(object sender, EventArgs e)
{
if (textBox1.Text == "")
{
MessageBox.Show("Please enter a path");
}
else
{
string[] allFiles = Directory.GetFiles(textBox1.Text, "*Passed*.*", SearchOption.AllDirectories);
string name = resultsText.Text;
foreach(string file in allFiles)
{
if (file.Contains("Passed"))
{
resultsText.Text = file;
}
}
}
}
However, in the resultsText texbox, it only returns 1 value. There are multiple files with "Passed" in their title and I would like to print them all to this textbox. Does anyone know where I may be going wrong and why I am only getting one file rather than all of them?
Also, this method seems to return the whole file path e.g.)
C:\Program Files\Test\abc\PassedTests.txt - does anyone know how I can trim the full path so it just returns the file name and extension?
Any help is greatly appreciated!
You need to append the text. At the moment, you're overwriting the previous value by using resultsText.Text = file;.
if (file.Contains("Passed"))
{
resultsText.AppendText(file);
}
What may be more performant would to use build your string using a StringBuilder and then assign that to the TextBox.
StringBuilder sb = new StringBuilder();
foreach(string file in allFiles)
{
if (file.Contains("Passed"))
{
sb.Append(file);
}
}
resultsText.Text = sb.ToString();
You have to change 1 line of code:
resultsText.Text = file;
To this:
resultsText.Text += file;
The + will append the text and not overwrite it.
this is the answer for your second question.
try this to get only the file name
Path.GetFileName(filepath)