Append Text with StringReader (After reader.ReadLine()) - c#

Right now I'm building a game application using c#, which will require loading from text file for the game script. (It's quite a simple visual novel game)
Now when the main form loads, i load the script from the file script.txt
And i declared :
StringReader reader = new StringReader(script);
as a global variable there
Now in the middle of the game where the reader is in the middle of the string script,
I need to append starting from next line of the reader.
Basically what I want to achieve:
Append all texts from "news.txt" to script starting from reader.ReadLine() [i.e. in the middle of the string script]
What will be the most efficient solution to achieve this?
What I know:
StreamReader sr = new StreamReader("news.txt");
string news = sr.ReadToEnd();
//Now how to append 'news' to reader.ReadLine() ??
Edit for more clarification (sorry, this is my first time asking here) :
I will try to explain more about what i'm trying to achieve here.
What i'm having right now :
//global variables
string script;
StringReader reader;
//during form_load
StreamReader sr = new StreamReader("script.txt");
script = sr.ReadToEnd();
reader - new StringReader(script);
//And as the game progresses, I keep on implementing reader.ReadLine()..
//At one point, the program will ask the user, do you want to watch the news?
DialogResult dialogResult = MessageBox("Do you want to watch the news?", , MessageBoxButtons.YesNo
if(dialogResult == DialogResult.Yes)
{
StreamReader newsSr = new StreamReader("news.txt");
string news = newsSr.ReadToEnd();
//now I want to append the contents of 'news' to the string 'script' after reader.ReadLine() - any best way to implement this?
}
One possible way (and i think it's the worst way as well) is by introducing one count variable, to get the starting position of the last reader.ReadLine(),
and execute the desired result using Insert like follows :
script = script.Insert(startIndex, news)

You cannot write into a StringReader.
However, if I understand your latest question I think you want this.
StreamReader sr = new StreamReader("news.txt");
string news = string.Empty;
string line = sr.ReadLine();
while (line != null)
{
news += line;
news += someOtherString;
line = sr.ReadLine();
}
Aside I wouldn't do this with string concatenation. I would do this with a StringBuilder.

Just load the file into memory using File.ReadAllLines().
You can then access this as a string array, without worrying about readers, writers, streams etc.
For example:
// load files as arrays
string[] scriptLinesArray = File.ReadAllLines("script.txt");
string[] newsLinesArray = File.ReadAllLines("news.txt");
// convert arrays to lists
var script = new List<string>(scriptLinesArray);
var news = new List<string>(newsLinesArray );
// append news list to script list
script.AddRange(news);

in the end I was able to resolve this problem.
This is what I used (in case anyone wanna know :))
//I'm using a switch statement, in case reader.ReadLine() == "#(morningnews)"
dialogResult = MessageBox.Show("Do you want to watch the news?", , MessageBoxButtons.YesNo);
if(dialogResult = DialogResult.Yes)
{
StreamReader sr = new StreamReader(directoryName + "\\morningactivities\\morningnews1.txt");
string news = sr.ReadToEnd();
script = script.Replace("#(morningnews)", "#(morningnews)\n" + news);
reader = new StringReader(script);
while (reader.ReadLine() != "#(morningnews)")
continue;
loadNextScript();
}
Thanks for everyone who helped, it gave me the inspiration to actually came up with this.

Related

Tried to get read file data to work, am missing the rest of the code

I am having trouble getting this to load, specifically with the indexing line. I was wondering if anyone knew how I would fill out the struct of these lines? The lines were sent from a friend whos code works but he didn't send me the rest and is busy. Ty in advance.
public static void readEmployees()
{
int index = 0;
FileStream fileStream = new FileStream(#"C:\Users\Public\TestFolder\Test.txt", FileMode.Open, FileAccess.Read);//Create file stream object with open and read modes
StreamReader streamReader = new StreamReader(fileStream);//Create file reader object
streamReader.BaseStream.Seek(0, SeekOrigin.Begin);//Return carret to the start of the file
for (string line = streamReader.ReadLine(); line != null; line = streamReader.ReadLine())//Read line and store in the string. Read till the read line is not empty.
{
string[] employee = line.Split(' ');//Split the read values by a space and returns each value to the array
int employeeId = int.Parse(employee[0]);
string employeeFirstName = employee[1];
string employeeLastName = employee[2];
double employeeIncome = double.Parse(employee[3]);
double employeeKiwiSaverPercentage = double.Parse(employee[4]);
employee Employee = new employee(employeeId, employeeFirstName, employeeLastName, employeeIncome, employeeKiwiSaverPercentage);
static.employees[index] = Employee;//Store the values in the employee
index++;
}
streamReader.Close();//Close the reader
fileStream.Close();//Close the
}
You need the rest plain and simple... code doesn't work unless you have all of it...you are asking for help fixing it, but we don't know the rest this code works but is worthless without the other pieces it's like doing a puzzle without the puzzle...

C# Most efficient way to read file content, replace some content and finally load it as XDocument

I would like to read file content and make some replacements on it. After that, the initial file with the replacements is loaded as XDocument. I have made a 2 different implementations:
implementation1:
string contents1 = File.ReadAllText(fileInfo.FullName, new UTF8Encoding(true));
File.WriteAllText(fileInfo.FullName, methodForReplacements(contents1), new UTF8Encoding(true));
return XDocument.Load(fileInfo.FullName, LoadOptions.PreserveWhitespace);
implementation2:
string contents;
using (FileStream fs = File.OpenRead(fileInfo.FullName))
{
using (StreamReader sr = new StreamReader(fs, new UTF8Encoding(true)))
{
contents = methodForReplacements(sr.ReadToEnd());
}
}
using (StreamWriter sw = new StreamWriter(fileInfo.Name, false, new UTF8Encoding(true)))
{
sw.Write(contents);
}
return XDocument.Load(fileInfo.FullName, LoadOptions.PreserveWhitespace);
replacementMethod():
private string methodForReplacements(string contents)
{
string replaced = new StringBuilder(contents)
.Replace("\r", "
")
.Replace("\n", "
")
.ToString();
return replaced;
}
After some benchmarking (10000 iterations, filesize: 265KB, numberOfReplacements: 10), it seems that the 2 implementations take very much the same time to execute (implementation1: 99sec, implementation2: 97sec). Is there any other more optimized and efficient way to achieve the same output?
It looks like a three task block process. so as long as you don't need to read ahead to know what you have to inert into the XDocument, what you can do is as you read in each line of input file, look for characters that need to be replaced, and then write out input line with changes. Between the input line and changed content, I gather you have enough information and content to decide what needs to go to the XDocument to respond accordingly. That'll save you some time.

How to enter multiple data from textbox to txtfile without overwrite [duplicate]

This question already has answers here:
Append lines to a file using a StreamWriter
(11 answers)
Closed 7 years ago.
i need some help with entering data in a txt.file.
this is the following code:
StreamWriter file = new StreamWriter("opslag_kentekens");
string opslag_kentekens = textBox1.Text;
file.WriteLine(opslag_kentekens);
file.Close();
label20.Text = File.ReadAllText("opslag_kentekens");
So when i click on my button the text what is entered in the textBox1.text
has to go to my opslag_kentekens.txt. this works fine but when want to enter new text to my txt, it overwrites the first entered text. I want every text whats entered among each other. How do i do this? (sorry for my bad english).
file.WriteLine() will not keep your existing text.
You can use File.AppendAllText(String, String) instead:
https://msdn.microsoft.com/en-us/library/ms143356(v=vs.110).aspx
try this
new StreamWriter("opslag_kentekens", true);
Change your constructor to use the append overload and set it to true, that should work.
StreamWriter file = new StreamWriter("opslag_kentekens", true);
Basically you're looking at appending to a file:
From msdn:
public static void Main()
{
string path = #"c:\temp\MyTest.txt";
// This text is added only once to the file.
if (!File.Exists(path))
{
// Create a file to write to.
using (StreamWriter sw = File.CreateText(path))
{
sw.WriteLine("Hello");
sw.WriteLine("And");
sw.WriteLine("Welcome");
}
}
// This text is always added, making the file longer over time
// if it is not deleted.
using (StreamWriter sw = File.AppendText(path))
{
sw.WriteLine("This");
sw.WriteLine("is Extra");
sw.WriteLine("Text");
}
// Open the file to read from.
using (StreamReader sr = File.OpenText(path))
{
string s = "";
while ((s = sr.ReadLine()) != null)
{
Console.WriteLine(s);
}
}
}
Usually, for writing (not appending), it's easier to use the File Write methods, as they are cleaner and convey your meaning better:
var some_text = "this is some text";
var out_path = #"C:\out_example.txt";
System.IO.File.WriteAllLines(out_path, some_text);
Even better and cleaner, look #Liem's answer, which is the same but with the correct Append syntax.

How to close file that has been read

So im trying to close a file (transactions.txt) that has been open that i've used to read into a textbox and now I want to save back to the file but the problem debug says that the file is in use so I need to find a way to close it. Can anyone help me with this? Thanks!
SearchID = textBox1.Text;
string ID = SearchID.ToString();
bool idFound = false;
int count = 0;
foreach (var line in File.ReadLines("transactions.txt"))
{
//listView1.Items.Add(line);
if (line.Contains(ID))
{
idFound = true;
}
//Displays Transactions if the variable SearchID is found.
if (idFound && count < 8)
{
textBox2.Text += line + "\r\n";
count++;
}
}
}
private void SaveEditedTransaction()
{
SearchID = textBox1.Text;
string ID = SearchID.ToString();
bool idFound = false;
int count = 0;
foreach (var lines in File.ReadLines("transactions.txt"))
{
//listView1.Items.Add(line);
if (lines.Contains(ID))
{
idFound = true;
}
if (idFound)
{
string edited = File.ReadAllText("transactions.txt");
edited = edited.Replace(lines, textBox2.Text);
File.WriteAllText("Transactions.txt", edited);
}
The problem here is that File.ReadLines keeps the file open while you read it, since you've put the call to write new text to it inside the loop, the file is still open.
Instead I would simply break out of the loop when you find the id, and then put the if-statement that writes to the file outside the loop.
This, however, means that you will also need to maintain which line to replace in.
So actually, instead I would switch to using File.ReadAllLines. This reads the entire file into memory, and closes it, before the loop starts.
Now, pragmatic minds might argue that if you have a lot of text in that text file, File.ReadLines (that you're currently using) will use a lot less memory than File.ReadAllLines (that I am suggesting you should use), but if that's the case then you should switch to a database, which would be much more suited to your purpose anyway. It is, however, a bit of an overkill for a toy project with 5 lines in that file.
Use StreamReader directly with the using statement, for example:
var lines = new List<string>();
using (StreamReader reader = new StreamReader(#"C:\test.txt")) {
var line = reader.ReadLine();
while (line != null) {
lines.Add(line);
line = reader.ReadLine();
}
}
By using the using statement the StreamReader instance will automatically be disposed of after it's done with it.
You can try with this:
File.WriteAllLines(
"transactions.txt",
File.ReadAllLines("transactions.txt")
.Select(x => x.Contains(ID) ? textBox2.Text : x));
It works fine, but if the file is big you have to find other solutions.
You can use the StreamReader class instead of the methods of the File class. In this way you can use, Stream.Close() and Stream.Dispose().

Unblock specific websites

Using hostfile in C# I can block websites but I couldn't unblock them.
String path = #"C:\Windows\System32\drivers\etc\hosts";
StreamWriter sw = new StreamWriter(path, true);
sitetoblock = "\r\n127.0.0.1\t" + txtException.Text;
sw.Write(sitetoblock);
sw.Close();
MessageBox.Show(txtException.Text + " is blocked", "BLOCKED");
lbWebsites.Items.Add(txtException.Text);
txtException.Clear();
Here I need some help to unblock a specific site which is selected from listbox(lbWebsites). Is there a way to remove them from host file? I tried a lot and looked other solutions but something goes wrong in every solution.
You need to remove the lines you wrote to block the site. The most effective way is to read in the hosts file and write it again.
BTW, your method of blocking sites isn't going to be very effective. It might be okay for your usage scenario, but slightly technical people will know to look in the hosts file.
You may use a StreamReader to read the hosts file into a string. Then, initialize a new instance of a StreamWriter to write the content gathered back excluding the website you want to unblock.
Example
string websiteToUnblock = "example.com"; //Initialize a new string of name websiteToUnblock as example.com
StreamReader myReader = new StreamReader(#"C:\Windows\System32\drivers\etc\hosts"); //Initialize a new instance of StreamReader of name myReader to read the hosts file
string myString = myReader.ReadToEnd().Replace(websiteToUnblock, ""); //Replace example.com from the content of the hosts file with an empty string
myReader.Close(); //Close the StreamReader
StreamWriter myWriter = new StreamWriter(#"C:\Windows\System32\drivers\etc\hosts"); //Initialize a new instance of StreamWriter to write to the hosts file; append is set to false as we will overwrite the file with myString
myWriter.Write(myString); //Write myString to the file
myWriter.Close(); //Close the StreamWriter
Thanks,
I hope you find this helpful :)
You can do this:
String path = #"C:\Windows\System32\drivers\etc\hosts";
System.IO.TextReader reader = new StreamReader(path);
List<String> lines = new List<String>();
while((String line = reader.ReadLine()) != null)
lines.Add(line);
Then you have all lines of your hosts-file in the lines list. Afterwards, you can search for the site you want to unblock and remove it from the list until the desired site is not anymore in the list:
int index = 0;
while(index != -1)
{
index = -1;
for(int i = 0; i< lines.Count(); i++)
{
if(lines[i].Contains(sitetounblock))
{
index = i;
break;
}
}
if(index != -1)
lines.RemoveAt(i);
}
After you have done that, just convert the cleaned list to a normal string:
String content = "";
foreach(String line in lines)
{
content += line + Environment.NewLine;
}
Then just write content to the file ;)
Written in my head, so no guarantee on having no errors :P

Categories