good morning, I'm having trouble with the following. I'm reading the contents of a file (. txt) in a folder, but what I want now is to print the contents of the files into a textbox, but I'm having problems with that.
what I have to code this is.
FolderBrowserDialog Lectura = new FolderBrowserDialog();
DialogResult response = Lectura.ShowDialog();
if (response == DialogResult.OK)
{
string[] files = Directory.GetFiles(Lectura.SelectedPath);
ListBox archivosListBox = new ListBox();
archivosListBox.Items.AddRange(files);
int tamanoLista = archivosListBox.Items.Count;
List <string[]> Miarchivo = new List<string[]>();
foreach (string archivos in archivosListBox.Items)
{
Miarchivo.Add(System.IO.File.ReadAllLines(archivos));
}
string[] leerArchivo;
int j =Miarchivo.Count;
for (int i = 0; i<tamanoLista; i++)
{
leerArchivo = Miarchivo[i];
for (int k = 0; k < Miarchivo[i].Count(); k++)
{
//textBox1.Text += leerArchivo[k] ;
}
}
}
You need to place a newline character after each entry in your TextBox. Change your code to following:
for (int k = 0; k < Miarchivo[i].Count(); k++)
{
textBox1.Text += leerArchivo[k] + Environment.NewLine;
}
More reading: Environment.NewLine Property (MSDN).
Use ReadAllText instead of ReadAllLines and replace entire loop with string join:
List<string> Miarchivo = new List<string>();
foreach (string archivos in archivosListBox.Items)
Miarchivo.Add(File.ReadAllText(archivos));
textBox1.Text = String.Join(Environment.NewLine, Miarchivo);
Another (probably better solution) is usage of TextBox.Lines property and getting files content with LINQ:
textBox1.Lines = archivosListBox.Items
.Cast<string>()
.SelectMany(archivos => File.ReadLines(archivos))
.ToArray();
You'd rather update textBox1.Text once in order to avoid constant repainting:
if (response == DialogResult.OK)
{
string[] files = Directory.GetFiles(Lectura.SelectedPath);
ListBox archivosListBox = new ListBox();
archivosListBox.Items.AddRange(files);
int tamanoLista = archivosListBox.Items.Count;
List <string[]> Miarchivo = new List<string[]>();
foreach (string archivos in archivosListBox.Items)
{
Miarchivo.Add(System.IO.File.ReadAllLines(archivos));
}
// Output into textBox1
StringBuilder sb = new StringBuilder();
foreach(String[] leerArchivo in Miarchivo)
foreach(String item in leerArchivo) {
if (sb.Length > 0)
sb.AppendLine(); // <- Or other deriver, e.g. sb.Append(';');
sb.Append(item);
}
// Pay attention: textBox1 has been updated once only
textBox1.Text = sb.ToString();
}
Based on your comments it sounds like you just need a line break at the end of each line:
textBox1.Text += leerArchivo[k] + Environment.NewLine ;
Related
I have a CSV file like this:
1,01/01/2001,hello
2,19/09/2013,world
3,12/05/2016,world
4,13/05/2016,hello
5,12/12/2012,world
6,05/02/2006,world
7,06/03/2011,hello
I have this set of code from a question I asked yesterday:
string parts = new StringReader(#"C:\input.txt").ReadToEnd();
string[] lines = parts.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
StringBuilder sb = new StringBuilder();
List<string> dates = new List<string>();
for (int i = 0; i < lines.Length; i++)
{
string[] data = lines[i].Split(new string[] { "," }, StringSplitOptions.None);
dates.Add(data[1]);
}
var datesSorted = dates.OrderBy(x => DateTime.ParseExact(x, "dd/MM/yyyy", null));
foreach (string s in datesSorted)
{
sb.AppendLine(s + "<br />");
}
Label1.Text = sb.ToString();
The above code works just fine but now I have another problem. I want to add an if statement within the code to only display the chosen value's date and all I could think of is doing either something like this:
string parts = new StringReader(#"C:\input.txt").ReadToEnd();
string[] lines = parts.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
StringBuilder sb = new StringBuilder();
List<string> dates = new List<string>();
for (int i = 0; i < lines.Length; i++)
{
string[] data = lines[i].Split(new string[] { "," }, StringSplitOptions.None);
dates.Add(data[1]);
var datesSorted = dates.OrderBy(x => DateTime.ParseExact(x, "dd/MM/yyyy", null));
if (data[2] == "hello")
{
foreach (string s in datesSorted)
{
sb.AppendLine(s + "<br />");
}
Label1.Text = sb.ToString();
}
}
Or placing the if statement within the foreach loop, which results in the same output:
01/01/2001
01/01/2001
19/09/2013
12/05/2016
13/05/2016
01/01/2001
05/02/2006
06/03/2011
12/12/2012
19/09/2013
12/05/2016
13/05/2016
It seems to me that you could make your code much simpler with LINQ.
Try this:
var lines = File.ReadAllLines(#"C:\input.txt");
var query =
from line in lines
let data = line.Split(',')
where data[2] == "hello"
orderby DateTime.ParseExact(data[1], "dd/MM/yyyy", null)
select data[1];
var dates = query.ToList();
Label1.Text = String.Join("", dates.Select(x => x + "<br />"));
This handles the if statement you wanted with the where data[2] == "hello" in the query.
One of the things you may want to consider doing instead is to use an intermediate class to represent a csv line, e.g.
private class CSVEntry
{
public int EntryNo { get; set; }
public DateTime Date { get; set; }
public string Text { get; set; }
}
And then change your data loading to:
List<CSVEntry> csvlist = new List<CSVEntry>();
for (int i = 0; i < lines.Length; i++)
{
string[] data = lines[i].Split(new string[] { "," }, StringSplitOptions.None);
csvlist.Add(new CSVEntry() { EntryNo = Int32.Parse(data[0]), Date = DateTime.ParseExact(data[1], "dd/MM/yyyy", null), Text = data[2] });
}
Then chose what to display by doing something like:
var results = csvlist.Where(x => x.Text == "hello").OrderBy(x => x.Date);
Label1.Text = String.Join("<br />", results.Select(x => x.Date.ToString("dd/MM/yyyy"));
The benefit to doing it this way is that you can re use what you have loaded in previously, and any changes to display new values can be done in a LINQ projection.
Edit:
I suggest you move the 'loading' into a separate function, e.g.
public List<CSVEntry> LoadData(string filename, ... other params) {...
and then the part where you want to find specific entries
public IEnumerable<CSVEntry> FindByName(List<CSVEntry> loadedData, ICollection<string> targetNames)
{
return loadedData.Where(x => targetNames.Contains(x.Text));
}
Moving on, you can call it by passing an array/list to the function
var results = FindByName(csvList, new string[] { "hello", "world"});
I do have the following CSV file:
34416;15,14;22,67;71,51;73,59;73,1;67,19;64,07;64,29;67,94; ...
...
Now, I would like to save the first number 34416 and replace every semicolon with it, but do not replace the first semicolon.
Now, there is the next line. Same procedure, just another number at the beginning.
public List<string> ConvertFile()
{
string allLines = string.Empty;
allLines = GetLinesFromFile();
for (int i = 0; i < GetLinesFromFile().Length; i++)
{
string[] split = allLines.Split(new Char[] { ';' });
string number = split[i];
allLines.Replace(";", ";34416|");
}
List<string> re = new List<string>();
re.Add(allLines);
return re;
}
I am very new to C# coding - could you please help me?
Thanks in advance.
You need to rethink your logic. First of all GetLinesFromFile() seems to return a string; I'd have that return a List<string> instead (with each line from the file being one string). And then you can do this:
public List<string> ConvertFile()
{
var result = new List<string>();
foreach(var line in GetLinesFromFile())
{
var lineParts = line.Split(';');
var fixedLine = line.Replace(";", ";" + lineParts[0] + "|");
result.Add(fixedLine);
}
return result;
}
try this
public List<string> ConvertFile( )
{
string allLines = GetLinesFromFile();
List<string> re = new List<string>();
for (int i = 0; i < allLines.Length; i++)
{
string[] split = allLines.Split(new Char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
allLines.Replace(";", ";" + split[0] + "|");
re.Add(allLines);
}
return re;
}
Is there any way to sort lines in winforms richtextbox preserving RTF formatting?
var lines = edit.Lines.OrderBy(s => s);
edit.Lines = lines.ToArray();
do the job fine, but, obviously, loosing any RTF formatting.
I have slightly changed the snippet of TaW:
1. Adding "unique" might break the very first line formatting
2. Besides "\par" tag there is also "\pard"
Here is a snippet (thanks again to TaW!):
private void cmdSort_Click(object sender, EventArgs e)
{
const string PARD = "\\pard";
var pard = Guid.NewGuid().ToString();
var pos1 = edit.Rtf.IndexOf(PARD, StringComparison.Ordinal) + PARD.Length;
if (pos1 < 0) return;
var header = edit.Rtf.Substring(0, pos1);
var body = edit.Rtf.Substring(pos1);
body = body.Replace("\\pard", pard);
var lines = body.Split(new[] { "\\par" }, StringSplitOptions.None);
var lastFormat = "";
var sb = new StringBuilder();
var rtfLines = new SortedList<string, string>();
foreach (var line in lines)
{
var ln = line.Replace(pard, "\\pard");
var temp = ln.Replace("\r\n", "").Trim();
if (temp.Length > 0 && temp[0] != '\\')
{
rtfLines.Add(temp.Trim(), lastFormat + " " + ln);
}
else
{
var pos2 = temp.IndexOf(' ');
if (pos2 < 0)
{
rtfLines.Add(temp.Trim(), ln);
}
else
{
rtfLines.Add(temp.Substring(pos2).Trim(), ln);
lastFormat = temp.Substring(0, pos2);
}
}
}
foreach (var key in rtfLines.Keys.Where(key => key != "}"))
{
sb.Append(rtfLines[key] + "\\par");
}
edit.Rtf = header + sb;
}
Here is a code snippet that seems to work if the file has neither images nor tables embedded..
It uses two RTF boxes. In my tests they sorted alright and kept all formatting intact.
private void button4_Click(object sender, EventArgs e)
{
string unique = Guid.NewGuid().ToString() ;
richTextBox1.SelectionStart = 0;
richTextBox1.SelectionLength = 0;
richTextBox1.SelectedText = unique;
int pos1 = richTextBox1.Rtf.IndexOf(unique);
if (pos1 >= 0)
{
string header = richTextBox1.Rtf.Substring(0, pos1);
string header1 = "";
string header2 = "";
int pos0 = header.LastIndexOf('}') + 1;
if (pos0 > 1) { header1 = header.Substring(0, pos0); header2 = header.Substring(pos0); }
// after the header comes a string of formats to start the document
string[] formats = header2.Split('\\');
string firstFormat = "";
string lastFormat = "";
// we extract a few important character formats (bold, italic, underline, font, color)
// to keep with the first line which will be sorted away
// the lastFormat variable holds the last formatting encountered
// so we can add it to all lines without formatting
// (and of course we are really talking about paragraphs)
foreach (string fmt in formats)
if (fmt[0]=='b' || ("cfiu".IndexOf(fmt[0]) >= 0 && fmt.Substring(0,2)!="uc") )
lastFormat += "\\" + fmt; else firstFormat += "\\" + fmt;
// add the rest to the header
header = header1 + firstFormat;
// now we remove our marker from the body and split it into paragraphs
string body = richTextBox1.Rtf.Substring(pos1);
string[] lines = body.Replace(unique, "").Split(new string[] { "\\par" }, StringSplitOptions.None);
StringBuilder sb = new StringBuilder();
// the soteredlist will contain the unformatted text as key and the formatted one as valaue
SortedList<string, string> rtfLines = new SortedList<string, string>();
foreach (string line in lines)
{
// cleanup
string line_ = line.Replace("\r\n", "").Trim();
if (line_[0] != '\\' ) rtfLines.Add(line_, lastFormat + " " + line);
else
{
int pos2 = line_.IndexOf(' ');
if (pos2 < 0) rtfLines.Add(line_, line);
else
{
rtfLines.Add(line_.Substring(pos2).Trim(), line);
lastFormat = line_.Substring(0, pos2);
}
}
}
foreach (string key in rtfLines.Keys) if (key != "}") sb.Append(rtfLines[key] + "\\par");
richTextBox2.Rtf = header + sb.ToString();
}
Of course this is really q&d and not ready for serious production; but it looks like a start.
EDIT 2: I changed the code to fix a bug with the first line's format and added some comments. This should work a lot better, but is still a hack that must be adapted to the real input files..
RichTextBox has a property Rtf that would keep RTF formatting.
[BrowsableAttribute(false)]
public string Rtf { get; set; }
I want to make this:
anywhere.com/file/mybirthday.avi
anywhere.com/file/yourbirthday.avi
somewhere.com/file/mybirthday.avi
somewhere.com/file/yourbirthday.avi
To This:
anywhere.com/file/mybirthday.avi
somewhere.com/file/mybirthday.avi
##############
anywhere.com/file/yourbirthday.avi
somewhere.com/file/yourbirthday.avi
I found filenames with regex. And I sorted them. So my codes are here:
private void button1_Click(object sender, EventArgs e)
{
string gelenler = textBox2.Text;
gelenler = gelenler.Replace("\r\n\r\n", "\r\n");
string cikti = string.Empty;
string regex = #"([^\/\\]+\.\w+)$";
string[] parca = Regex.Split(gelenler, "\r\n");
string[] parca2 = new string[parca.Length];
for (int i = 0; i < parca.Length; i++)
{
string ad = match(regex, parca[i]);
parca2[i] = ad;
}
Array.Sort(parca2);
for (int j = 0; j < parca2.Length; j++)
{
for (int i = 0; i < parca2.Length; i++)
{
if (parca2[i].IndexOf(match(regex,parca[j]))!=-1)
{
textBox1.Text += parca[i] + Environment.NewLine;
parca[i] = "";
}
textBox1.Text += "#############" + Environment.NewLine;
}
}
}
private string match(string regex, string html, int i = 1)
{
return new Regex(regex, RegexOptions.Multiline).Match(html).Groups[i].Value.Trim();
}
But didn't working. Any ideas ?
//Sorry my English
I think always the best idea is to use existing .net framework stuff, as in this case Path.GetFileName:
var strings = new[]
{
"anywhere.com/file/mybirthday.avi",
"anywhere.com/file/yourbirthday.avi",
"somewhere.com/file/mybirthday.avi",
"somewhere.com/file/yourbirthday.avi"
};
strings = strings.OrderBy(x => Path.GetFileName(x)).ToArray();
foreach (var s in strings)
{
Console.WriteLine(s);
}
Console.ReadKey();
I think you mean grouping the files; in which case the following code can be used:
IEnumerable<IGrouping<string, string>> groups = strings.GroupBy(x => Path.GetFileName(x)).OrderBy(g => g.Key);
foreach (var group in groups)
{
foreach (var str in group)
{
Console.WriteLine(str);
}
Console.WriteLine("#############");
}
You should use the Uri class. Use the Segements property in order to get the file name (it will be the last segment).
var uris = new[]
{
new Uri("http://anywhere.com/file/mybirthday.avi"),
new Uri("http://anywhere.com/file/yourbirthday.avi"),
new Uri("http://somewhere.com/file/mybirthday.avi"),
new Uri("http://somewhere.com/file/yourbirthday.avi")
};
var filename = uris.OrderBy(x => x.Segments[x.Segments.Length - 1]).ToArray();
foreach (var f in filename)
{
Console.WriteLine(f);
}
I have a situation where I am given a text file with text formatted as follows:
C:\Users\Admin\Documents\report2011.docx: My Report 2011
C:\Users\Admin\Documents\newposter.docx: Dinner Party Poster 08
How would it be possible to trim the text file, so to trim the ":" and all characters after it.
E.g. so the output would be like:
C:\Users\Admin\Documents\report2011.docx
C:\Users\Admin\Documents\newposter.docx
Current Code:
private void button1_Click(object sender, EventArgs e)
{
using (StreamWriter sw = File.AppendText(#"c:\output.txt"))
{
StreamReader sr = new StreamReader(#"c:\filename.txt");
Regex reg = new Regex(#"\w\:(.(?!\:))+");
List<string> parsedStrings = new List<string>();
while (sr.EndOfStream)
{
sw.WriteLine(reg.Match(sr.ReadLine()).Value);
}
}
}
Not working :(
int index = myString.LastIndexOf(":");
if (index > 0)
myString= myString.Substring(0, index);
Edit - Added answer based on modified question. It can be condensed slightly, but left expanded for clarity of what's going on.
using (StreamWriter sw = File.AppendText(#"c:\output.txt"))
{
using(StreamReader sr = new StreamReader(#"input.txt"))
{
string myString = "";
while (!sr.EndOfStream)
{
myString = sr.ReadLine();
int index = myString.LastIndexOf(":");
if (index > 0)
myString = myString.Substring(0, index);
sw.WriteLine(myString);
}
}
}
Edited
StreamReader sr = new StreamReader("yourfile.txt");
Regex reg = new Regex(#"\w\:(.(?!\:))+");
List<string> parsedStrings = new List<string>();
while (!sr.EndOfStream)
{
parsedStrings.Add(reg.Match(sr.ReadLine()).Value);
}
sure. while reading each line, do a
Console.WriteLine(line.Substring(0,line.IndexOf(": "));
i'd use the answer given here Code to trim part of a text file in C# and find the 2nd occurrence and then use it in substring.
var s = #"C:\Users\Admin\Documents\report2011.docx: My Report 2011";
var i = GetNthIndex(s,':',2);
var result = s.Substring(i+1);
public int GetNthIndex(string s, char t, int n)
{
int count = 0;
for (int i = 0; i < s.Length; i++)
{
if (s[i] == t)
{
count++;
if (count == n)
{
return i;
}
}
}
return -1;
}
Assuming this is being done where the files are supposed to exist, you could handle this taking into account any colons in the (what I assume is) description by checking for the existence of the files after you get the index of the colon.
List<string> files = new List<string>();
files.Add(#"C:\Users\Admin\Documents\report2011.docx: My Report 2011");
files.Add(#"C:\Users\Admin\Documents\newposter.docx: Dinner Party Poster 08");
files.Add(#"C:\Users\Admin\Documents\newposter.docx: Dinner Party: 08");
int lastColon;
string filename;
foreach (string s in files)
{
bool isFilePath = false;
filename = s;
while (!isFilePath)
{
lastColon = filename.LastIndexOf(":");
if (lastColon > 0)
{
filename = filename.Substring(0, lastColon);
if (File.Exists(filename))
{
Console.WriteLine(filename);
isFilePath = true;
}
}
else
{
throw new FileNotFoundException("File not found", s);
}
}
}
Try this:
more faster:
string s = #"C:\Users\Admin\Documents\report2011.docx: My Report 2011";
string path = Path.GetDirectoryName(s) + s.Split(new char[] { ':' }) [1];
Console.WriteLine(path); //C:\Users\Admin\Documents\report2011.docx
you need import System.IO
you could use split:
string[] splitted= myString.Split(':');
Then you get an array where you take the first one.
var mySplittedString = splitted[0]
Have a look here if you need more information on this.
EDIT: In your case you get an array with the size of at least 3 so you need to get splitted[0] and splitted[ 1]