How do I add parsed lines into a dictionary? - c#

I am trying to make a dictionary where the compiler reads from a text file where there are two words per line. I have parsed it through the split() method but I am struggling on how to add the corresponding keys and values from the line to the dictionary container. I am trying to add it in the ReadStream2() function after doing the split() in the line line.add(rez,rez). I know this is wrong but I have no idea how to combine what I am parsing into the dictionary in terms of keys and values. Thanks!
class Program
{
static void Main(string[] args)
{
Dictionary<string, string> line = new Dictionary<string, string>();
FileStream filestream = null;
string path = "Dictionary.txt";
//WriteByte(filestream, path);
//ReadByte(filestream, path);
//WriteStream(filestream, path);
//ReadFromFile();
Menu(filestream, path);
ReadStream2(filestream,path);
Group(filestream, path);
}
static void WriteByte(FileStream filestream, string path)
{
string str;
Console.WriteLine("Enter word");
str = Console.ReadLine();
try
{
filestream = new FileStream("Dictionary.txt", FileMode.Open, FileAccess.Write);
byte[] by = Encoding.Default.GetBytes(str);
filestream.Write(by, 0, by.Length);
Console.WriteLine("File written");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
filestream.Close();
}
}
static void ReadByte(FileStream filestream, string path)
{
try
{
filestream = new FileStream(path, FileMode.Open, FileAccess.Read);
byte[] by = new byte[(int)filestream.Length];
filestream.Read(by, 0, by.Length);
string str = Encoding.Default.GetString(by);
Console.WriteLine("File read");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
filestream.Close();
}
}
static void WriteStream(FileStream filestream, string path)
{
using (filestream = new FileStream(path, FileMode.Append, FileAccess.Write))
{
using (StreamWriter streamWriter = new StreamWriter(filestream))
{
//string str;
//Console.WriteLine("Enter word");
//str = Console.ReadLine();
//streamWriter.WriteLine(str);
}
}
}
static void ReadStream2(FileStream fileStream, string path)
{
using (fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
Dictionary<string, string> line = new Dictionary<string, string>();
using (StreamReader sw = new StreamReader(fileStream))
{
string rez = "";
while(sw.Peek() > 0)
{
rez = sw.ReadLine();
Console.WriteLine(rez);
string[] words = rez.Split(' ');
line.Add(rez, rez);
}
}
}
}
static void Group(FileStream fileStream, string path)
{
var list = File
.ReadLines(path)
.Select((v, i) => new { Index = i, Value = v })
.GroupBy(p => p.Index / 2)
.ToDictionary(g => g.First().Value, g => g.Last().Value);
}
static void Menu(FileStream fileStream, string path)
{
char choice;
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Welcome this is a English dictionary press d to continue");
Console.ResetColor();
choice = Convert.ToChar(Console.ReadLine());
while (choice == 'd' || choice == 'D')
{
ReadStream2(fileStream, path);
}
}
static void askWord()
{
string ask;
Console.WriteLine("What english word would you like to translate");
ask = Console.ReadLine();
if (ask == )
}
}
}

I have difficulties to understand.
Are you trying to read the words array? words[0] and words[1]?
string[] words = rez.Split(' ');
line.Add(words[0], words[1]);

#Larrythelobster
I write an sample project, hope I can help you:
using System.Text;
class Program
{
static void Main(string[] args)
{
WelcomeText();
string path = "Dictionary.txt";
var dict = ReadFile(path);
var input = GetInputWord();
var translateWord = SearchWord(dict, input);
ShowResult(translateWord);
}
private static void WelcomeText()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Welcome! This is a English dictionary...");
Console.ResetColor();
}
private static IDictionary<string, string> ReadFile(string path)
{
var lines = File.ReadAllLines(path);
var dict = new Dictionary<string, string>();
foreach(var line in lines)
{
var words = line.Split(' ');
dict.Add(words[0], words[1]);
}
return dict;
}
private static string GetInputWord()
{
Console.WriteLine("Enter a word to translate: ");
var word = Console.ReadLine();
return word;
}
private static string SearchWord(IDictionary<string, string> dict, string wordToSearch)
{
return dict[wordToSearch];
}
private static void ShowResult(string translateWord)
{
Console.WriteLine("The translate word is: " + translateWord);
}
}
Dictionary.txt (English > French):
yellow jaune
red rouge
blue bleu
green vert

Related

How to create threads for functions with many arguments

Suppose I have a directory with log files. log file
My program has to create 3 text files with some statistics.
date statistic domain statistic user statistic
Each log file has to process separately in parallel. But I don't understand how to create threads for functions with many arguments.
Main functions are void WriteInFileUserStat(string filename,string txt, Dictionary dict), void WriteInFileDomainStat(string filename, string txt, Dictionary dict), void WriteInFileDateStat(string filename, string txt, Dictionary dict).
class Program
{
static void Main(string[] args)
{
string dirName = #"C:\MY DISK\Study\7th semester\Основы параллельной обработки данных\log";
string[] filelist = Directory.GetFiles(#"C:\MY DISK\Study\7th semester\Основы параллельной обработки данных\log", "*.txt");
string[] fileliststat = Directory.GetFiles(#"C:\MY DISK\Study\7th semester\Основы параллельной обработки данных\log\statistic", "*.txt");
string userlog = #"C:\MY DISK\Study\7th semester\Основы параллельной обработки данных\log\statistic\userlog.txt";
string domainlog = #"C:\MY DISK\Study\7th semester\Основы параллельной обработки данных\log\statistic\domainlog.txt";
string datelog = #"C:\MY DISK\Study\7th semester\Основы параллельной обработки данных\log\statistic\datelog.txt";
Dictionary<string, string> userDict = new Dictionary<string, string>();
Dictionary<string, string> domainDict = new Dictionary<string, string>();
Dictionary<string, string> dateDict = new Dictionary<string, string>();
//Thread userStatThread = new Thread(new ParameterizedThreadStart(WriteInFileUserStat));
//userStatThread.Start(s, userlog, userDict);
if (Directory.Exists(dirName))
{
Console.WriteLine("Файлы с логами прокси-сервера:");
string[] files = Directory.GetFiles(dirName);
foreach (string s in files)
{
string fname = s;
Console.WriteLine(s);
}
}
Console.WriteLine("Статистика по пользователям: ");
foreach(string s in filelist)
{
WriteInFileUserStat(s, userlog, userDict);
}
foreach (KeyValuePair<string, string> keyValue in userDict)
{
Console.WriteLine(keyValue.Key + " - " + keyValue.Value);
}
Console.WriteLine("Статистика по доменам: ");
foreach (string s in filelist)
{
WriteInFileDomainStat(s, domainlog, domainDict);
}
foreach (KeyValuePair<string, string> keyValue in domainDict)
{
Console.WriteLine(keyValue.Key + " - " + keyValue.Value);
}
Console.WriteLine("Статистика по датам: ");
foreach (string s in filelist)
{
WriteInFileDateStat(s, datelog, dateDict);
}
foreach (KeyValuePair<string, string> keyValue in dateDict)
{
Console.WriteLine(keyValue.Key + " - " + keyValue.Value);
}
Console.ReadLine();
}
/*Парсинг файла*/
public static void FilesParsing(string line)
{
string userName;
string domainName;
string traffic;
string date;
string[] filelist = Directory.GetFiles(#"C:\MY DISK\Study\7th semester\Основы параллельной обработки данных\log", "*.txt");
foreach (string file_to_read in filelist)
{
}
string[] parts = line.Split('\t');
userName = parts[0];
domainName = parts[1];
traffic = parts[2];
date = parts[3];
Console.WriteLine($"Username = {userName} , Domain name = {domainName}, Traffic = {traffic}, Date = {date}");
}
/*Чтение из файла*/
static public void ReadingFile(string filename)
{
using (StreamReader sr = new StreamReader(filename))
{
string line;
while ((line = sr.ReadLine()) != null)
{
FilesParsing(line);
}
}
}
/*Запись в файл статистики по пользователю*/
static public void WriteInFileUserStat(string filename,string txt, Dictionary<string, string> dict)
{
string user;
string traffic;
int trafficInt = 0;
int tempValue = 0;
using (StreamWriter swr = new StreamWriter(txt))
{
using (StreamReader sr = new StreamReader(filename))
{
string line;
while ((line = sr.ReadLine()) != null)
{
string[] parts = line.Split('\t');
user = parts[0];
traffic = parts[2];
if (dict.ContainsKey(user))
{
tempValue = Convert.ToInt32(dict[user]) + Convert.ToInt32(traffic);
dict.Remove(user);
trafficInt = Convert.ToInt32(traffic);
dict.Add(user, Convert.ToString(tempValue));
}
else dict.Add(user, traffic);
//swr.WriteLine("{0}\t{1}", user, traffic);
}
}
foreach (KeyValuePair<string, string> KeyValue in dict)
{
swr.WriteLine("{0} - {1}", KeyValue.Key, KeyValue.Value);
}
swr.Close();
}
}
/*Запись в файл статистики по доменам*/
static public void WriteInFileDomainStat(string filename, string txt, Dictionary<string, string> dict)
{
string domain;
string traffic;
int trafficInt = 0;
int tempValue = 0;
using (StreamWriter swr = new StreamWriter(txt))
{
using (StreamReader sr = new StreamReader(filename))
{
string line;
while ((line = sr.ReadLine()) != null)
{
string[] parts = line.Split('\t');
domain = parts[1];
traffic = parts[2];
if (dict.ContainsKey(domain))
{
tempValue = Convert.ToInt32(dict[domain]) + Convert.ToInt32(traffic);
dict.Remove(domain);
trafficInt = Convert.ToInt32(traffic);
dict.Add(domain, Convert.ToString(tempValue));
}
else dict.Add(domain, traffic);
//swr.WriteLine("{0}\t{1}", domain, traffic);
}
}
foreach (KeyValuePair<string, string> KeyValue in dict)
{
swr.WriteLine("{0} - {1}", KeyValue.Key, KeyValue.Value);
}
swr.Close();
}
}
/*Запись в файл статистики по дате*/
static public void WriteInFileDateStat(string filename, string txt, Dictionary<string, string> dict)
{
string date;
string traffic;
int trafficInt = 0;
int tempValue = 0;
using (StreamWriter swr = new StreamWriter(txt))
{
using (StreamReader sr = new StreamReader(filename))
{
string line;
while ((line = sr.ReadLine()) != null)
{
string[] parts = line.Split('\t');
date = parts[3];
traffic = parts[2];
if (dict.ContainsKey(date))
{
tempValue = Convert.ToInt32(dict[date]) + Convert.ToInt32(traffic);
dict.Remove(date);
trafficInt = Convert.ToInt32(traffic);
dict.Add(date, Convert.ToString(tempValue));
}
else dict.Add(date, traffic);
//swr.WriteLine("{0}\t{1}", date, traffic);
}
}
foreach (KeyValuePair<string, string> KeyValue in dict)
{
swr.WriteLine("{0} - {1}", KeyValue.Key, KeyValue.Value);
}
swr.Close();
}
}
}
If you got many arguments but only want 1 type to write in, make a single class, struct or tupple to take them all. Use that as the type for the argument. That is the way Events Arguments go.

How can I remove the oldest lines in a file when using a FileStream and StreamWriter?

Based on Prakash's answer here, I thought I'd try something like this to remove the oldest lines in a file prior to adding a new line to it:
private ExceptionLoggingService()
{
_fileStream = File.OpenWrite(GetExecutionFolder() + "\\Application.log");
_streamWriter = new StreamWriter(_fileStream);
}
public void WriteLog(string message)
{
const int MAX_LINES_DESIRED = 1000;
StringBuilder formattedMessage = new StringBuilder();
formattedMessage.AppendLine("Date: " + DateTime.Now.ToString());
formattedMessage.AppendLine("Message: " + message);
// First, remove the earliest lines from the file if it's grown too much
List<string> logList = File.ReadAllLines(_fileStream).ToList();
while (logList.Count > MAX_LINES_DESIRED)
{
logList.RemoveAt(0);
}
File.WriteAllLines(_fileStream, logList.ToArray());
_streamWriter.WriteLine(formattedMessage.ToString());
_streamWriter.Flush();
}
...but in my version of .NET (Compact Framework, Windows CE C# project in VS 2008), neither ReadAllLines() nor WriteAllLines() are available.
What is the ReadAllLines/WriteAllLines-challenged way of accomplishing the same thing?
UPDATE
This is doubtless kludgy, but it seems like it should work, and I'm going to test it out. I moved the "shorten the log file" code from the WriteLog() method to the constructor:
private ExceptionLoggingService()
{
const int MAX_LINES_DESIRED = 1000;
string uriPath = GetExecutionFolder() + "\\Application.log";
string localPath = new Uri(uriPath).LocalPath;
if (!File.Exists(localPath))
{
File.Create(localPath);
}
_fileStream = File.OpenWrite(localPath);
// First, remove the earliest lines from the file if it's grown too much
StreamReader reader = new StreamReader(_fileStream);
List<String> logList = new List<String>();
while (!reader.EndOfStream)
{
logList.Add(reader.ReadLine());
}
while (logList.Count > MAX_LINES_DESIRED)
{
logList.RemoveAt(0);
}
if (logList.Count > MAX_LINES_DESIRED)
{
_fileStream.Close();
File.Delete(GetExecutionFolder() + "\\Application.log");
File.Create(GetExecutionFolder() + "\\Application.log");
_fileStream = File.OpenWrite(GetExecutionFolder() + "\\Application.log");
}
_streamWriter = new StreamWriter(_fileStream);
foreach (String s in logList)
{
_streamWriter.WriteLine(s);
_streamWriter.Flush();
}
}
public void WriteLog(string message)
{
StringBuilder formattedMessage = new StringBuilder();
formattedMessage.AppendLine("Date: " + DateTime.Now.ToString());
formattedMessage.AppendLine("Message: " + message);
_streamWriter.WriteLine(formattedMessage.ToString());
_streamWriter.Flush();
}
ReadAllLines and WriteAllLines are just hiding a loop from you. Just do:
StreamReader reader = new StreamReader(_fileStream);
List<String> logList = new List<String>();
while (!reader.EndOfStream)
logList.Add(reader.ReadLine());
Note that this is nearly identical to the implementation of File.ReadAllLines (from MSDN Reference Source)
String line;
List<String> lines = new List<String>();
using (StreamReader sr = new StreamReader(path, encoding))
while ((line = sr.ReadLine()) != null)
lines.Add(line);
return lines.ToArray();
WriteAllLines is simialr:
StreamWriter writer = new StreamWriter(path, false); //Don't append!
foreach (String line in logList)
{
writer.WriteLine(line);
}
I would write simple extension methods for this, that do the job lazily without loading whole file to memory.
Usage would be something like this:
outfile.MyWriteLines(infile.MyReadLines().Skip(1));
public static class Extensions
{
public static IEnumerable<string> MyReadLines(this FileStream f)
{
var sr = new StreamReader(f);
var line = sr.ReadLine();
while (line != null)
{
yield return line;
line = sr.ReadLine();
}
}
public static void MyWriteLines(this FileStream f, IEnumerable<string> lines)
{
var sw = new StreamWriter(f);
foreach(var line in lines)
{
sw.WriteLine(line);
}
}
}

How to split a text file into multiple files?

In C#, what is the most efficient method to split a text file into multiple text files (the splitting delimiter being a blank line), while preserving the character encoding?
I would use the StreamReader and StreamWriter classes:
public void Split(string inputfile, string outputfilesformat) {
int i = 0;
System.IO.StreamWriter outfile = null;
string line;
try {
using(var infile = new System.IO.StreamReader(inputfile)) {
while(!infile.EndOfStream){
line = infile.ReadLine();
if(string.IsNullOrEmpty(line)) {
if(outfile != null) {
outfile.Dispose();
outfile = null;
}
continue;
}
if(outfile == null) {
outfile = new System.IO.StreamWriter(
string.Format(outputfilesformat, i++),
false,
infile.CurrentEncoding);
}
outfile.WriteLine(line);
}
}
} finally {
if(outfile != null)
outfile.Dispose();
}
}
You would then call this method like this:
Split("C:\\somefile.txt", "C:\\output-files-{0}.txt");
Purely for those who want to avoid thinking:
If you have a CSV (comma separated values) file and want to split the file when a field changes, identify/name the file by the change (without unnecessary quote marks), and strip out comments/certain lines (here identified by starting with "#)
Modified method:
public void Split(string inputfile, string outputfilesformat)
{
System.IO.StreamWriter outfile = null;
string line;
string[] splitArray;
string nameFromFile = "";
try
{
using (var infile = new System.IO.StreamReader(inputfile))
{
while (!infile.EndOfStream)
{
line = infile.ReadLine();
splitArray = line.Split(new char[] { ',' });
if (!splitArray[0].StartsWith("\"#"))
{
if (splitArray[4].Replace("\"", "") != nameFromFile.Replace("\"", ""))
{
if (outfile != null)
{
outfile.Dispose();
outfile = null;
}
nameFromFile = splitArray[4].Replace("\"", "");
continue;
}
if (outfile == null)
{
outfile = new System.IO.StreamWriter(
string.Format(outputfilesformat, nameFromFile),
false,
infile.CurrentEncoding);
}
outfile.WriteLine(line);
}
}
}
}
finally
{
if (outfile != null)
outfile.Dispose();
}
}
Local path call:
string strpath = Server.MapPath("~/Data/SPLIT/DATA.TXT");
string newFile = Server.MapPath("~/Data/SPLIT");
if (System.IO.File.Exists(#strpath))
{
Split(strpath, newFile+"\\{0}.CSV");
}
In the case anyone needs to split a text file into multiple files using a string:
public static void Main(string[] args)
{
void Split(string inputfile, string outputfilesformat)
{
int i = 0;
System.IO.StreamWriter outfile = null;
string line;
try
{
using (var infile = new System.IO.StreamReader(inputfile))
{
while (!infile.EndOfStream)
{
line = infile.ReadLine();
if (line.Trim().Contains("String You Want File To Split From"))
{
if (outfile != null)
{
outfile.Dispose();
outfile = null;
}
continue;
}
if (outfile == null)
{
outfile = new System.IO.StreamWriter(
string.Format(outputfilesformat, i++),
false,
infile.CurrentEncoding);
}
outfile.WriteLine(line);
}
}
}
finally
{
if (outfile != null)
outfile.Dispose();
}
}
Split("C:test.txt", "C:\\output-files-{0}.txt");
}

How to give a file path in code instead of command line

I've been working on my module exercises and I came across this code snippet which reads the text file and prints the details about it.
It's working fine, but I just want to know how to give the path of the text file in the code itself other than giving the path in the command line.
Below is my code.
class Module06
{
public static void Exercise01(string[] args)
{
string fileName = args[0];
FileStream stream = new FileStream(fileName, FileMode.Open);
StreamReader reader = new StreamReader(stream);
int size = (int)stream.Length;
char[] contents = new char[size];
for (int i = 0; i < size; i++)
{
contents[i] = (char)reader.Read();
}
reader.Close();
Summarize(contents);
}
static void Summarize(char[] contents)
{
int vowels = 0, consonants = 0, lines = 0;
foreach (char current in contents)
{
if (Char.IsLetter(current))
{
if ("AEIOUaeiou".IndexOf(current) != -1)
{
vowels++;
}
else
{
consonants++;
}
}
else if (current == '\n')
{
lines++;
}
}
Console.WriteLine("Total no of characters: {0}", contents.Length);
Console.WriteLine("Total no of vowels : {0}", vowels);
Console.WriteLine("Total no of consonants: {0}", consonants);
Console.WriteLine("Total no of lines : {0}", lines);
}
}
In your static void Main, call
string[] args = {"filename.txt"};
Module06.Exercise01(args);
Reading of a text file is much easier with File.ReadAllText then you don't need to think about closing the file you just use it. It accepts file name as parameter.
string fileContent = File.ReadAllText("path to my file");
string fileName = #"path\to\file.txt";

Reading in files that contain specific characters in C#

I have a text file named C:/test.txt:
1 2 3 4
5 6
I want to read every number in this file using StreamReader.
How can I do that?
Do you really need to use a StreamReader to do this?
IEnumerable<int> numbers =
Regex.Split(File.ReadAllText(#"c:\test.txt"), #"\D+").Select(int.Parse);
(Obviously if it's impractical to read the entire file in one hit then you'll need to stream it, but if you're able to use File.ReadAllText then that's the way to do it, in my opinion.)
For completeness, here's a streaming version:
public IEnumerable<int> GetNumbers(string fileName)
{
using (StreamReader sr = File.OpenText(fileName))
{
string line;
while ((line = sr.ReadLine()) != null)
{
foreach (string item in Regex.Split(line, #"\D+"))
{
yield return int.Parse(item);
}
}
}
}
using (StreamReader reader = new StreamReader(stream))
{
string contents = reader.ReadToEnd();
Regex r = new Regex("[0-9]");
Match m = r.Match(contents );
while (m.Success)
{
int number = Convert.ToInt32(match.Value);
// do something with the number
m = m.NextMatch();
}
}
Something like so might do the trick, if what you want is to read integers from a file and store them in a list.
try
{
StreamReader sr = new StreamReader("C:/test.txt"))
List<int> theIntegers = new List<int>();
while (sr.Peek() >= 0)
theIntegers.Add(sr.Read());
sr.Close();
}
catch (Exception e)
{
//Do something clever to deal with the exception here
}
Solution for big files:
class Program
{
const int ReadBufferSize = 4096;
static void Main(string[] args)
{
var result = new List<int>();
using (var reader = new StreamReader(#"c:\test.txt"))
{
var readBuffer = new char[ReadBufferSize];
var buffer = new StringBuilder();
while ((reader.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
foreach (char c in readBuffer)
{
if (!char.IsDigit(c))
{
// we found non digit character
int newInt;
if (int.TryParse(buffer.ToString(), out newInt))
{
result.Add(newInt);
}
buffer.Remove(0, buffer.Length);
}
else
{
buffer.Append(c);
}
}
}
// check buffer
if (buffer.Length > 0)
{
int newInt;
if (int.TryParse(buffer.ToString(), out newInt))
{
result.Add(newInt);
}
}
}
result.ForEach(Console.WriteLine);
Console.ReadKey();
}
}
I might be wrong but with StreamReader you cannot set delimeter.
But you can use String.Split() to set delimeter (it is space in your case?) and extract all numbers into separate array.
Something like this ought to work:
using (var sr = new StreamReader("C:/test.txt"))
{
var s = sr.ReadToEnd();
var numbers = (from x in s.Split('\n')
from y in x.Split(' ')
select int.Parse(y));
}
Something like this:
using System;
using System.IO;
class Test
{
public static void Main()
{
string path = #"C:\Test.txt";
try
{
if( File.Exists( path ) )
{
using( StreamReader sr = new StreamReader( path ) )
{
while( sr.Peek() >= 0 )
{
char c = ( char )sr.Read();
if( Char.IsNumber( c ) )
Console.Write( c );
}
}
}
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
}
}
}

Categories