I have a textfile that looks like this :
John,Gauthier,blue,May
Henry,Ford,Red,June
James,Bond,Orange,December
I want to split it into a two dimensional string array so I could separate each lines then each words. Ex:
mystring[0][0] = "John"
mystring[1][3] = "June"
mystring[2][2] = "Orange"
Here's what I did right now:
string[] words = new string [100];
System.IO.StreamReader myfile = new System.IO.StreamReader("c:\\myfile.csv");
while (fichier.Peek() != -1)
{
i++;
words = myfile.ReadLine().Split(',');
}
I'm stuck. I'm able to split it into a one dimensional string array but not into a two dimensional string array. I guess I need to split it two times ; First time with '\n' and the second time with ',' and then put those two together.
This is actually a one-liner:
File.ReadLines("myfilename.txt").Select(s=>s.Split(',')).ToArray()
Since this is a beginner question, here's what's going on:
File.ReadLines(filename) returns a collection of all lines in your text file
.Select is an extension method that takes a function
s=>s.Split(',') is the function, it splits the string s by all commas and returns an array of strings.
.ToArray() takes the collection of string arrays created by .Select and makes an array out of that, so you get array of arrays.
Try this
var str = File.ReadAllText("myfile.csv");
var arr = str.Split(new string[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);
var multi = arr.Select(x => x.Split(',')).ToArray();
Try:
var First = new string [100];
var Sec = new string [100];
System.IO.StreamReader myfile = new System.IO.StreamReader("c:\\myfile.csv");
while (fichier.Peek() != -1)
{
i++;
var buff = myfile.ReadLine().Split(',');
First[i] = buff[0];
Sec[i] = buff[1];
}
Other idea, use a XML serilizer to serilize your hole Object. Two extensions for this:
public static void SaveAsXML(this Object A, string FileName)
{
var serializer = new XmlSerializer(A.GetType());
using (var textWriter = new StreamWriter(FileName))
{
serializer.Serialize(textWriter, A);
textWriter.Close();
}
}
public static void LoadFromXML(this Object A, string FileName)
{
if (File.Exists(FileName))
{
using (TextReader textReader = new StreamReader(FileName))
{
XmlSerializer deserializer = new XmlSerializer(A.GetType());
A = (deserializer.Deserialize(textReader));
}
}
}
Add than in any Static class and call:
YourSaveClassWhitchContainsYourArray.SaveAsXML("Datastore.xml");
or
YourSaveClassWhitchContainsYourArray.LoadFromXML("Datastore.xml");
Related
I have a function that reads a CSV file and returns a list of objects whose parameters depends on the content of the CSV. Right now it works if I hardcode one object. I would like to return different object types.
public static List<CSVObject> ImportCsvIntoObject(string csvFile, string delimiter)
{
List<CSVObject> list = new List<CSVObject>();
using (TextFieldParser csvReader = new TextFieldParser(csvFile))
{
csvReader.SetDelimiters(new String[] { delimiter });
csvReader.HasFieldsEnclosedInQuotes = true;
//Parse the file and creates a list of CSVObject
//example with a csv file with 3 columns
while (!csvReader.EndOfData)
{
string[] fieldData = csvReader.ReadFields();
string parameter1 = fieldData[0];
string parameter2 = fieldData[1];
string parameter3 = fieldData[2];
CSVObject example = new CSVObject(parameter1, parameter2, parameter3);
list.Add(example);
}
}
return list;
}
The following solution works but I'm not sure if there are not better ways to do this.
public static List<Object> ImportCsvIntoList(string csvFile, string delimiter, Type type)
{
List<Object> list = new List<Object>();
using (TextFieldParser csvReader = new TextFieldParser(csvFile))
{
csvReader.SetDelimiters(new String[] { delimiter });
csvReader.HasFieldsEnclosedInQuotes = true;
while (!csvReader.EndOfData)
{
string[] fieldData = csvReader.ReadFields();
string parameter1 = fieldData[0];
string parameter2 = fieldData[1];
string parameter3 = fieldData[2];
var example = Activator.CreateInstance(type, parameter1, parameter2, parameter3);
list.Add(example);
}
}
return list;
}
Furthermore, right now it only works with a hardcoded amount of parameters. Unfortunately, my objects all have a different amount of parameters. How can I call Activator.CreateInstance with different amount of parameters ?
It is my first question so sorry if it isn't written properly, suggestion to improve are more than welcome.
The following might work for you using generics and delegates
public static List<T> ImportCsvIntoObject<T>(string csvFile, string delimiter, Func<List<string>, T> createObject)
{
List<T> list = new List<T>();
using (TextFieldParser csvReader = new TextFieldParser(csvFile))
{
csvReader.SetDelimiters(new String[] { delimiter });
csvReader.HasFieldsEnclosedInQuotes = true;
//Parse the file and creates a list of CSVObject
//example with a csv file with 3 columns
while (!csvReader.EndOfData)
{
string[] fieldData = csvReader.ReadFields();
CSVObject example = createObject(fieldData.ToList())
list.Add(example);
}
}
return list;
}
And you would call the following using:
List<CSVObject> objectList = ImportCsvIntoObject("csvData", ",", (list) => { new CSVObject(list[0], list[1], list[2]); });
The Activator.CreateInstance() function can take an array of parameters, so that you might not know how many you need before runtime, but as you read your CSV, you create arrays corresponding to the number of parameters needed for this particular object (fortunately, your field data object seems to already do this).
So it could be like this :
string[] fieldData = csvReader.ReadFields();
var example = Activator.CreateInstance(type, fieldData);
list.Add(example);
This is because the Activator.CreateInstance function uses the params keyword
Hi I am fairly new to coding, I have a piece of code that searches for a string and replaces it with another string like so:
var replacements = new[]{
new{Find="123",Replace="Word one"},
new{Find="ABC",Replace="Word two"},
new{Find="999",Replace="Word two"},
};
var myLongString = "123 is a long 999 string yeah";
foreach(var set in replacements)
{
myLongString = myLongString.Replace(set.Find, set.Replace);
}
If I want to use a CSV file that contains a lot of words and their replacements, for example, LOL,Laugh Out Loud, and ROFL, Roll Around Floor Laughing. How would I implement that?
Create a text file that looks like (you could use commas, but I like pipes (|)):
123|Word One
ABC|Word Two
999|Word Three
LOL|Laugh Out Loud
ROFL|Roll Around Floor Laughing
Then create a tiny helper class:
public class WordReplace
{
public string Find { get; set; }
public string Replace { get; set; }
}
And finally, call this code:
private static string DoWordReplace()
{
//first read in the data
var fileData = File.ReadAllLines("WordReplace.txt");
var wordReplacePairs = new List<WordReplace>();
var lineNo = 1;
foreach (var item in fileData)
{
var pair = item.Split(new[] {'|'}, StringSplitOptions.RemoveEmptyEntries);
if (pair.Length != 2)
{
throw new ApplicationException($"Malformed file, line {lineNo}, data = [{item}] ");
}
wordReplacePairs.Add(new WordReplace{Find = pair[0], Replace = pair[1]});
++lineNo;
}
var longString = "LOL, 123 is a long 999 string yeah, ROFL";
//now do the replacements
var buffer = new StringBuilder(longString);
foreach (var pair in wordReplacePairs)
{
buffer.Replace(pair.Find, pair.Replace);
}
return buffer.ToString();
}
The result is:
Laugh Out Loud, Word One is a long Word Three string yeah, Roll Around Floor Laughing
I'm trying to read a text file, which contains proxys into a 2 dimensional array.
The text file looks like the following:
00.00.00.00:80
00.00.00.00:80
00.00.00.00:80
00.00.00.00:80
00.00.00.00:80
How could I seperate the ip from the port?`
So my array would look like the following:
[00.00.00.00][80]
Current code:
public void readProxyList(string FileName)
{
using (StreamReader sr = new StreamReader(FileName, Encoding.Default))
{
string text = sr.ReadToEnd();
string[] lines = text.Split('\r');
foreach (string s in lines)
{
}
}
}
If you are not expecting the file to be too large you could use File.ReadAllLines to read in each line. Then to split, just use String.Split with ':' as your token.
Example:
var lines = File.ReadAllLines(FileName));
var array = new string[lines.Length,2];
for(int i=0; i < lines.Length; i++)
{
var temp = lines[i].Split(':');
array[i,0] = temp[0];
array[i,1] = temp[1];
}
Edit
If you expect that the file may be large, instead of using ReadAllLines you can use File.ReadLines. This method returns an IEnumerable<string> and will not read the whole file at once. In this case, I would probably opt away from the 2d array and make a simple class (call it IpAndPort or something like that) and create a list of those.
Example:
public sealed class IpAndPort
{
public string Ip { get; private set; }
public string Port { get; private set; }
public IpAndPort (string ip, string port)
{
Ip = ip;
Port = port;
}
}
var list = new List<IpAndPort>();
foreach(var line in File.ReadLines(FileName))
{
var temp = line.Split(':');
list.Add(new IpAndPort(temp[0], temp[1]);
}
Try this:
public IEnumerable<string> GetProxyList(string FileName)
{
string[] allLines = File.ReadAllLines(FileName);
var result = new List<string>(allLines.Length);
foreach (string line in allLines)
{
var splittedLine = line.Split(':');
result.Add($"[{splittedLine[0]}][{splittedLine[1]}]");
}
return result;
}
I have list of string and each of that strings in list look like this: sim_pin: 1234. List have 24 strings, and I wanna to get each of that strings, separate string where separator will be : ( : and space), and save to list only that part who is right from separator.
EDIT:
Here is my code
string url = #"E:\Sims.log";
public static IEnumerable<DiverGate> GetData(string url)
{
Stream stream = File.Open(url, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (StreamReader sr = new StreamReader(stream))
{
string str = sr.ReadToEnd();
string[] lines = Regex.Split(str, "\r\n");
List<string> lista = new List<string>();
foreach (string line in lines)
{
lista.Add(line);
}
List<string> header = lista.GetRange(0, 23);
//I stop here and im out of idea
}
}
Something like this should work:
where input is your original list of strings
List<string> output = new List<string>();
input.ForEach(x=> output.Add(x.Split(new[] {": "},StringSplitOptions.None).Last()));
var List1 = new List<string>{"sim_pin: 1234", "sim_pin: 2345", "sim_pin: 3456"};
var List2 = new List<string>();
foreach (var s in List1) {
var ns = s.Split(':')[1].TrimStart(' ');
List2.Add(ns);
}
try this code:
for ( int i =0; i< yourList.Count(); i++) {
string s = yourList[i];
int i = s.indexOf(":");
s = s.Substring (i);
yourList.Insert(i, s);
}
First of all, i'm using the function below to read data from a pdf file.
public string ReadPdfFile(string fileName)
{
StringBuilder text = new StringBuilder();
if (File.Exists(fileName))
{
PdfReader pdfReader = new PdfReader(fileName);
for (int page = 1; page <= pdfReader.NumberOfPages; page++)
{
ITextExtractionStrategy strategy = new SimpleTextExtractionStrategy();
string currentText = PdfTextExtractor.GetTextFromPage(pdfReader, page, strategy);
currentText = Encoding.UTF8.GetString(ASCIIEncoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(currentText)));
text.Append(currentText);
pdfReader.Close();
}
}
return text.ToString();
}
As you can see , all data is saved in a string. The string looks like this:
label1: data1;
label2: data2;
label3: data3;
.............
labeln: datan;
My question: How can i get the data from string based on labels ?
I've tried this , but i'm getting stuck:
if ( string.Contains("label1"))
{
extracted_data1 = string.Substring(string.IndexOf(':') , string.IndexOf(';') - string.IndexOf(':') - 1);
}
if ( string.Contains("label2"))
{
extracted_data2 = string.Substring(string.IndexOf("label2") + string.IndexOf(':') , string.IndexOf(';') - string.IndexOf(':') - 1);
}
Have a look at the String.Split() function, it tokenises a string based on an array of characters supplied.
e.g.
string[] lines = text.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries);
now loop through that array and split each one again
foreach(string line in lines) {
string[] pair = line.Split(new[] {':'});
string key = pair[0].Trim();
string val = pair[1].Trim();
....
}
Obviously check for empty lines, and use .Trim() where needed...
[EDIT]
Or alternatively as a nice Linq statement...
var result = from line in text.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries)
let tokens = line.Split(new[] {':'})
select tokens;
Dictionary<string, string> =
result.ToDictionary (key => key[0].Trim(), value => value[1].Trim());
It's pretty hard-coded, but you could use something like this (with a little bit of trimming to your needs):
string input = "label1: data1;" // Example of your input
string data = input.Split(':')[1].Replace(";","").Trim();
You can do this by using Dictionary<string,string>,
Dictionary<string, string> dicLabelData = new Dictionary<string, string>();
List<string> listStrSplit = new List<string>();
listStrSplit = strBig.Split(';').ToList<string>();//strBig is big string which you want to parse
foreach (string strSplit in listStrSplit)
{
if (strSplit.Split(':').ToList<string>().Count > 1)
{
List<string> listLable = new List<string>();
listLable = strSplit.Split(':').ToList<string>();
dicLabelData.Add(listLable[0],listLable[1]);//Key=Label,Value=Data
}
}
dicLabelData contains data of all label....
i think you can use regex to solve this problem. Just split the string on the break line and use a regex to get the right number.
You can use a regex to do it:
Regex rx = new Regex("label([0-9]+): ([^;]*);");
var matches = rx.Matches("label1: a string; label2: another string; label100: a third string;");
foreach (Match match in matches) {
var id = match.Groups[1].ToString();
var data = match.Groups[2].ToString();
var idAsNumber = int.Parse(id);
// Here you use an array or a dictionary to save id/data
}