Split a text in blocks of text when encountering a defalult sign - c#

So, I have been working with some texts.
I've trying to separate the text in multiple blocks when I encountered '$'sign in text. In my example I used two richTextBox. I tried using lists, and Split() method but it didn't work so well.
StreamReader read = new StreamReader(#"texte\Senzatii\definirea&caracterizarea_senzatiilor.txt");
string lines = "";
int state = 1;
while ((lines = read.ReadLine()) != null)
{
if (lines == "$".ToString())
state = 2;
if (state == 1)
richTextBox1.Text = richTextBox1.Text + lines + "\n";
else
richTextBox2.Text = richTextBox2.Text + lines + "\n";
}
This method works, it splits the text into two block of texts, but it doesn't look so good. Is there a better way to split the text into two blocks of text, a more c# way, solution to do this ?

I tried using lists, and Split() method but it didn't work so well.
Hard to help with almost no informations. But if you want to split on this $ sign. What's wrong with:
string[] bothParts = File.ReadAllText(#"texte\Senzatii\definirea&caracterizarea_senzatiilor.txt")
.Split('$');
string firstPart = bothParts[0];
string secondPart = bothParts.ElementAtOrDefault(1);
richTextBox1.Text = firstPart;
richTextBox2.Text = secondPart;

Related

C# - split a RichTextBox line in two based on the caret position

I've got a RichTextBox, here referred to as box.
string currentline = box.Lines[box.GetLineFromCharIndex(box.SelectionStart)];
That line there fetches the line the caret is in. It works excellently.
However, I have a need to get two strings from this. The first is everything on that line UP to the caret, and the second is everything on that line AFTER it.
For instance, if the line is How is you|r day going?, with | representing the caret, I would get How is you and r day going?, separately.
I wrote this monstrosity, which works:
string allbefore = box.Text.Substring(0, box.SelectionStart);
string allafter = box.Text.Substring(box.SelectionStart, box.Text.Length - box.SelectionStart);
string linebefore = "";
for (int i = 0; i < allbefore.Length; i++)
{
linebefore += allbefore[i];
if (allbefore[i] == '\n')
linebefore = "";
}
string lineafter = "";
for (int i = 0; i < allafter.Length; i++)
{
if (allafter[i] == '\n')
break;
else
lineafter += allafter[i];
}
It gives me the result I want, but involves looping through EVERY character in the entire box, which just hurts. Is there an easy way to do this I'm just missing? Thanks.
This might do the trick for you
string currentline = box.Lines[box.GetLineFromCharIndex(box.SelectionStart)];
var listOfStrings = new List<string>();
string[] splitedBox = currentline.Split('|');
foreach(string sp in splitedBox)
{
string[] lineleft = sp.Split('\n');
listOfStrings.Add(lineleft[lineleft.Count() - 1]);
}
In the first approach we are splitting the line by char | than finding if we have any \n if it exsist we are taking the values accordingly
Another approach could be
string box = "How is \n you|r day \n going?";
bool alllinesremoved = true;
while(alllinesremoved)
{
if(box.Contains('\n'))
{
if(box.IndexOf('\n') > box.IndexOf('|'))
{
box = box.Remove(box.IndexOf('\n'), (box.Length - box.IndexOf('\n')));
}
else
{
box = box.Remove(0, box.IndexOf('\n') + 1);
}
}
else
{
alllinesremoved = false;
}
}
string[] splitedBox = box.Split('|');
in the second approach we are removing the characters before and after the \n and then splitting the string. I think the second one seems more good to me.
Have you tried using line.split? Not sure if this is what you want.
Store the position of \n using indexOf and, if >= 0, that is, the string contains it, use substring and assign the value otherwise.
string allbefore = box.Text.Substring(0, box.SelectionStart);
string allafter = box.Text.Substring(box.SelectionStart, box.Text.Length - box.SelectionStart);
int newLinePos = allBefore.lastIndexOf("\n");
string lineBefore = ((newLinePos >= 0) ? (allBefore.substring(newLinePos + 1)) : (allBefore));
newLinePos = allafter.indexOf("\n");
string lineAfter = ((newLinePost >= 0) ? (allAfter.substring(0, newLinePos)) : (allAfter));

C# Split String to Excel

I have been reading up on Split string. I am sending data from C# to Excel and some of this text can be rather long. So without using word wrap or autofit with Excel. I would like the data to break at a certain point and continue to the row below it.Can this be accomplished? ProdDescription is the targeted field here. Here is the code I am using to send the basic data over :
worksheet.Cells[3, "E"].Value = txtCustomer.Text;
worksheet.Cells[4, "E"].Value = txtDate.Text;
worksheet.Cells[5, "E"].Value = cboTerms.Text;
worksheet.Cells[6, "E"].Value = txtProposalID.Text;
worksheet.Cells[10, "D"].value = frmProposal.QtyMaintxt.Text;
worksheet.Cells[10, "E"].value = frmProposal.ProdName.Text;
worksheet.Cells[11, "E"].value = frmProposal.ProdDescription.Text;**
worksheet.Cells[10, "F"].value = frmProposal.ListPrice.Text;
worksheet.Cells[10, "G"].value = frmProposal.MaxDiscount.Text;
Try it like this:
string s = "This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. ";
s += "This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. ";
s += "This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. ";
var words = s.Split(new char[] { ' ' });
int maxLineCount = 35;
var sb=new System.Text.StringBuilder();
string part=words[0];
int i=1;
while (true) {
if (i >= words.Length)
break;
if ((part + " " + words[i]).Length < maxLineCount)
part += " " + words[i];
else {
sb.AppendLine(part);
part = words[i];
}
i++;
}
var result = sb.ToString();
You could write the generated "lines" into an array or directly into your cells too. I just used Stringbuilder to check the result easily...

Indent multiple lines of text

I need to indent multiple lines of text (in contrast to this question for a single line of text).
Let's say this is my input text:
First line
Second line
Last line
What I need is this result:
First line
Second line
Last line
Notice the indentation in each line.
This is what I have so far:
var textToIndent = #"First line
Second line
Last line.";
var splittedText = textToIndent.Split(new string[] {Environment.NewLine}, StringSplitOptions.None);
var indentAmount = 4;
var indent = new string(' ', indentAmount);
var sb = new StringBuilder();
foreach (var line in splittedText) {
sb.Append(indent);
sb.AppendLine(line);
}
var result = sb.ToString();
Is there a safer/simpler way to do it?
My concern is in the split method, which might be tricky if text from Linux, Mac or Windows is transfered, and new lines might not get splitted correctly in the target machine.
Since you are indenting all the lines, how about doing something like:
var result = indent + textToIndent.Replace("\n", "\n" + indent);
Which should cover both Windows \r\n and Unix \n end of lines.
Just replace your newline with newline + indent:
var indentAmount = 4;
var indent = new string(' ', indentAmount);
textToIndent = indent + textToIndent.Replace(Environment.NewLine, Environment.NewLine + indent);
The following solution may seem long-winded compared to other solutions posted here; but it has a few distinct advantages:
It will preserve line separators / terminators exactly as they are in the input string.
It will not append superfluous indentation characters at the end of the string.
It might run faster, as it uses only very primitive operations (character comparisons and copying; no substring searches, nor regular expressions). (But that's just my expectation; I haven't actually measured.)
static string Indent(this string str, int count = 1, char indentChar = ' ')
{
var indented = new StringBuilder();
var i = 0;
while (i < str.Length)
{
indented.Append(indentChar, count);
var j = str.IndexOf('\n', i + 1);
if (j > i)
{
indented.Append(str, i, j - i + 1);
i = j + 1;
}
else
{
break;
}
}
indented.Append(str, i, str.Length - i);
return indented.ToString();
}
Stakx's answer got me thinking about not appending superfluous indentation characters. And I think is best to avoid those characters not only at the end, but also in the middle and beginning of the string (when that's all that line has).
I used a Regex to replace new lines only if they are not followed by another new line, and another Regex to avoid adding the first indent in case the string begins with a new line:
Regex regexForReplace = new Regex(#"(\n)(?![\r\n])");
Regex regexForFirst = new Regex(#"^([\r\n]|$)");
string Indent(string textToIndent, int indentAmount = 1, char indentChar = ' ')
{
var indent = new string(indentChar, indentAmount);
string firstIndent = regexForFirst.Match(textToIndent).Success ? "" : indent;
return firstIndent + regexForReplace.Replace(textToIndent, #"$1" + indent);
}
I create the Regexs outside the method in order to speed up multiple replacements.
This solution can be tested at: https://ideone.com/9yu5Ih
If you need a string extension that adds a generic indent to a multi line string you can use:
public static string Indent(this string input, string indent)
{
return string.Join(Environment.NewLine, input.Split(Environment.NewLine).Select(item => string.IsNullOrEmpty(item.Trim()) ? item : indent + item));
}
This extension skips empty lines.
This solution is really simple to understand if you know linq and it's more simple to debug and change if you need to adapt it to different scopes.

Manipulating String in C#

I have a code in C# and have to print a label with the name of the seller, but i have a problem.
Every line in the label comport 20 letters and i have 2 lines to put this name.
I need to arrange the name of the seller in the 2 lines, without cut words.
For example - Name: JOSE MAURICIO BERTOLOTO MENDES
Line1: JOSE MAURICIO
Line2: BERTOLOTO MENDES
someone know how i do this?
Thanks
EDIT: Based in the answers, i implemente this code:
string[] SellerPrint = Seller.Split(' ');
Line1 = "";
Line2 = "";
foreach (string name in SellerPrint )
{
if (Line1.Length <= 20)
{
if ((Line1 + name).Length <= 20)
Line1 += (Line1.Length == 0) ? name : " " + name;
else
break;
}
}
Line2 = (Seller.Replace(Line1, "").Length <= 20) ? Seller.Replace(Line1+ " ", "") : Seller.Replace(Line1+ " ", "").Remove(20);
Thanks for the help!
You could simply split the string into words using string.Split() and then add to each as long it small enough to add to the line.
I also wouldn't use the character count but use Graphics.MeasureString() instead.
You can split the full name in to it's individual parts.
var names = fullname.Split(' ');
Which will give you a string[]. From there you can do the math by looking at length of each string.
The idea is that you want to append all parts of the name until you will reach or exceed your 20 character limit on the next token. When that happens, append a new line with that token and continue appending until you hit the character limit once again.
Here is a quick example:
public static string FormatName(string name)
{
const int MaxLength = 20;
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException("name");
if (name.Length <= MaxLength)
return name;
string[] tokens = name.Split(' ');
if (tokens.Length == 0)
return name; //hyphen the name?
StringBuilder sb = new StringBuilder(name.Length);
int len = 0;
foreach (string token in tokens)
{
if (token.Length + len < MaxLength)
{
sb.Append(token + " ");
len += token.Length;
}
else
{
sb.Append(Environment.NewLine + token + " ");
len = 0;
}
}
return sb.ToString();
}
Note: I left the case open for when a section of the name, without spaces, is longer than 20 characters. Also, this example will continue on to the Nth line, if the name won't fit onto two lines.
Here is the logic.
Use String.split to split the name into an array. Iterate over the strings in the array, concat them into a line, while the line is less than 20 characters. A recursive function would be a good idea! When you are greater than two lines, drop the rest of the names that put it over.
I'm not sure but I think you can use a special character: '\n' (without the quotes)
Its basiclly stands for new line. So for example : JOSE MAURICIO BERTOLOTO MENDES will become JOSE MAURICIO \n BERTOLOTO MENDES.

Add to string until hits length (noobie C# guy)

I am trying to read a text file, break it into a string array, and then compile new strings out of the words, but I don't want it to exceed 120 characters in length.
What I am doing with is making it write PML to create a macro for some software I use, and the text can't exceed 120 characters. To take it even further I need to wrap the 120 characters or less (to the nearest word), string with "BTEXT |the string here|" which is the command.
Here is the code:
static void Main(string[] args)
{
int BIGSTRINGLEN = 120;
string readit = File.ReadAllText("C:\\stringtest.txt");
string finish = readit.Replace("\r\n", " ").Replace("\t", "");
string[] seeit = finish.Split(' ');
StringBuilder builder = new StringBuilder(BIGSTRINGLEN);
foreach(string word in seeit)
{
while (builder.Length + " " + word.Length <= BIGSTRINGLEN)
{
builder.Append(word)
}
}
}
Try using an if instead of the while as you will continually append the same word if not!!
Rather than read the entire file into memory, you can read it a line at a time. That will reduce your memory requirements and also prevent you having to replace the newlines.
StringBuilder builder = new StringBuilder(BIGSTRINGLEN);
foreach (var line in File.ReadLines(filename))
{
// clean up the line.
// Do you really want to replace tabs with nothing?
// if you want to treat tabs like spaces, change the call to Split
// and include '\t' in the character array.
string finish = line.Replace("\t", string.Empty);
string[] seeit = finish.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
foreach (string word in seeit)
{
if ((builder.Length + word.Length + 1 <= BIGSTRINGLEN)
{
if (builder.Length != 0)
builder.Append(' ');
builder.Append(word);
}
else
{
// output line
Console.WriteLine(builder.ToString());
// and reset the builder
builder.Length = 0;
}
}
}
// and write the last line
if (builder.Length > 0)
Console.WriteLine(builder.ToString());
That code is going to fail if a word is longer than BIGSTRINGLEN. Long words will end up outputting a blank line. I think you can figure out how to handle that case if it becomes a problem.
Matthew Moon is right - your while loop is not going to work as currently placed.
But that aside, you have some problems in this line
while (builder.Length + " " + word.Length <= BIGSTRINGLEN)
builder.Length and word.Length are integers - the number of characters in each word. " " is not an integer, it's a string. You can't correctly add 10 + " " + 5. You probably want
while (builder.Length + (" ").Length + word.Length <= BIGSTRINGLEN)
// or
while (builder.Length + 1 + word.Length <= BIGSTRINGLEN)

Categories