I'm reading a .txt file that contains 5 columns, but I only want to add the 5th column to a listbox, I tried IndexOf and Remove but it doesn't work, any suggestions?
Within your inner reading loop you just use something like:
private static void Readfile(String filePath)
{
foreach(String line in ReadAllLines(filePath))
{
string[] tokens = line.Split(new char[] { 'X' });
listbox.Add(tokens[4]); // This should be your 5th column.
}
}
And replace the X with a comma, space, or whatever symbol you use to separate.
This should work for you but it assumes that the split will always be successful.
var columnFiveValues = File.ReadLines("fileName")
.Select(line => line.Split('\t')) // tsv
.Select(split => split[4]) // column 5
.ToArray(); // evaluate now
Related
New to C# and Linq. I've tried searching, and I cant seem to get anywhere.
I'm trying to format the last column in the file. It's a monetary value and I want to format it to display 2 decimal places.
This function is splitting the data and sorting the files. I think the formatting should happen when putting the file back together but I'm not sure how to implement this.
static void SortData(string directory, string outputDirectory)
{
var d = new DirectoryInfo(directory);
Console.WriteLine("Sorting Files...");
foreach (FileInfo fi in d.GetFiles())
{
// Read file
var fileContents = File.ReadAllText(directory+ fi.Name);
//split on carriage returns and line feeds, remove empty entries.
var lines = fileContents.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
//Split each line on Tab
var splitLines = lines.Select(l => l.Split(new[] { '\t' }));
//splitLines is now an array of arrays. Each splitLine entry is a line, and each entry of each splitline element is
//a single field... so we should be able to sort how we want, e.g. by first field then by second field:
var sortedLines = splitLines.OrderBy(sl => sl[0]).ThenBy(sl => sl[1]).ThenBy(sl => sl[2]).ThenBy(sl => sl[3]).ThenBy(sl => sl[4]).ThenBy(sl => sl[5]).ThenBy(sl => sl[6]);
//put back together as TSV - put tabs back.
var linesWithTabsAgain = sortedLines.Select(sl => string.Join("\t", sl));
//put carriage returns/linefeeds back
var linesWithCRLF = string.Join("\r\n", linesWithTabsAgain);
File.WriteAllText(outputDirectory + fi.Name, linesWithCRLF);
}
Console.WriteLine("Sorting Complete");
}
So what you need to do is that after you split your data, for each or the lines, parse the string value into the number and then format it back into string but with 2 digits.
Put the following line after var sortedLines = splitLines.....:
foreach(var sl in sortedLines)
{
sl[6]=decimal.Parse(sl[6]).ToString("F2");
}
I need to find distinct values of partial filenames in an array of filenames. I'd like to do it in one line.
So, I have something like that as a filenames:
string[] filenames = {"aaa_ab12345.txt", "bbb_ab12345.txt", "aaa_ac12345.txt", "bbb_ac12345"}
and I need to find distinct values for ab12345 part of it.
So I currently have something like that:
string[] filenames_partial_distinct = Array.ConvertAll(
filenames,
file => System.IO.Path.GetFileNameWithoutExtension(file)
.Split({"_","."}, StringSplitOptions.RemoveEmptyEntries)[1]
)
.Distinct()
.ToArray();
Now, I'm getting filenames that are of form of aaa_bbb_ab12345.txt. So, instead of referring to the second part of the filename, I need to refer to the second to the last.
So, how do I refer to an arbitrary element based on length of array in one line, if it's a result of Split method? Something along lines of:
Array.ConvertAll(filenames, file=>file.Split(separator)[this.Length-2]).Distinct().ToArray();
In other words, if a string method results in an array of strings, how do I immediately select element based on the length of array:
String.Split()[third from end, fifth from end, etc.];
If you use GetFileNameWithoutExtension there will be no extension and therefore splitting by '_' will do it. Then you can take the last part with .Last().
string[] filenames_partial_distinct = Array.ConvertAll(
filenames,
file => Path.GetFileNameWithoutExtension(file).Split('_').Last()
)
.Distinct()
.ToArray();
With the input
string[] filenames = { "aaa_ab12345.txt", "bbb_ab12345.txt",
"aaa_ac12345.txt", "bbb_ac12345", "aaa_bbb_ab12345.txt" };
You get the result
{ "ab12345", "ac12345" }
The StringSplitOptions.RemoveEmptyEntries is only required if there are filenames ending with _ (before the extension).
Seems you're looking for something like this:
string[] arr = filenames.Select(n => n.Substring(n.IndexOf("_") + 1, 7)).Distinct().ToArray();
I usually defer problems like this to regex. They are very powerful. This approach also gives you the opportunity to detect unexpected cases and handle them appropriately.
Here is a crude example, assuming I understood your requirements:
using System;
using System.Linq;
using System.Text.RegularExpressions;
public class Program
{
public static void Main()
{
string MyMatcher(string filename)
{
// this pattern may need work depending on what you need - it says
// extract that pattern between the "()" which is 2 characters and
// 4 digits, exactly; and can be found in `Groups[1]`.
Regex r = new Regex(#".*_(\w{2}\d{4}).*", RegexOptions.IgnoreCase);
Match m = r.Match(filename);
return m.Success
? m.Groups[1].ToString()
: null; // what should happen here?
}
string[] filenames =
{
"aaa_ab12345.txt",
"bbb_ab12345.txt",
"aaa_ac12345.txt",
"bbb_ac12345",
"aaa_bbb_ab12345.txt",
"ae12345.txt" // MyMatcher() return null for this - what should you do if this happens?
};
var results = filenames
.Select(MyMatcher)
.Distinct();
foreach (var result in results)
{
Console.WriteLine(result);
}
}
}
Gives:
ab1234
ac1234
This can be refined further, such as pre-compiled regex patterns, encapsulation in a class, etc.
I have a text-file with many lines, each line looks like this:
"string string double double" between each value is a space. I'd like to read out the first string and last double of every line and put these two values in a existing list. That is my code so far, but it doesnt really work.
private void bOpen_Click(object sender, RoutedEventArgs e)
{
bool exists = File.Exists(#"C:\Users\p2\Desktop\Liste.txt");
if (exists == true)
{
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(#"C:\Users\p2\Desktop\Liste.txt"))
{
Vgl comp = new Vgl();
comp.name = Abzahlungsdarlehenrechner.zgName;
comp.gErg = Abzahlungsdarlehenrechner.zgErg;
GlobaleDaten.VglDaten.Add(comp);
int i = 0;
string line = File.ReadLines(#"Liste.txt").Skip(0).Take(1).First();
while ((line = sr.ReadLine()) != null)
{
sb.Append((line));
listBox.Items.Add(line);
GlobaleDaten.VglDaten.Add(comp);
i++;
}
}
}
I have already read this, but it didnt help How do I read specific value[...]
You can try Linq:
var source = File
.ReadLines(#"C:\Users\p2\Desktop\Liste.txt")
.Select(line => line.Split(' '))
.Select(items => new Vgl() {
name = items[0],
gErg = double.Parse(items[3])
});
// If you want to add into existing list
GlobaleDaten.VglDaten.AddRange(source);
// If you want to create a new list
//List<Vgl> list = source.ToList();
how about
List<Vgl> Result = File.ReadLines(#"C:\Users\p2\Desktop\Liste.txt")
.Select(x => new Vgl()
{
name = x.Split(' ').First(),
gErg = decimal.Parse(x.Split(' ').Last(), NumberStyles.AllowCurrencySymbol)
})
.ToList();
I would avoid storing money within doulbe values because this could lead to rounding issues. Use decimal instead. Examples here: Is a double really unsuitable for money?
You can use:
string[] splitBySpace = line.Split(' ');
string first = splitBySpace.ElementAt(0);
decimal last = Convert.ToDecimal(splitBySpace.ElementAt(splitBySpace.Length - 1));
Edit : To Handle Currency symbol:
string[] splitBySpace = line.Split(' ');
string pattern = #"[^0-9\.\,]+";
string first = splitBySpace.ElementAt(0);
string last = (new Regex(pattern)).Split(splitBySpace.ElementAt(splitBySpace.Length - 1))
.FirstOrDefault();
decimal lastDecimal;
bool success = decimal.TryParse(last, out lastDecimal);
I agree with #Dmitry and fubo, if you are looking for alternatives, you could try this.
var source = File
.ReadLines(#"C:\Users\p2\Desktop\Liste.txt")
.Select(line =>
{
var splits = line.Split(' '));
return new Vgl()
{
name = splits[0],
gErg = double.Parse(splits[3])
};
}
use string.split using space as the delimiter on line to the string into an array with each value. Then just access the first and last array element. Of course, if you aren't absolutely certain that each line contains exactly 4 values, you may want to inspect the length of the array to ensure there are at least 4 values.
reference on using split:
https://msdn.microsoft.com/en-us/library/ms228388.aspx
Read the whole file as a string.
Split the string in a foreach loop using \r\n as a row separator. Add each row to a list of strings.
Iterate through that list and split again each record in another loop using space as field separator and put them into another list of strings.
Now you have all the four fields containig one row. Now just use First and Last methods to get the first word and the last number.
I have an MVC app which I need to store information into the database. I get a string value e.g. as
string a = "a,b,c";
I then split the string by removing the commas as
string[] b = a.Split(',');
Now before I save to database I have to add the comma back in and this is where I'm kind of stuck. I can add the comma however one gets added to the end of the string too which I don't want. If I do TrimEnd(',') it removes every comma. Can someone tell me where I'm going wrong please. I'm adding the comma back as:
foreach(var items in b)
{
Console.WriteLine(string.Format("{0},", items));
}
Please note I have to split the comma first due to some validation which needs to be carried out before saving to DB
The expected result should be for example
a,b,c
In stead I get
a,b,c,
Update - The below is the code I'm using In my MVC app after Bruno Garcia answer
string[] checkBoxValues = Request.Form["location"].Split(',');
foreach(var items in checkBoxValues)
{
if (!items.Contains("false"))
{
UsersDto.Location += string.Join(",", items);
}
}
Try:
string.Join(",", b);
This will add a ',' in between each item of your array
Based on the code you posted this is what I think you need
UsersDto.Location = string.Join(
",",
Request.Form["location"]
.Split(',')
.Where(item => !item.Contains("false")));
That will split the values in Request.Form["location"] on comma. Then filter out items that contain "false" as a substring, and finally join them back together with a comma.
So a string like "abc,def,blahfalseblah,xyz" would become "abc,def,xyz".
You can just use String.Join then?
var result = String.join(",", b); // a,b,c
Full document: https://msdn.microsoft.com/en-us/library/57a79xd0(v=vs.110).aspx
it can do
string[] checkBoxValues = Request.Form["location"].Split(',');
string s = "";
foreach (var items in checkBoxValues)
{
if (!items.Contains("false"))
{
s = s + string.Format("{0},", items);
}
}
UsersDto.Location = s.TrimEnd(',');
I have a dat file that looks like this:
and I would like to turn this data into a matrix of some sort that includes values for the empty spaces. Any idea how to approach this?
If you wish to preserve the empty spaces then you may need to treat the data as fixed width columns.
https://codereview.stackexchange.com/questions/27782/how-to-read-fixed-width-data-fields-in-net
If it turns out that the data is tab delimited as #WaiHaLee suggests then just split the lines using the tab character. For example:
//read all lines
var lines = System.IO.File.ReadAllLines("C:/path/to/file.txt");
//loop through all lines
foreach(var line in lines)
{
//split the line
var splitString = line.Split(new char[] { '\t' });
//pull out some data from the 6th column
double avDP = double.Parse(splitString[5]);
//save the data wherever you want
}