Code:
using System;
using System.IO;
namespace TimeTress
{
class Program
{
static void Main(string[] args)
{
GetString("../../../../timeline.csv");
GetString("../../../../people.csv");
}
static void GetString(string path)
{
if (File.Exists(path))
{
foreach (var line in File.ReadAllLines(path))
{
Console.WriteLine(line);
}
}
else
{
Console.WriteLine($"Файл не найден по пути {Path.GetFullPath(path)}");
}
}
}
}
It is necessary that the result should not be simply displayed, but written into two different variables, preferably into the arrays string [] [] or string [], so that you can work with them in the future. File text: timeline: {event_date}; {event_description} people: {Name}; {Date of Birth}; {Date of death}
Change the method's return type to string[] or List<string> (if you don't know the difference, use Google)
then, instead of:
Console.WriteLine(line);
create a list and add lines to it:
List<string> result = new ListString();
foreach (var line in File.ReadAllLines(path))
{
result.Add(line);
}
return line; // or `lines.ToArray()`, if your return type is `string[]`
Now you need to think about the return value when the file does not exist. One option would be returning null. But that's not good and forces the users (of the method, I mean, the programmers) to check for null result whenever the method is called. A better option in my opinion is not checking for the existence of the file. Yes, you heard me right. Let the FileNotFoundException be thrown.
For more elaborate ways of processing the CSV file and parsing fields, consult other posts on the internet, including the ones available in StackOverflow
First, the variable(s) need to be defined before a value can be assigned to the variable(s). This variable definition is done using a statement similar to the following:
string[] stringArray;
After defining a variable, it is possible to assign values to the intended variable(s), as shown below:
stringArray = new string[] { "message one", "message two" };
Building upon this, if one would like to read through the lines in a text file, assign the lines to an array of strings, and then return a variable containing that array of strings, the following function would be one way to accomplish this:
static string[] GetListOfStringsFromTextFile(string filePath)
{
string[] stringArray;
if (File.Exists(filePath))
{
// ReadAllLines() already returns a string array. No need to loop.
stringArray = File.ReadAllLines(filePath);
}
else
{
// If file not found, return empty string array as default.
stringArray = new string[0];
}
return stringArray;
}
Related
I got stuck writing some simple program which writes some data to the text file and reads them form this file later.
I have a function that writes lines to a txt file; each line contains Name, Surname, and Idnumber.
And below I have a function that reads the data from that file.
I want to separate Name, Surname and Idnumber so below code seems to be correct but during debugging I got a message "An unhandled exception of type 'System.NullReferenceException' occurred" for this line:
string[] tabstring = myString.Split(' ', ' ');.
I created the tab string which contains 3 elements - each for each word in the line i.e. tabstring[0]=Name and so on.
The while loop is to do it for each line in the text file. But something is wrong.
public void ReadFromFile()
{
FileStream fsListOfObjects = new FileStream("C:\\Users\\Dom\\Desktop\\ListOfObjects.txt",
FileMode.Open);
StreamReader srListOfObjects = new StreamReader(fsListOfObjects);
while (srListOfObjects.ReadLine() != null)
{
string myString= (srListOfObjects.ReadLine();
Console.WriteLine(myString);
**string[] tabstring = myString.Split(' ', ' ');**
Name = tabstring[0];
Surname = tabstring[1];
Id= long.Parse(tabstring[2]);
ClassName object= new ClassName(Name, Surname, Id);
myList.Add(object);
}
srListOfObjects.Close();
Console.ReadLine();
}
And here is what the text file looks like:
Ann Brown 1233456789
Bruce Willis 098987875
Bill Gates 789678678
and so on...
I would appreciate your comments on the described problem.
while (srListOfObjects.ReadLine().. reads a line but doesn't save it into a variable. string myString= (srListOfObjects.ReadLine()) reads another line.
Use while (!srListOfObjects.EndOfStream) to check for the end of the stream: StreamReader.EndOfStream Property.
Also, it is a good idea to check that the correct number of parts of the string were obtained by the Split - it guards against things like lines with only whitespace.
Things like StreamReaders need have .Dispose() called on them to clear up "unmanaged resources" - an easy way to do that which will work even if the program crashes is to use the using statement.
If you make the ReadFromFile method into a function instead of a void then you can avoid (no pun) using a global variable for the data. Global variables are not necessarily a problem, but it's usually good to avoid them.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace ConsoleApp1
{
public class ClassName
{
public string Name { get; set; }
public string Surname { get; set; }
public long Id { get; set; }
}
class Program
{
public static List<ClassName> ReadFromFile(string fileName)
{
var result = new List<ClassName>();
using (var sr = new StreamReader(fileName))
{
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
var parts = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Count() == 3)
{
result.Add(new ClassName
{
Name = parts[0],
Surname = parts[1],
Id = long.Parse(parts[2])
});
}
}
}
return result;
}
static void Main(string[] args)
{
string myFile = #"C:\temp\namesList.txt";
var theList = ReadFromFile(myFile);
foreach(var c in theList)
{
Console.WriteLine($"{c.Id} - {c.Surname}, {c.Name}");
}
Console.ReadLine();
}
}
}
outputs:
1233456789 - Brown, Ann
98987875 - Willis, Bruce
789678678 - Gates, Bill
Your problem is here:
while (srListOfObjects.ReadLine() != null)
{
string myString= (srListOfObjects.ReadLine();
You are entering the loop on the condition that srListOfObjects.ReadLine() returns something other than null but then you are immediately reading a new line form srListOfObjects and storing the returned reference in myString. This has obviously two problems:
The second call to ReadLine can return null and you are not checking if it is. The error you are getting is due to this reason.
You are losing information. You are ignoring the line you are reading when checking the while condition. Until your program crashes or runs to the end (depends on wether the input file has even or odd number of lines), you will process only half of the data.
Update:
You should only read one line per iteration. One way to do it is declaring and initializing myString before entering the loop and updating it on every iteration:
var myString = srListOfObjects.ReadLine();
while (myString != null)
{
//do your stuff
myString = srListOfObjects.ReadLine();
}
https://learn.microsoft.com/en-us/dotnet/api/system.io.streamreader.readline?view=netcore-3.1
ReadLine() - Reads a line of characters from the current stream and returns the data as a string.
In your code you do a null check, but then call ReadLine again. When you hit the last line, you will get a NULL string, and splitting that will fail with the NULL ref
I was trying to create a list from a user input with something like this:
Create newlist: word1, word2, word3, etc...,
but how do I get those words one by one only by using commas as references going through them (in order) and placing them into an Array etc? Example:
string Input = Console.ReadLine();
if (Input.Contains("Create new list:"))
{
foreach (char character in Input)
{
if (character == ',')//when it reach a comma
{
//code goes here, where I got stuck...
}
}
}
Edit: I didn`t know the existence of "Split" my mistake... but at least it would great if you could explain me to to use it for the problem above?
You can use this:
String words = "word1, word2, word3";
List:
List<string> wordsList= words.Split(',').ToList<string>();
Array:
string[] namesArray = words.Split(',');
#patrick Artner beat me to it, but you can just split the input with the comma as the argument, or whatever you want the argument to be.
This is the example, and you will learn from the documentation.
using System;
public class Example {
public static void Main() {
String value = "This is a short string.";
Char delimiter = 's';
String[] substrings = value.Split(delimiter);
foreach (var substring in substrings)
Console.WriteLine(substring);
}
}
The example displays the following output:
Thi
i
a
hort
tring.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am trying to find out if a .txt file contains words stored in a list named Abreviated. This list is filled by reading values from a csv file as shown below;
StreamReader sr = new StreamReader(#"C:\textwords.csv");
string TxtWrd = sr.ReadLine();
while ((TxtWrd = sr.ReadLine()) != null)
{
Words = TxtWrd.Split(Seperators, StringSplitOptions.None);
Abreviated.Add(Words[0]);
Expanded.Add(Words[1]);
}
I would like to use this list to check if a .txt file contains any of the words in the list. The .txt file is being read using a streamreader and is stored as a string FileContent. the code i have to try and find the matches is below;
if (FC.Contains(Abreviated.ToString()))
{
MessageBox.Show("Match found");
}
else
{
MessageBox.Show("No Match");
}
This will always return the else statement even though one of the words is in the text file.
any advice on how to get this working?
Thanks in advance!
You can use key-value pair data structure for storing abbreviated word and respective full word as key-value pair. In C#, Dictionary has generic implementation for storing key value pair.
I've refactored your code which makes easy to reuse.
internal class FileParser
{
internal Dictionary<string, string> WordDictionary = new Dictionary<string, string>();
private string _filePath;
private char Seperators => ',';
internal FileParser(string filePath)
{
_filePath = filePath;
}
internal void Parse()
{
StreamReader sr = new StreamReader(_filePath);
string TxtWrd = sr.ReadLine();
while ((TxtWrd = sr.ReadLine()) != null)
{
var words = TxtWrd.Split(Seperators, StringSplitOptions.None);
//WordDictionary.TryAdd(Words[0], Words[1]); // available in .NET corefx https://github.com/dotnet/corefx/issues/1942
if (!WordDictionary.ContainsKey(words[0]))
WordDictionary.Add(words[0], words[1]);
}
}
internal bool IsWordAvailable(string word)
{
return WordDictionary.ContainsKey(word);
}
}
Now, you can reuse above class within your assembly like in following way :
public class Program
{
public static void Main(string[] args)
{
var fileParser = new FileParser(#"C:\textwords.csv");
if(fileParser.IsWordAvailable("abc"))
{
MessageBox.Show("Match found");
}
else
{
MessageBox.Show("No Match");
}
}
}
You are comparing your entire file's content to the string representation of a collections of words. You need to compare each individual word found in the file content to your abbreviated list. One way you could do the comparison is to split the file content into individual words and then look those up individually against your abbreviated list.
string[] fileWords = FC.Split(Separators, StringSplitOptions.RemoveEmptyEntries);
bool hasMatch = false;
for(string fileWord : fileWords)
{
if(Abbreviated.Contains(fileWord))
{
hasMatch = true;
break;
}
}
if (hasMatch)
{
MessageBox.Show("Match found");
}
else
{
MessageBox.Show("No Match");
}
I would recommend switching your abbreviated collection to a HashSet or a Dictionary that also includes your matching expanded text for the abbreviation. Also, there are probably alternate ways to do the search you are looking for with regex.
I'm unsure on what some of your variables are so this may be slightly different to what you have, but gives the same functionality.
static void Main(string[] args)
{
List<string> abbreviated = new List<string>();
List<string> expanded = new List<string>();
StreamReader sr = new StreamReader("textwords.csv");
string TxtWrd = "";
while ((TxtWrd = sr.ReadLine()) != null)
{
Debug.WriteLine("line: " + TxtWrd);
string[] Words = TxtWrd.Split(new char[] { ',' } , StringSplitOptions.None);
abbreviated.Add(Words[0]);
expanded.Add(Words[1]);
}
if (abbreviated.Contains("wuu2"))
{
//show message box
} else
{
//don't
}
}
As mentioned in one of the comments, a Dictionary might be better suited for this.
This assumes that the data in your file is in the following format, with a new set on each line.
wuu2,what are you up to
If all you want to do is check if a text file contains words in your list, you can read the entire contents of the file into a string (instead of line by line), split the string on your separators, and then check if the intersection of the words in the text file and your list of words has any items:
// Get the "separators" into a list
var wordsFile = #"c:\public\temp\textWords.csv"; // (#"C:\textwords.csv");
var separators = File.ReadAllText(wordsFile).Split(',');
// Get the words of the file into a list (add more delimeters as necessary)
var txtFile = #"c:\public\temp\temp.txt";
var allWords = File.ReadAllText(txtFile).Split(new[] {' ', '.', ',', ';', ':', '\r', '\n'});
// Get the intersection of the file words and the separator words
var commonWords = allWords.Intersect(separators).ToList().Distinct();
if (commonWords.Any())
{
Console.WriteLine("The text file contains the following matching words:");
Console.WriteLine(string.Join(", ", commonWords));
}
else
{
Console.WriteLine("The file did not contain any matching words.");
}
Console.Write("\nDone!\nPress any key to exit...");
Console.ReadKey();
I'm trying to make ildasm output more like json or xml so that its somewhat easy to programmatically read it.
The way I intended to do it by reading the output line by line and then adding the classes and methods etc to lists and then modify and rewrite it as xml and then read it.
Question: Are there any smarter or simpler ways to read the output?
There is a way to get a list of classes and methods by reading IL Code.
The solution which i am telling might be a bit long but it will work.
IL is nothing but .exe or .dll . First try to convert this to C# or VB by using ILSpy . Download this tool and open your DLL into this. This tool can convert your IL Code into C# or VB.
After converting , save your converted code into a txt file.
Then read the text file and find the classes and methods inside it.
To read Method Names :
MatchCollection mc = Regex.Matches(str, #"(\s)([A-Z]+[a-z]+[A-Z]*)+\(");
To read Class Names :
Iterate through the file line by line and check whether the line has name "Class" . if it has the name then Split the values and store the value/text which comes after the name "Class" which is nothing but ClassName.
Complete Code :
static void Main(string[] args)
{
string line;
List<string> classLst = new List<string>();
List<string> methodLst = new List<string>();
System.IO.StreamReader file = new System.IO.StreamReader(#"C:\Users\******\Desktop\TreeView.txt");
string str = File.ReadAllText(#"C:\Users\*******\Desktop\TreeView.txt");
while ((line = file.ReadLine()) != null)
{
if (line.Contains("class")&&!line.Contains("///"))
{
// for finding class names
int si = line.IndexOf("class");
string followstring = line.Substring(si);
if (!string.IsNullOrEmpty(followstring))
{
string[] spilts = followstring.Split(' ');
if(spilts.Length>1)
{
classLst.Add(spilts[1].ToString());
}
}
}
}
MatchCollection mc = Regex.Matches(str, #"(\s)([A-Z]+[a-z]+[A-Z]*)+\(");
foreach (Match m in mc)
{
methodLst.Add(m.ToString().Substring(1, m.ToString().Length - 2));
//Console.WriteLine(m.ToString().Substring(1, m.ToString().Length - 2));
}
file.Close();
Console.WriteLine("******** classes ***********");
foreach (var item in classLst)
{
Console.WriteLine(item);
}
Console.WriteLine("******** end of classes ***********");
Console.WriteLine("******** methods ***********");
foreach (var item in methodLst)
{
Console.WriteLine(item);
}
Console.WriteLine("******** end of methods ***********");
Console.ReadKey();
}
Here I am storing the class names and method names in a list. you can later store them in XML or JSON as you described above.
Ping us if you face any problem.
I'm trying to get certain strings out of a text file and put it in a variable.
This is what the structure of the text file looks like keep in mind this is just one line and each line looks like this and is separated by a blank line:
Date: 8/12/2013 12:00:00 AM Source Path: \\build\PM\11.0.64.1\build.11.0.64.1.FileServerOutput.zip Destination Path: C:\Users\Documents\.NET Development\testing\11.0.64.1\build.11.0.55.5.FileServerOutput.zip Folder Updated: 11.0.64.1 File Copied: build.11.0.55.5.FileServerOutput.zip
I wasn't entirely too sure of what to use for a delimiter for this text file or even if I should be using a delimiter so it could be subjected to change.
So just a quick example of what I want to happen with this, is I want to go through and grab the Destination Path and store it in a variable such as strDestPath.
Overall the code I came up with so far is this:
//find the variables from the text file
string[] lines = File.ReadAllLines(GlobalVars.strLogPath);
Yeah not much, but I thought perhaps if I just read one line at at a time and tried to search for what I was looking for through that line but honestly I'm not 100% sure if I should stick with that way or not...
If you are skeptical about how large your file is, you should come up using ReadLines which is deferred execution instead of ReadAllLines:
var lines = File.ReadLines(GlobalVars.strLogPath);
The ReadLines and ReadAllLines methods differ as follows:
When you use ReadLines, you can start enumerating the collection of strings before the whole collection is returned; when you use ReadAllLines, you must wait for the whole array of strings be returned before you can access the array. Therefore, when you are working with very large files, ReadLines can be more efficient.
As weird as it might sound, you should take a look to log parser. If you are free to set the file format you could use one that fits with log parser and, believe me, it will make your life a lot more easy.
Once you load the file with log parse you can user queries to get the information you want. If you don't care about using interop in your project you can even add a com reference and use it from any .net project.
This sample reads a HUGE csv file a makes a bulkcopy to the DB to perform there the final steps. This is not really your case, but shows you how easy is to do this with logparser
COMTSVInputContextClass logParserTsv = new COMTSVInputContextClass();
COMSQLOutputContextClass logParserSql = new COMSQLOutputContextClass();
logParserTsv.separator = ";";
logParserTsv.fixedSep = true;
logParserSql.database = _sqlDatabaseName;
logParserSql.server = _sqlServerName;
logParserSql.username = _sqlUser;
logParserSql.password = _sqlPass;
logParserSql.createTable = false;
logParserSql.ignoreIdCols = true;
// query shortened for clarity purposes
string SelectPattern = #"Select TO_STRING(UserName),TO_STRING(UserID) INTO {0} From {1}";
string query = string.Format(SelectPattern, _sqlTable, _csvPath);
logParser.ExecuteBatch(query, logParserTsv, logParserSql);
LogParser in one of those hidden gems Microsoft has and most people don't know about. I have use to read iis logs, CSV files, txt files, etc. You can even generate graphics!!!
Just check it here http://support.microsoft.com/kb/910447/en
Looks like you need to create a Tokenizer. Try something like this:
Define a list of token values:
List<string> gTkList = new List<string>() {"Date:","Source Path:" }; //...etc.
Create a Token class:
public class Token
{
private readonly string _tokenText;
private string _val;
private int _begin, _end;
public Token(string tk, int beg, int end)
{
this._tokenText = tk;
this._begin = beg;
this._end = end;
this._val = String.Empty;
}
public string TokenText
{
get{ return _tokenText; }
}
public string Value
{
get { return _val; }
set { _val = value; }
}
public int IdxBegin
{
get { return _begin; }
}
public int IdxEnd
{
get { return _end; }
}
}
Create a method to Find your Tokens:
List<Token> FindTokens(string str)
{
List<Token> retVal = new List<Token>();
if (!String.IsNullOrWhitespace(str))
{
foreach(string cd in gTkList)
{
int fIdx = str.IndexOf(cd);
if(fIdx > -1)
retVal.Add(cd,fIdx,fIdx + cd.Length);
}
}
return retVal;
}
Then just do something like this:
foreach(string ln in lines)
{
//returns ordered list of tokens
var tkns = FindTokens(ln);
for(int i=0; i < tkns.Length; i++)
{
int len = (i == tkns.Length - 1) ? ln.Length - tkns[i].IdxEnd : tkns[i+1].IdxBegin - tkns[i].IdxEnd;
tkns[i].value = ln.Substring(tkns[i].IdxEnd+1,len).Trim();
}
//Do something with the gathered values
foreach(Token tk in tkns)
{
//stuff
}
}