I want to replace one specific line in a text file. The simplest solution would be:
public void ModifyFile(string path, int line, string targetText) {
var lines = File.ReadAllLines(path);
lines[line] = targetText;
File.WriteAllLines(path, lines);
}
The thing is, if the file is huge enough, I will get a System.OutOfMemoryException because File.ReadAllLines() tries to load the whole file in memory, instead of a line-by-line way.
I know there is another way to read a specific line with less memory cost:
var line = File.ReadLines(path).Skip(line-1).Take(1).ToString();
How can I replace over that line in the file?
I'm looking for something like FileStream.Write Method:
var writer = File.OpenWrite(path);
writer.Write(Encoding.UTF8.GetBytes(targetText),
offset, Encoding.UTF8.GetByteCount(targetText));
But it's difficult to know offset.
Is there a better way to do that?
-- UPDATE --
The temporary file solution suggested by answers works great.
At the same time, I am wondering, is there a specific case solution without creating a temporary file, if I know line is a small number (line < 100 let's say)? There must be a better solution if I want to change the 10th line in a text file having 100m lines.
You could just read the file a line at a time using streams, and copy the contents into a new file, or rename the old file with a backup name and then process with;
string line;
int couinter = 0;
// Read the file and display it line by line.
System.IO.StreamReader reader = new System.IO.StreamReader(path);
System.IO.StreamWriter writer = new System.IO.StreamWriter(new_path);
while((text = reader.ReadLine()) != null)
{
// Check for your content and replace if required here
if ( counter == line )
text = targetText;
writer.writeline(text);
counter++;
}
reader.Close();
writer.Close();
What you can do is open the FileStrem with StreamReader (which provides ReadLine method). Now read line by line and write the output to a temporary file line by line. When you are on the desired line just change the line.
Related
I'm trying to modify an .ini file, in C# with .NET 5.0, using FileStream and StreamReader / StreamWriter. I just need to modify the first line of the file so I read the entire file into a list of strings called strList, modify the first line, and then write it all back to the same file.
List<string> strList = new List<string>();
using (FileStream fs = File.OpenRead(#"C:\MyFolder\test.ini"))
{
using (StreamReader sr = new StreamReader(fs))
{
while (!sr.EndOfStream)
{
strList.Add(sr.ReadLine());
}
}
}
strList[0] = "test01";
using (FileStream fs = File.OpenWrite(#"C:\MyFolder\test.ini"))
{
using (StreamWriter sw = new StreamWriter(fs))
{
for (int x = 0; x < ewsLines.Count; x++)
{
sw.WriteLine(strList[x]);
}
}
}
The issue I'm running into is that I'll have new character(s) at the end of my file on new line(s). I verified that the number of lines I read from the file matches what is in the file and that the for loop only writes that same number of lines back into the file. I don't have any issues writing other strings except for "test01". This string is the only one that causes the issue that I just described. It seems to be grabbing characters from the last line like R or LAYER from MULTI_LAYER.
Ex 1: This
S10087_U1
Cq4InEq=TRUE
XtrVer=5.5
IOCUPDATEMDB=TRUE
ARCHITECTURE=MULTI_LAYER
Becomes this
test01
Cq4InEq=TRUE
XtrVer=5.5
IOCUPDATEMDB=TRUE
ARCHITECTURE=MULTI_LAYER
R
Ex 2: This
test01 - Copy
Cq4InEq=TRUE
XtrVer=5.5
IOCUPDATEMDB=TRUE
ARCHITECTURE=MULTI_LAYER
ER
Becomes this
test01
Cq4InEq=TRUE
XtrVer=5.5
IOCUPDATEMDB=TRUE
ARCHITECTURE=MULTI_LAYER
LAYER
Replacing the StreamWriter portion with the following seems to fix the issue but I'm trying to figure out why using StreamWriter doesn't work as I expect it to.
File.WriteAllLines(#"C:\MyFolder\test.ini", strList);
This is because you're using File.OpenWrite. From the remarks in the documentation:
The OpenWrite method opens a file if one already exists for the file path, or creates a new file if one does not exist. For an existing file, it does not append the new text to the existing text. Instead, it overwrites the existing characters with the new characters. If you overwrite a longer string (such as "This is a test of the OpenWrite method") with a shorter string (such as "Second run"), the file will contain a mix of the strings ("Second runtest of the OpenWrite method").
While you could just change your code to use File.Create instead, I'd suggest changing the code more significantly - not just the writing, but the reading too:
string path = #"C:\MyFolder\test.ini";
var lines = File.ReadAllLines(path);
lines[0] = "test01";
File.WriteAllLines(path, lines);
That's much simpler code to do the same thing.
The half-way house between the two would be to use File.OpenText (to return a StreamWriter) and File.CreateText (to return a StreamWriter). There's no need to do the wrapping yourself.
I'm running a test where i need to validate data from a linux file. I've defined the path of the file is located (see below). Once i cat the file to read the data contents (irm_dwge_stt_l__xxxx.csv.ovr) how can i validate the data within this file
Also where i have defined the measurementName where can i define what measurements belong within this.
public string validateMeasurement(string measurementName, string domaianName)
{
var processFilePath = "/inputs/ff/ff/actuals/" + measurementName + ".csv.ovr";
var actualItemData = Common.LinuxCommandExecutor.RunLinuxcommand("cat " + processFilePath);
return actualItemData;
}
One way of reading data in C# is to use File.Open.
Running cat and capturing the output is probably not the way to go.
This C# example from https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/file-system/how-to-read-a-text-file-one-line-at-a-time shows you how to read a file line by line.
You can then compare the file line by line to whatever data you are validating against.
Notice, this will probably only works if you are trying to validate a text file.
int counter = 0;
string line;
// Read the file and display it line by line.
System.IO.StreamReader file =
new System.IO.StreamReader(#"c:\test.txt");
while((line = file.ReadLine()) != null)
{
System.Console.WriteLine (line);
counter++;
}
file.Close();
System.Console.WriteLine("There were {0} lines.", counter);
// Suspend the screen.
System.Console.ReadLine();
string curetn = Environment.CurrentDirectory;
string path = curetn.ToString() + #"\DATA\SaveGame.txt";
Console.WriteLine(path);
TextReader tr = new StreamReader(path);
Hello, I am making a text-adventure, and I do not like having all my save files, and mp3 file in the same place as my application. I would like for the files to be in a folder. I want to be able to use StreamWriter and StreamReader, to be able to write and read files that are in a folder. This file is also in a distributable folder, not just in the Visual Studios Projects folders. I have tried everything I can, and this is what I have. I also have one of these for StreamWriter. Please help!
Edit:
The thing that does not work, is that it does not read the lines, and assigns them to a variable. I have it in a try-catch, and it catches, and displays the error message that I wrote.
If you are looking for simply read and write lines from file you can try this
using (StreamReader sr = new StreamReader(path))
{
while (!sr.EndOfStream)
{
sr.ReadLine();
}
}
string s;
using (StreamWriter sw = new StreamWriter(path))
{
sw.WriteLine(s);
}
So basically what you want to do is read the text file:
string data[] = File.ReadAllLines(path); // Read the text file.
var x = data[1]; // Replace the '1' with the line number you want.
Console.WriteLine(x);
This is a good way to read the text file, I think it's better than opening a stream.
You can also write to it, so every time you want to save, just do this:
// When you want to write:
File.WriteAllText(path, "");
File.AppendAllText(path, "Add a data line" + Environment.NewLine); // Environment.NewLine adds a line.
Keep appending text to the file for the data you need.
This question already has answers here:
How to copy a file to another path?
(10 answers)
Closed 8 years ago.
I'm creating a C# code that is required to read a text file line by line and then copy each line onto a new text file. I was able to figure out how to read line by line, but I'm having trouble copying line by line to the new text file I created.
This is what I am using to read my original text file line by line:
int counter = 0;
string line;
// Read the file and display it line by line.
System.IO.StreamReader file = new System.IO.StreamReader(#"c:\AnswerFile.txt");
while ((line = file.ReadLine()) != null)
{
System.Console.WriteLine(line);
counter++;
}
file.Close();
System.Console.WriteLine("There were {0} lines.", counter);
// Suspend the screen.
System.Console.ReadLine();
Any help is appreciated! Thank you
EDIT: I did not forget to write the code that copies the text onto another text file. That is the part I am having trouble with. I tried using streamwriter while specifying the directory of the file I want the text to go to, but something wasn't right. I want to create a code that literally reads line by line from one text file and copies line by line (as it reads from the initial file) to the new text file. I hope that clarifies my question.
EDIT2: Figured it out guys. Thank you for all the help! I had to call my company's security department to grant me access to write in the c drive.
int counter = 0;
string line;
try
{
// Read the file and display it line by line.
using (System.IO.StreamReader file = new System.IO.StreamReader(#"C:\\AnswerFile.txt"))
{
using (System.IO.StreamWriter fileWriter = new System.IO.StreamWriter(#"C:\outputFile.txt"))
{
while ((line = file.ReadLine()) != null)
{
System.Console.WriteLine(line);
fileWriter.WriteLine(line);
counter++;
}
}
}
System.Console.WriteLine("There were {0} lines.", counter);
// Suspend the screen.
System.Console.ReadLine();
}
catch (System.IO.IOException ex)
{
// Handle the Error Properly Here
}
Updated answer in response to comments about missing exception handling and closing of File handles in case of error.
I am reading text file with StreamReader and doing Regex.Match to find specific info, now when I found it I want to replace it with Regex.Replace and I want to write this replacement back to the file.
this is text inside my file:
///
/// <Command Name="Press_Button" Comment="Press button" Security="Security1">
///
/// <Command Name="Create_Button" Comment="Create button" Security="Security3">
/// ... lots of other Commands
now I need to find : Security="Security3"> in Create_Button command, change it to Security="Security2"> and write it back to the file
do {
// read line by line
string ReadLine = InfoStreamReader.ReadLine();
if (ReadLine.Contains("<Command Name"))
{
// now I need to find Security1, replace it with Security2 and write back to the file
}
}
while (!InfoStreamReader.EndOfStream);
any ideas are welcome...
EDITED:
Good call was from tnw to read and write to the file line by line. Need an example.
I'd do something more like this. You can't directly write to a line in the file like you're describing there.
This doesn't use regex but accomplishes the same thing.
var fileContents = System.IO.File.ReadAllText(#"<File Path>");
fileContents = fileContents.Replace("Security1", "Security2");
System.IO.File.WriteAllText(#"<File Path>", fileContents);
Pulled pretty much directly from here: c# replace string within file
Alternatively, you could loop thru and read your file line-by-line and write it line-by-line to a new file. For each line, you could check for Security1, replace it, and then write it to the new file.
For example:
StringBuilder newFile = new StringBuilder();
string temp = "";
string[] file = File.ReadAllLines(#"<File Path>");
foreach (string line in file)
{
if (line.Contains("Security1"))
{
temp = line.Replace("Security1", "Security2");
newFile.Append(temp + "\r\n");
continue;
}
newFile.Append(line + "\r\n");
}
File.WriteAllText(#"<File Path>", newFile.ToString());
Source: how to edit a line from a text file using c#