I've written a program that reads a text file into a variable, does a regex replace on the text, and writes it back to the file. Obviously this is not scalable for large text files; I want to be able to read the text file line-by-line and do a regex replace for a desired pattern.
Here is my non-scalable code:
static void Main(string[] args) {
var fileContents = System.IO.File.ReadAllText("names.txt");
string pattern = "Ali";
string rep = "Tyson";
Regex rgx = new Regex(pattern);
fileContents = rgx.Replace(fileContents, rep);
System.IO.File.WriteAllText("names.txt", fileContents);}
I know how to use StreamReader for reading a file line-by-line but when I tried nest StreamWriter inside of StreamReader so I could write to the file while searching line-by-line I ran into an unhandled exception error.
Does anyone know how to solve this?
You could try this,
using (var input = File.OpenText("input.txt"))
using (var output = new StreamWriter("output.txt")) {
string line;
while (null != (line = input.ReadLine()) {
// Apply regex to line before writing to new outpu file
output.WriteLine(line);
}
}
Once you finish reading and writing all lines to output.txt you could replace input.txt with output.txt.
Related
I was looking to append text to a exact location in a text file. I have used StreamReader to find the text in the file I am looking for. I thought about using StreamWriter but that obviously doesn't make sense. I was hoping to find some "append" method in some class somewhere that would help me do this but with now success. Or is there a better way to do this than to use StreamReader?
using (StreamReader sr = new StreamReader(fileName))
{
string line;
while ((line = sr.ReadLine()) != null)
{
if (line.Contains("VAR_GLOBAL CONSTANT"))
{
//append text before this variable
// e.g. (*VAR_GLOBAL CONSTANT
// append the (* before VAR_GLOBAL CONSTANT
}
if (line.Contains("END_VAR"))
{
//append text after this variable
// e.g. END_VAR*)
// append the *) after END_VAR
}
}
}
Does anyone have any thoughts on how to accomplish this?
One way to do it would be to read the file contents into a string, update the contents locally, and then write it back to the file again. This probably isn't very feasible for really large files, especially if the appending is done at the end, but it's a start:
var filePath = #"f:\public\temp\temp.txt";
var appendBeforeDelim = "VAR_GLOBAL CONSTANT";
var appendAfterDelim = "END_VAR";
var appendBeforeText = "Append this string before some text";
var appendAfterText = "Append this string after some text";
var newFileContents = File.ReadAllText(filePath)
.Replace(appendBeforeDelim, $"{appendBeforeText}{appendBeforeDelim}")
.Replace(appendAfterDelim, $"{appendAfterDelim}{appendAfterText}");
File.WriteAllText(filePath, newFileContents);
What is the quickest way to read a text file into a string variable?
I understand it can be done in several ways, such as read individual bytes and then convert those to string. I was looking for a method with minimal coding.
How about File.ReadAllText:
string contents = File.ReadAllText(#"C:\temp\test.txt");
A benchmark comparison of File.ReadAllLines vs StreamReader ReadLine from C# file handling
Results. StreamReader is much faster for large files with 10,000+
lines, but the difference for smaller files is negligible. As always,
plan for varying sizes of files, and use File.ReadAllLines only when
performance isn't critical.
StreamReader approach
As the File.ReadAllText approach has been suggested by others, you can also try the quicker (I have not tested quantitatively the performance impact, but it appears to be faster than File.ReadAllText (see comparison below)). The difference in performance will be visible only in case of larger files though.
string readContents;
using (StreamReader streamReader = new StreamReader(path, Encoding.UTF8))
{
readContents = streamReader.ReadToEnd();
}
Comparison of File.Readxxx() vs StreamReader.Readxxx()
Viewing the indicative code through ILSpy I have found the following about File.ReadAllLines, File.ReadAllText.
File.ReadAllText - Uses StreamReader.ReadToEnd internally
File.ReadAllLines - Also uses StreamReader.ReadLine internally with the additionally overhead of creating the List<string> to return as the read lines and looping till the end of file.
So both the methods are an additional layer of convenience built on top of StreamReader. This is evident by the indicative body of the method.
File.ReadAllText() implementation as decompiled by ILSpy
public static string ReadAllText(string path)
{
if (path == null)
{
throw new ArgumentNullException("path");
}
if (path.Length == 0)
{
throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
}
return File.InternalReadAllText(path, Encoding.UTF8);
}
private static string InternalReadAllText(string path, Encoding encoding)
{
string result;
using (StreamReader streamReader = new StreamReader(path, encoding))
{
result = streamReader.ReadToEnd();
}
return result;
}
string contents = System.IO.File.ReadAllText(path)
Here's the MSDN documentation
For the noobs out there who find this stuff fun and interesting, the fastest way to read an entire file into a string in most cases (according to these benchmarks) is by the following:
using (StreamReader sr = File.OpenText(fileName))
{
string s = sr.ReadToEnd();
}
//you then have to process the string
However, the absolute fastest to read a text file overall appears to be the following:
using (StreamReader sr = File.OpenText(fileName))
{
string s = String.Empty;
while ((s = sr.ReadLine()) != null)
{
//do what you have to here
}
}
Put up against several other techniques, it won out most of the time, including against the BufferedReader.
Take a look at the File.ReadAllText() method
Some important remarks:
This method opens a file, reads each line of the file, and then adds
each line as an element of a string. It then closes the file. A line
is defined as a sequence of characters followed by a carriage return
('\r'), a line feed ('\n'), or a carriage return immediately followed
by a line feed. The resulting string does not contain the terminating
carriage return and/or line feed.
This method attempts to automatically detect the encoding of a file
based on the presence of byte order marks. Encoding formats UTF-8 and
UTF-32 (both big-endian and little-endian) can be detected.
Use the ReadAllText(String, Encoding) method overload when reading
files that might contain imported text, because unrecognized
characters may not be read correctly.
The file handle is guaranteed to be closed by this method, even if
exceptions are raised
string text = File.ReadAllText("Path"); you have all text in one string variable. If you need each line individually you can use this:
string[] lines = File.ReadAllLines("Path");
System.IO.StreamReader myFile =
new System.IO.StreamReader("c:\\test.txt");
string myString = myFile.ReadToEnd();
if you want to pick file from Bin folder of the application then you can try following and don't forget to do exception handling.
string content = File.ReadAllText(Path.Combine(System.IO.Directory.GetCurrentDirectory(), #"FilesFolder\Sample.txt"));
#Cris sorry .This is quote MSDN Microsoft
Methodology
In this experiment, two classes will be compared. The StreamReader and the FileStream class will be directed to read two files of 10K and 200K in their entirety from the application directory.
StreamReader (VB.NET)
sr = New StreamReader(strFileName)
Do
line = sr.ReadLine()
Loop Until line Is Nothing
sr.Close()
FileStream (VB.NET)
Dim fs As FileStream
Dim temp As UTF8Encoding = New UTF8Encoding(True)
Dim b(1024) As Byte
fs = File.OpenRead(strFileName)
Do While fs.Read(b, 0, b.Length) > 0
temp.GetString(b, 0, b.Length)
Loop
fs.Close()
Result
FileStream is obviously faster in this test. It takes an additional 50% more time for StreamReader to read the small file. For the large file, it took an additional 27% of the time.
StreamReader is specifically looking for line breaks while FileStream does not. This will account for some of the extra time.
Recommendations
Depending on what the application needs to do with a section of data, there may be additional parsing that will require additional processing time. Consider a scenario where a file has columns of data and the rows are CR/LF delimited. The StreamReader would work down the line of text looking for the CR/LF, and then the application would do additional parsing looking for a specific location of data. (Did you think String. SubString comes without a price?)
On the other hand, the FileStream reads the data in chunks and a proactive developer could write a little more logic to use the stream to his benefit. If the needed data is in specific positions in the file, this is certainly the way to go as it keeps the memory usage down.
FileStream is the better mechanism for speed but will take more logic.
well the quickest way meaning with the least possible C# code is probably this one:
string readText = System.IO.File.ReadAllText(path);
you can use :
public static void ReadFileToEnd()
{
try
{
//provide to reader your complete text file
using (StreamReader sr = new StreamReader("TestFile.txt"))
{
String line = sr.ReadToEnd();
Console.WriteLine(line);
}
}
catch (Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
string content = System.IO.File.ReadAllText( #"C:\file.txt" );
You can use like this
public static string ReadFileAndFetchStringInSingleLine(string file)
{
StringBuilder sb;
try
{
sb = new StringBuilder();
using (FileStream fs = File.Open(file, FileMode.Open))
{
using (BufferedStream bs = new BufferedStream(fs))
{
using (StreamReader sr = new StreamReader(bs))
{
string str;
while ((str = sr.ReadLine()) != null)
{
sb.Append(str);
}
}
}
}
return sb.ToString();
}
catch (Exception ex)
{
return "";
}
}
Hope this will help you.
you can read a text from a text file in to string as follows also
string str = "";
StreamReader sr = new StreamReader(Application.StartupPath + "\\Sample.txt");
while(sr.Peek() != -1)
{
str = str + sr.ReadLine();
}
I made a comparison between a ReadAllText and StreamBuffer for a 2Mb csv and it seemed that the difference was quite small but ReadAllText seemed to take the upper hand from the times taken to complete functions.
I'd highly recommend using the File.ReadLines(path) compare to StreamReader or any other File reading methods. Please find below the detailed performance benchmark for both small-size file and large-size file.
I hope this would help.
File operations read result:
For small file (just 8 lines)
For larger file (128465 lines)
Readlines Example:
public void ReadFileUsingReadLines()
{
var contents = File.ReadLines(path);
}
Note : Benchmark is done in .NET 6.
This comment is for those who are trying to read the complete text file in winform using c++ with the help of C# ReadAllText function
using namespace System::IO;
String filename = gcnew String(charfilename);
if(System::IO::File::Exists(filename))
{
String ^ data = gcnew String(System::IO::File::RealAllText(filename)->Replace("\0", Environment::Newline));
textBox1->Text = data;
}
I can currently remove the last line of a text file using:
var lines = System.IO.File.ReadAllLines("test.txt");
System.IO.File.WriteAllLines("test.txt", lines.Take(lines.Length - 1).ToArray());
Although, how is it possible to instead remove the beginning of the text file?
Instead of lines.Take, you can use lines.Skip, like:
var lines = File.ReadAllLines("test.txt");
File.WriteAllLines("test.txt", lines.Skip(1).ToArray());
to truncate at the beginning despite the fact that the technique used (read all text and write everything back) is very inefficient.
About the efficient way: The inefficiency comes from the necessity to read the whole file into memory. The other way around could easily be to seek in a stream and copy the stream to another output file, delete the original, and rename the old. That one would be equally fast and yet consume much less memory.
Truncating a file at the end is much easier. You can just find the trunaction position and call FileStream.SetLength().
Here is an alternative:
using (var stream = File.OpenRead("C:\\yourfile"))
{
var items = new LinkedList<string>();
using (var reader = new StreamReader(stream))
{
reader.ReadLine(); // skip one line
string line;
while ((line = reader.ReadLine()) != null)
{
//it's far better to do the actual processing here
items.AddLast(line);
}
}
}
Update
If you need an IEnumerable<string> and don't want to waste memory you could do something like this:
public static IEnumerable<string> GetFileLines(string filename)
{
using (var stream = File.OpenRead(filename))
{
using (var reader = new StreamReader(stream))
{
reader.ReadLine(); // skip one line
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
}
static void Main(string[] args)
{
foreach (var line in GetFileLines("C:\\yourfile.txt"))
{
// do something with the line here.
}
}
var lines = System.IO.File.ReadAllLines("test.txt");
System.IO.File.WriteAllLines("test.txt", lines.Skip(1).ToArray());
Skip eliminates the given number of elements from the beginning of the sequence. Take eliminates all but the given number of elements from the end of the sequence.
To remove fist line from a text file
System.IO.StreamReader file = new System.IO.StreamReader(filePath);
string data = file.ReadToEnd();
file.Close();
data = Regex.Replace(data, "<.*\n", "");
System.IO.StreamWriter file = new System.IO.StreamWriter(filePath, false);
file.Write(data);
file.Close();
can do in one line also
File.WriteAllLines(origialFilePath,File.ReadAllLines(originalFilePath).Skip(1));
Assuming you are passing your filePath as parameter to the function.
I have code that reads a file and then converts it to a string, the string is then written to a new file, although could someone demonstrate how to append this string to the destination file (rather than overwriting it)
private static void Ignore()
{
System.IO.StreamReader myFile =
new System.IO.StreamReader("c:\\test.txt");
string myString = myFile.ReadToEnd();
myFile.Close();
Console.WriteLine(myString);
// Write the string to a file.
System.IO.StreamWriter file = new System.IO.StreamWriter("c:\\test2.txt");
file.WriteLine(myString);
file.Close();
}
If the file is small, you can read and write in two code lines.
var myString = File.ReadAllText("c:\\test.txt");
File.AppendAllText("c:\\test2.txt", myString);
If the file is huge, you can read and write line-by-line:
using (var source = new StreamReader("c:\\test.txt"))
using (var destination = File.AppendText("c:\\test2.txt"))
{
var line = source.ReadLine();
destination.WriteLine(line);
}
using(StreamWriter file = File.AppendText(#"c:\test2.txt"))
{
file.WriteLine(myString);
}
Use File.AppendAllText
File.AppendAllText("c:\\test2.txt", myString)
Also to read it, you can use File.ReadAllText to read it. Otherwise use a using statement to Dispose of the stream once you're done with the file.
Try
StreamWriter writer = File.AppendText("C:\\test.txt");
writer.WriteLine(mystring);
Notepad:
Hello world!
How I'll put it in C# and convert it into string..?
So far, I'm getting the path of the notepad.
string notepad = #"c:\oasis\B1.text"; //this must be Hello world
Please advice me.. I'm not familiar on this.. tnx
You can read text using the File.ReadAllText() method:
public static void Main()
{
string path = #"c:\oasis\B1.txt";
try {
// Open the file to read from.
string readText = System.IO.File.ReadAllText(path);
Console.WriteLine(readText);
}
catch (System.IO.FileNotFoundException fnfe) {
// Handle file not found.
}
}
You need to read the content of the file, e.g.:
using (var reader = new StreamReader(new FileStream(path, FileMode.Open, FileAccess.Read))
{
return reader.ReadToEnd();
}
Or, as simply as possible:
return File.ReadAllText(path);
make use of StreamReader and read the file as shown below
string notepad = #"c:\oasis\B1.text";
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(notepad))
{
while (sr.Peek() >= 0)
{
sb.Append(sr.ReadLine());
}
}
string s = sb.ToString();
Use File.ReadAllText
string text_in_file = File.ReadAllText(notepad);
check this example:
// Read the file as one string.
System.IO.StreamReader myFile =
new System.IO.StreamReader("c:\\test.txt");
string myString = myFile.ReadToEnd();
myFile.Close();
// Display the file contents.
Console.WriteLine(myString);
// Suspend the screen.
Console.ReadLine();
Reading From a Text File (Visual C#), in this example # is not used when StreamReader is being called, however when you write the code in Visual Studio it will give the below error for each \
Unrecognized escape sequence
To escape this error you can write # before " that is at the beginning of your path string.
I shoul also mentioned that it does not give this error if we use \\ even if we do not write #.
// Read the file as one string.
System.IO.StreamReader myFile = new System.IO.StreamReader(#"c:\oasis\B1.text");
string myString = myFile.ReadToEnd();
myFile.Close();
// Display the file contents.
Console.WriteLine(myString);
// Suspend the screen.
Console.ReadLine();