i just cant find a clean explanation on how to read a text file, line by line in Windows RT ( for Windows 8 Store).
Lets say i have a folder: MyFolder/Notes.txt
And i want to read the data from Notes.txt and add it to an array of strings.
How do i read/write from that file? I was using StreamReader before, but now it is very confusing. And the dev samples dont help that much.
Ive managed to find the answer myself. Thanks for the help.
// READ FILE
public async void ReadFile()
{
// settings
var path = #"MyFolder\MyFile.txt";
var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
// acquire file
var file = await folder.GetFileAsync(path);
var readFile = await Windows.Storage.FileIO.ReadLinesAsync(file);
foreach (var line in readFile)
{
Debug.WriteLine("" + line.Split(';')[0]);
}
}
MyFile.txt has:
Test1;Description1;
Test2;Description2;
//Output for ReadFile()
Test1
Test2
You don't have to use File.ReadLines. You try an implementation like this if you prefer:
using (StreamReader reader = new StreamReader("notes.txt"))
{
while (reader.Peek() >= 0)
{
Console.WriteLine(reader.ReadLine());
}
}
foreach (var line in File.ReadLines("MyFolder/Notes.txt"))
{
...
}
reads the file line by line. This is different from File.ReadAllLines which reads the entire file at once.
If you want to read everything at once, into an array, use the latter.
Related
Im writing this in C#, I need my program to read a (large) XML file, search for a specific word ('Implements') and then delete every line where this word is present. But a bit confused as to how to go about it. This is what I have so far. Does anyone know what to use instead of what Im hoping 'Deleteline' would do, Im very new to coding. thanks!
using System;
using System.Xml;
namespace XMLReadAndParse
{
class XMLReadandParse
{
static void Main(string[] args)
{
string result = string.Empty;
var lines = File.ReadAllLines("CaxtonFx.FirebirdApi.xml");
foreach (var line in lines)
{
if(line.Contains("Implements"))
{
var text = line.Contains("Implements");
result = text.Deleteline(); //I know this doesn't work but not sure how to proceed
}
}
Console.WriteLine(result);
Console.ReadLine();
}
}
}
As far as I know, this is not possible. You cannot delete lines from the file you are reading.
You can however, create a new file, write the lines you need to the new file, delete the original file, and rename the new file to the old file.
I wrote a small and simple example using your code above, I have also tested it for you. All passed my side :)
var originalFile = "CaxtonFx.FirebirdApi.xml";
var tempFile = "TempXmlFile.xml";
var file = File.Create(tempFile);
file.Close();
var lines = File.ReadAllLines(originalFile);
var newLines = new List<string>();
foreach (var line in lines)
{
if (!line.Contains("Implements"))
{
newLines.Add(line);
}
}
File.WriteAllText(tempFile, String.Join(Environment.NewLine, newLines));
File.Delete(originalFile);
File.Move(tempFile, originalFile);
Let me know if you need me to clarify anything.
Happy coding!
So, let's say i have a text file with 20 lines, with on each line different text.
i want to be able to have a string that has the first line in it, but when i do NextLine(); i want it to be the next line. I tried this but it doesn't seem to work:
string CurrentLine;
int LastLineNumber;
Void NextLine()
{
System.IO.StreamReader file = new System.IO.StreamReader("c:\\test.txt");
CurrentLine = file.ReadLine(LastLineNumber + 1);
LastLineNumber++;
}
How would i be able to do this?
Thanks in advance.
In general, it would be better if you could design this in a way to leave your file open, and not try to reopen the file each time.
If that is not practical, you'll need to call ReadLine multiple times:
string CurrentLine;
int LastLineNumber;
void NextLine()
{
// using will make sure the file is closed
using(System.IO.StreamReader file = new System.IO.StreamReader("c:\\test.txt"))
{
// Skip lines
for (int i=0;i<LastLineNumber;++i)
file.ReadLine();
// Store your line
CurrentLine = file.ReadLine();
LastLineNumber++;
}
}
Note that this can be simplified via File.ReadLines:
void NextLine()
{
var lines = File.ReadLines("C:\\test.txt");
CurrentLine = lines.Skip(LastLineNumber).First();
LastLineNumber++;
}
One simple call should do it:
var fileLines = System.IO.File.ReadAllLines(fileName);
You will want to validate the file exists and of course you still need to watch for blank lines or invalid values but that should give you the basics. To loop over the file you can use the following:
foreach (var singleLine in fileLines) {
// process "singleLine" here
}
One more note - you won't want to do this with large files since it processes everything in memory.
Well, if you really don't mind re-opening the file each time, you can use:
CurrentLine = File.ReadLines("c:\\test.txt").Skip(LastLineNumber).First();
LastLineNumber++;
However, I'd advise you to just read the whole thing in one go using File.ReadAllLines, or perhaps File.ReadLines(...).ToList().
The ReadLine method already reads the next line in the StreamReader, you don't need the counter, or your custom function for that matter. Just keep reading until you reach your 20 lines or until the file ends.
You can't pass a line number to ReadLine and expect it to find that particular line. If you look at the ReadLine documentation, you'll see it doesn't accept any parameters.
public override string ReadLine()
When working with files, you must treat them as streams of data. Every time you open the file, you start at the very first byte/character of the file.
var reader = new StreamReader("c:\\test.txt"); // Starts at byte/character 0
You have to keep the stream open if you want to read more lines.
using (var reader = new StreamReader("c:\\test.txt"))
{
string line1 = reader.ReadLine();
string line2 = reader.ReadLine();
string line3 = reader.ReadLine();
// etc..
}
If you really want to write a method NextLine, then you need to store the created StreamReader object somewhere and use that every time. Somewhat like this:
public class MyClass : IDisposable
{
StreamReader reader;
public MyClass(string path)
{
this.reader = new StreamReader(path);
}
public string NextLine()
{
return this.reader.ReadLine();
}
public void Dispose()
{
reader.Dispose();
}
}
But I suggest you either loop through the stream:
using (var reader = new StreamReader("c:\\test.txt"))
{
while (some_condition)
{
string line = reader.ReadLine();
// Do something
}
}
Or get all the lines at once using the File class ReadAllLines method:
string[] lines = System.IO.File.ReadAllLines("c:\\test.txt");
for (int i = 0; i < lines.Length; i++)
{
string line = lines[i];
// Do something
}
In my application there is a situation like this.Before creating a file, my application search for files in a directory under a particular filename. If any file/files found, then it should read each files contents and write these contents(of each file) to a new file. I have googled many and tried some like this:
string temp_file_format = "ScriptLog_" + DateTime.Now.ToString("dd_MM_yyyy_HH");
string[] files = Directory.GetFiles(path,temp_file_format);
foreach (FileAccess finfo in files)
{
string text = File.ReadAllText(finfo);
}
and
System.IO.DirectoryInfo dir = new DirectoryInfo(path);
System.IO.FileInfo[] files = dir.GetFiles(temp_file_format);
foreach (FileInfo finfo in files)
{
finfo.OpenRead();
}
But all these failed..Can anyone show me an alternative for this?
Is there anything wrong in my temp_file_format string?
It will be nice if I could prepend these contents to the new file. Else also, no worries..
any help would be really appreciated..
This is a compete working implementation that does all of that
without reading everything in memory at one time (which doesn't work for large files)
without keeping any files open for more than the required time
using System.IO;
using System.Linq;
public static class Program {
public static void Main()
{
var all = Directory.GetFiles("/tmp", "*.cpp")
.SelectMany(File.ReadAllLines);
using (var w = new StreamWriter("/tmp/output.txt"))
foreach(var line in all)
w.WriteLine(line);
}
}
I tested it on mono 2.10, and it should work on any .NET 4.0+ (for File.ReadAllLines which is a lazy linewise enumerable)
Here's a short snippet that reads all the files and out puts them to the path outputPath
var lines = from file in Directory.GetFiles(path,temp_file_format)
from line in File.ReadAllLines(file)
select line;
File.WriteAllLines(outputPath, content);
The problem you are having with your code is not really related to reading files but simply trying to use an object as a type it's not. Directory.GetFiles returns an array of string and File.ReadXXX and File.OpenRead expects the path as a string. So you simply need to pass each of the strings returned as the path argument to the appropriate method. The above is one such example. Hope it helps both solve your problem and explain the actually issue with your code
try this:
foreach (FileInfo finfo in files)
{
try
{
using (StreamReader sr = new StreamReader("finfo "))
{
String line = sr.ReadToEnd();
Console.WriteLine(line);
}
}
catch (Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
using (var output = File.Create(outputPath))
{
foreach (var file in Directory.GetFiles(InputPath,temp_file_format))
{
using (var input = File.OpenRead(file))
{
input.CopyTo(output);
}
}
}
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;
}
In C#, I'm reading a moderate size of file (100 KB ~ 1 MB), modifying some parts of the content, and finally writing to a different file. All contents are text. Modification is done as string objects and string operations. My current approach is:
Read each line from the original file by using StreamReader.
Open a StringBuilder for the contents of the new file.
Modify the string object and call AppendLine of the StringBuilder (until the end of the file)
Open a new StreamWriter, and write the StringBuilder to the write stream.
However, I've found that StremWriter.Write truncates 32768 bytes (2^16), but the length of StringBuilder is greater than that. I could write a simple loop to guarantee entire string to a file. But, I'm wondering what would be the most efficient way in C# for doing this task?
To summarize, I'd like to modify only some parts of a text file and write to a different file. But, the text file size could be larger than 32768 bytes.
== Answer == I'm sorry to make confusin to you! It was just I didn't call flush. StremWriter.Write does not have a short (e.g., 2^16) limitation.
StreamWriter.Write
does not
truncate the string and has no limitation.
Internally it uses String.CopyTo which on the other hand uses unsafe code (using fixed) to copy chars so it is the most efficient.
The problem is most likely related to not closing the writer. See http://msdn.microsoft.com/en-us/library/system.io.streamwriter.flush.aspx.
But I would suggest not loading the whole file in memory if that can be avoided.
can you try this :
void Test()
{
using (var inputFile = File.OpenText(#"c:\in.txt"))
{
using (var outputFile = File.CreateText(#"c:\out.txt"))
{
string current;
while ((current = inputFile.ReadLine()) != null)
{
outputFile.WriteLine(Process(current));
}
}
}
}
string Process(string current)
{
return current.ToLower();
}
It avoid to have to full file loaded in memory, by processing line by line and writing it directly
Well, that entirely depends on what you want to modify. If your modifications of one part of the text file are dependent on another part of the text file, you obviously need to have both of those parts in memory. If however, you only need to modify the text file on a line-by-line basis then use something like this :
using (StreamReader sr = new StreamReader(#"test.txt"))
{
using (StreamWriter sw = new StreamWriter(#"modifiedtest.txt"))
{
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
//do some modifications
sw.WriteLine(line);
sw.Flush(); //force line to be written to disk
}
}
}
Instead of of running though the hole dokument i would use a regex to find what you are looking for Sample:
public List<string> GetAllProfiles()
{
List<string> profileNames = new List<string>();
using (StreamReader reader = new StreamReader(_folderLocation + "profiles.pg"))
{
string profiles = reader.ReadToEnd();
var regex = new Regex("\nname=([^\r]{0,})", RegexOptions.IgnoreCase);
var regexMatchs = regex.Matches(profiles);
profileNames.AddRange(from Match regexMatch in regexMatchs select regexMatch.Groups[1].Value);
}
return profileNames;
}