I am new to learning C# and have a question.
I have a txt file with tests and scores like below
ACT
21.0
SAT
478.9
CLEP
69.1
ACT 32.0
How do I parse this txt to dictionary and display as below (removing any duplicates)
ACT 21.0
SAT 478.9
CLEP 69.1
Here is what I have attempted
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Text.RegularExpressions;
namespace Generate
{
class generateInputStream
{
static void Main(string[] args)
{
FileManager objfileManager = new FileManager();
FileStream fs = null;
Console.Write("Enter the file path: ");
while (fs == null)
{
string Path = Console.ReadLine();
fs = objfileManager.OpenFile(Path);
}
int
}
}
public class FileManager
{
public FileStream OpenFile(string Path)
{
try
{
return new FileStream(Path, FileMode.Open, FileAccess.Read);
}
catch (Exception e)
{
Console.Write("Problem opening file {0}, please enter a valid path: ", Path);
}
return null;
}
public List<string> ReadLines(FileStream File)
{
List<string> text = new List<string>();
try
{
var streamReader = new StreamReader(File);
}
catch (Exception e)
{
Console.Write(e.Message);
}
return text;
}
static readFileIntoDictionary()
{
StreamReader generateInputStream;
var streamReader = new StreamReader();
SortedDictionary<string, double> dic = new SortedDictionary<string, double>();
string Key = string.Empty;
double Value = 0.0;
while ((Key = streamReader.ReadLine())!= null)
{
Value = Convert.ToInt32(streamReader.ReadLine());
dic.Add(Key, Value);
}
streamReader.Close();
return dic;
}
static displayScoreData()
{
readFileIntoDictionary();
foreach (KeyValuePair<string, double> pair in dic)
{
Console.WriteLine(pair.Key, "-",pair.Value);
}
}
}
}
This method should help you a bit. There is no error handling here, so we assume your file is always in correct format.
public static KeyValuePair<string, decimal>? ReadPair (StreamReader sr)
{
if (sr.EndOfStream) return null;
string key = sr.ReadLine ();
decimal value = decimal.Parse (sr.ReadLine ());
return new KeyValuePair<string, decimal> (key, value);
}
I don't know what is a duplicate for you, the same key? The same key + value?
Related
I have this code which reads from my json file an array of words
public static string[] GetProfanity()
{
var json = string.Empty;
using (var fs = File.OpenRead("profanity.json"))
using (var sr = new StreamReader(fs, new UTF8Encoding(false)))
json = sr.ReadToEnd();
var profanityJson = JsonConvert.DeserializeObject<ProfanityJson>(json);
return profanityJson.badwords;
}
This is the json
{
"badwords" : ["bad", "stupid"]
}
And i try to access this here
public static bool ProfanityCheck(string inputString)
{
string[] badWords = GetProfanity();
string checkString = inputString.ToLower();
if (badWords.Any(checkString.Contains))
return true;
return false;
}
As requested I access the ProfanityCheck method here
[Command("echo")]
[Description("says whatever the user gives")]
public async Task Echo(CommandContext ctx, [RemainingText] string echoText)
{
bool hasProfanity = ProfanityFilter.ProfanityCheck(echoText);
if(hasProfanity)
{
var errMsg = ProfanityFilter.ErrorMessage();
var errSent = await ctx.Channel.SendMessageAsync(embed: errMsg).ConfigureAwait(false);
Thread.Sleep(3000);
await ctx.Channel.DeleteMessageAsync(errSent).ConfigureAwait(false);
await ctx.Channel.DeleteMessageAsync(ctx.Message).ConfigureAwait(false);
return;
}
await ctx.Channel.SendMessageAsync(echoText).ConfigureAwait(false);
}
and the struct I Deserialize it as
public struct ProfanityJson
{
[JsonProperty("badwords")]
public string[] badwords { get; private set; }
}
but when i attempt to search for this any bad words in a string I pass, nothing happens, no errors in the console, no output otherwise. I have it set up so that it sends me an error message when profanity is found, but in its current state it does nothing when profanity is passed
Your code seems to be correct... I would write the GetProfanity() in another way (and I wouldn't surely reread it every time a word is passed to to ProfanityCheck) but this is tangential to your problem. I've written a minimum testable example:
public class ProfanityJson
{
public string[] badwords { get; set; }
}
public static class ProfanityChecker
{
public static string[] GetProfanity()
{
var json = string.Empty;
using (var fs = File.OpenRead("profanity.json"))
using (var sr = new StreamReader(fs, new UTF8Encoding(false)))
json = sr.ReadToEnd();
var profanityJson = JsonConvert.DeserializeObject<ProfanityJson>(json);
return profanityJson.badwords;
}
public static string[] GetProfanity2()
{
using (var sr = new StreamReader("profanity.json"))
using (var jtr = new JsonTextReader(sr))
{
var ser = new JsonSerializer();
var profanityJson = ser.Deserialize<ProfanityJson>(jtr);
return profanityJson.badwords;
}
}
public static bool ProfanityCheck(string inputString)
{
string[] badWords = GetProfanity2();
Trace.WriteLine($"Loaded {badWords.Length} bad words");
string checkString = inputString.ToLower();
if (badWords.Any(checkString.Contains))
return true;
return false;
}
}
static void Main(string[] args)
{
Console.WriteLine(ProfanityChecker.ProfanityCheck("badder"));
}
So the only idea I have is that you are using a "stale" version of profanity.json. I've added a little loggin in the ProfanityCheck() method. It will go to the Output pane in Visual Studio.
(Would be a mess as a comment)
You could have your class like this:
public class ProfanityJson
{
[JsonProperty("badwords")]
public string[] Badwords { get; set; }
}
Is it like so? Json is case sensitive.
I have to import my file excel csv to mongodb, but I want use code c#.
public class AnimalRetriever : IAnimalRetriever
{
private readonly MongoClient _mongoClient;
public AnimalRetriever()
{
_mongoClient = new MongoClient("mongodb://localhost:27017");
}
private List<Animal> GetByContinent(string continent)
{
_mongoClient.GetDatabase("local")
.GetCollection<Animal>("Animal")
.ReplaceOne(
filter: new BsonDocument("Continent", continent),
options: new UpdateOptions { IsUpsert = true },
replacement: animal.csv); //file di testo da leggere invece di newDoc(csv extension)
return _mongoClient.GetDatabase("local")
.GetCollection<Animal>("Continent")
.Find("{\"Continent\":\"" + continent + "\"}")
.ToList();
}
using System;
using System.Collections.Generic;
using System.IO;
using FactoryExample.Continent;
using MongoDB.Bson;
using MongoDB.Driver;
using CsvHelper;
namespace FactoryExample
{
class MainApp
{
public static void Main()
{ try
{
var client = new MongoClient("mongodb://localhost:27017");
var db = client.GetDatabase("local");
var coll = db.GetCollection<BsonDocument>("Animal");
var reader = new StreamReader("animal.csv");
var csv = new CsvReader(reader);
csv.Configuration.HasHeaderRecord = true;
var records = csv.GetRecords<Animals>();
var dizionario = new Dictionary<string,Animal>();
foreach (var animal in records)
{
if (dizionario.ContainsKey(animal.Continent))
{
dizionario[animal.Continent].Carnivor.Add(animal.Carnivor);
dizionario[animal.Continent].Herbivor.Add(animal.Herbivor);
}
else
{
var newanimal = new Animal
{
Continent = animal.Continent,
Carnivor = new List<string>(),
Herbivor = new List<string>()
};
newanimal.Carnivor.Add(animal.Carnivor);
newanimal.Herbivor.Add(animal.Herbivor);
dizionario.Add(newanimal.Continent,newanimal);
}
}
}
catch (Exception err)
{
Console.WriteLine("Error!!");
Console.WriteLine(err.Message);
}
Console.ReadKey();
//Console.Read();
var continentFactory = ContinentFactory.Get(ContinentType.AMERICA);
var carnivore = continentFactory.GetCarnivore();
var herbivore = continentFactory.GetHerbivore();
foreach (var h in herbivore)
{
Console.WriteLine(h);
}
foreach (var c in carnivore)
{
Console.WriteLine(c);
}
Console.ReadKey();
}
}
}
I have two files F1.txt and F2.txt. F1.txt contains some contents like
U1,U2
U1,U5
U3,U4
U2,U1
U3,U4
Essentially U1,U2 and U2,U1 mean the same . So now I want to write the distinct contents to a file F2.txt i.e. after writing F2.txt should contain
U1,U2
U1,U5
U3,U4
I tried the below but that did not work out.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StringInFileTechchef
{
class Program
{
static void Main(string[] args)
{
string line = "";
using (StreamReader sr = new StreamReader(#"C:\Users\Chiranjib\Desktop\F1.txt"))
{
while((line=sr.ReadLine()) !=null)
{
if (!File.ReadAllText(#"C:\Users\Chiranjib\Desktop\F2.txt").Contains(line))
{
//char[] array = line.ToCharArray();
//Array.Reverse(array);
//string temp = new string(array);
string temp1 = line.Substring(0, 2);
string temp2 = line.Substring(3, 2);
if (!File.ReadAllText(#"C:\Users\Chiranjib\Desktop\F2.txt").Contains(temp2 + "," + temp1))
{
using (StreamWriter sw = new StreamWriter(#"C:\Users\Chiranjib\Desktop\F2.txt"))
{
sw.WriteLine(line);
Console.WriteLine(line);
}
}
}
}
}
Console.ReadKey();
}
}
}
What am I missing ? How to achieve the scenario.
Here is how I would do it:
Take each line and split it to a string[]
Sort the string[]
Join the string[] back to a string
Take the distinct strings
var distinct = File.ReadLines("TextFile2.txt")
.Select(l => String.Join(",", l.Split(',').OrderBy(i => i)))
.Distinct();
File.WriteAllLines("F2.txt", distinct);
Another method:
HashSet<string> uniqueLines = new HashSet<string>();
foreach(string line in File.ReadLines("F1.txt"))
{
if (uniqueLines.Contains(line))
continue;
string[] tokens = line.Split(',');
string reversedLine = string.Join(",", tokens.Reverse());
if (uniqueLines.Contains(reversedLine))
continue;
uniqueLines.Add(line);
}
File.WriteAllLines("F2.txt", uniqueLines);
This worked for me. Basically assuming that there are two strings separated by comma always, I just filter them out using a HashSet. May be an overkill but works for small files.
#region
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
#endregion
namespace StringInFileTechchef
{
internal class Program
{
private static void Main(string[] args)
{
HashSet<WordCombo> existingWordCombos = GetWordCombos(File.ReadAllLines(#"C:\Users\Chiranjib\Desktop\F2.txt"));
HashSet<WordCombo> newWordCombos = GetWordCombos(File.ReadAllLines(#"C:\Users\Ganesh\Chiranjib\F1.txt"));
foreach (WordCombo newWordCombo in newWordCombos)
{
existingWordCombos.Add(newWordCombo);
}
StringBuilder stringBuilder = new StringBuilder();
foreach (WordCombo existingWordCombo in existingWordCombos)
{
stringBuilder.AppendFormat("{0},{1}{2}", existingWordCombo.SmallerWord, existingWordCombo.BiggerWord, Environment.NewLine);
}
File.WriteAllText(#"C:\Users\Ganesh\Desktop\F2.txt", stringBuilder.ToString());
}
private static HashSet<WordCombo> GetWordCombos(IEnumerable<string> lines)
{
HashSet<WordCombo> wordCombos = new HashSet<WordCombo>();
foreach (string line in lines)
{
string[] splitWords = line.Split(new[] {','});
wordCombos.Add(new WordCombo(splitWords[0], splitWords[1]));
}
return wordCombos;
}
private class WordCombo
{
public string BiggerWord { get; private set; }
public string SmallerWord { get; private set; }
public WordCombo(string part1, string part2)
{
if (0 < string.Compare(part1, part2, StringComparison.InvariantCultureIgnoreCase))
{
BiggerWord = part1;
SmallerWord = part2;
}
else
{
BiggerWord = part2;
SmallerWord = part1;
}
}
protected bool Equals(WordCombo other)
{
return string.Equals(BiggerWord, other.BiggerWord, StringComparison.InvariantCultureIgnoreCase)
&& string.Equals(SmallerWord, other.SmallerWord, StringComparison.InvariantCultureIgnoreCase);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((WordCombo) obj);
}
public override int GetHashCode()
{
unchecked
{
return ((BiggerWord != null ? BiggerWord.ToLowerInvariant().GetHashCode() : 0)*397) ^
(SmallerWord != null ? SmallerWord.ToLowerInvariant().GetHashCode() : 0);
}
}
}
}
}
I am using a certain method of mine over and over again. Therefore, I tend to import this class to all of my projects, where I have to access the IsolatedStorage of a Windows Phone-Device.
But, it doesn't really seem elegant to me.
Take a look:
public static Object getFileContent (String filename, String returntype)
{
IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
Object returnobj = new Object();
List<String> list = new List<String>();
String r;
IsolatedStorageFileStream fileStream = isf.OpenFile(filename, FileMode.Open, FileAccess.Read);
StreamReader reader = new StreamReader(fileStream);
if (returntype.Equals("list"))
{
while ((r = reader.ReadLine()) != null)
{
list.Add(r);
}
returnobj = list;
}
else if (returntype.Equals("string"))
{
r = reader.ReadLine();
returnobj = r;
}
fileStream.Close();
reader.Close();
return returnobj;
}
My main issue is the paramter returntype. It's a obviously a string.
I'd like to have it as the type directly. But that didn't work on my last attempt.
Also, when I use this method, like for instance:
string random = (string) MyFavClass.getFileContent("randomFile","string");
I have to convert the return type of that method once again, before I can use it.
Just write two methods: getFileContentAsString and getFileContentAsList. You're not getting any benefit of genericness here if you can only support exactly two types.
You could use the strategy pattern if you're going to have an arbitrary amount of return types.
public static T GetFileContents<T>(String filename, Func<StreamReader, T> readMethod)
{
// initialize stuff
using (StreamReader reader = new StreamReader(...))
{
return readMethod(reader);
}
}
public static string ReadStreamAsString(StreamReader reader)
{
return reader.ReadLine();
}
public static List<string> ReadStreamAsList(StreamReader reader)
{
var list = new List<string>();
while ((r = reader.ReadLine()) != null)
{
list.Add(r);
}
return list;
}
And to use it:
string myString = GetFileContents("foo.txt", ReadStreamAsString);
List<string> myList = GetFileContents("bar.xml", ReadStreamAsList);
My generics are probably off, but hopefully it conveys the right idea.
Untested, but I would try to do something like this:
public static T getFileContent (String filename, Func<StreamReader, T> process)
{
IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
Object returnobj = new Object();
List<String> list = new List<String>();
String r;
IsolatedStorageFileStream fileStream = isf.OpenFile(filename, FileMode.Open, FileAccess.Read);
StreamReader reader = new StreamReader(fileStream);
try{
return process(reader);
}
finally{
fileStream.Close();
reader.Close();
}
}
I'm sure this is error-prone as I have it, but the idea is to pass in a converter function that will handle whatever type you want to return.
Assuming:
Readonly, forward only acces is all that's required from the List; and
It is desired to treat the results of both possibilities identically in the application code.
Then he following would work:
public abstract class MySequence : IEnumerable<string> {
protected string Filename { get; private set; }
public MySequence(string filename) {
Filename = filename;
}
IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); }
public IEnumerator<string> GetEnumerator() {
using (var isf = IsolatedStorageFile.GetUserStoreForApplication())
using (var stream = isf.OpenFile(Filename, FileMode.Open, FileAccess.Read))
using (var reader = new StreamReader(stream)) {
return GetEnumerator(reader);
}
}
protected abstract IEnumerator<string> GetEnumerator(StreamReader reader);
}
public class MyListSequence : MySequence, IEnumerable<string> {
public MyListSequence(string filename) : base(filename) {}
protected override IEnumerator<string> GetEnumerator(StreamReader reader) {
while (! reader.EndOfStream) yield return reader.ReadLine();
}
}
public class MyStringSequence : MySequence, IEnumerable<string> {
public MyStringSequence(string filename) : base(filename) {}
protected override IEnumerator<string> GetEnumerator(StreamReader reader) {
yield return reader.ReadLine();
}
}
Usage would be like this:
foreach (var s in (new MyListSequence("fred"))) { Console.WriteLine(s); }
foreach (var s in (new MyStringSequence("fred"))) { Console.WriteLine(s); }
A particular advantage of this mechanism, when ti applies,is that no storage needs to be allocated for the List; eaxh text line is simply read and returned by the iterator.
I have read many codes on this but none happened to solve the problem. first the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace Serialization
{
class Program
{
static void Main(string[] args)
{
using (MoveSaver objSaver = new MoveSaver(#"C:\1.bin"))
{
MoveAndTime mv1, mv2;
mv1.MoveStruc = "1";
mv1.timeHLd = DateTime.Now;
objSaver.SaveToFile(mv1);
mv2.MoveStruc = "2";
mv2.timeHLd = DateTime.Now;
objSaver.SaveToFile(mv2);
}
using (MoveSaver svrObj = new MoveSaver())
{
MoveAndTime[] MVTobjs = svrObj.DeSerializeObject(#"C:\1.bin");
foreach (MoveAndTime item in MVTobjs)
{
//Do Something
}
}
}
}
public class MoveSaver:IDisposable
{
public void Dispose()
{
if (fs != null)
{
fs.Close();
}
}
FileStream fs;
StreamWriter sw;
public string filename { get; set; }
public MoveSaver(string FileName)
{
this.filename = FileName;
fs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite);
}
public MoveSaver()
{
}
~MoveSaver()
{
if (fs != null)
{
fs.Close();
}
}
public MoveAndTime[] DeSerializeObject(string filename)
{
MoveAndTime[] objectToSerialize;
Stream stream = File.Open(filename, FileMode.Open);
BinaryFormatter bFormatter = new BinaryFormatter();
objectToSerialize = (MoveAndTime[])bFormatter.Deserialize(stream);
stream.Close();
return objectToSerialize;
}
public bool SaveToFile(MoveAndTime moveTime)
{
try
{
BinaryFormatter bformatter = new BinaryFormatter();
bformatter.Serialize(fs, moveTime);
return true;
}
catch (Exception)
{
return false;
}
}
}
[Serializable]
public struct MoveAndTime
{
public string MoveStruc;
public DateTime timeHLd;
}
}
The code mimics a need for saving all actions of user on the program. to be later shown on that program (say you play cards or so and you want to review :D what has happened). The problem is when DeSerializeObject function is called the line objectToSerialize = (MoveAndTime[])bFormatter.Deserialize(stream); throws an exception (definitely in runtime) that the cast from a single object to array is not valid:
Unable to cast object of type
'Serialization.MoveAndTime' to type
'Serialization.MoveAndTime[]'.
Any idea? Any improvement or total change of approach is appreciated.
You're saving a single MoveAndTime instance to the file, but you're trying to read an array of them.
Please modify your main block like this. I think it achieves what you want.
static void Main(string[] args)
{
using (MoveSaver objSaver = new MoveSaver(#"C:\1.bin"))
{
MoveAndTime[] MVobjects = new MoveAndTime[2];
MoveAndTime mv1, mv2;
mv2 = new MoveAndTime();
mv1 = new MoveAndTime();
mv1.MoveStruc = "1";
mv1.timeHLd = DateTime.Now;
mv2.MoveStruc = "2";
mv2.timeHLd = DateTime.Now;
MVobjects[0] = new MoveAndTime();
MVobjects[0] = mv1;
MVobjects[1] = new MoveAndTime();
MVobjects[1] = mv2;
objSaver.SaveToFile(MVobjects);
}
using (MoveSaver svrObj = new MoveSaver())
{
MoveAndTime[] MVTobjs = svrObj.DeSerializeObject(#"C:\1.bin");
foreach (MoveAndTime item in MVTobjs)
{
//Do Something
Console.WriteLine(item.MoveStruc);
Console.WriteLine(item.timeHLd);
}
}
}
Thanks