We are trying to read each word from a text file and replace it with another word.
For smaller text files, it works well. But for larger text files we keep getting the exception: "String cannot be of zero length.
Parameter name: oldValue "
void replace()
{
string s1 = " ", s2 = " ";
StreamReader streamReader;
streamReader = File.OpenText("C:\\sample.txt");
StreamWriter streamWriter = File.CreateText("C:\\sample1.txt");
//int x = st.Rows.Count;
while ((line = streamReader.ReadLine()) != null)
{
char[] delimiterChars = { ' ', '\t' };
String[] words = line.Split(delimiterChars);
foreach (string str in words)
{
s1 = str;
DataRow drow = st.Rows.Find(str);
if (drow != null)
{
index = st.Rows.IndexOf(drow);
s2 = Convert.ToString(st.Rows[index]["Binary"]);
s2 += "000";
// Console.WriteLine(s1);
// Console.WriteLine(s2);
streamWriter.Write(s1.Replace(s1,s2)); // Exception occurs here
}
else
break;
}
}
streamReader.Close();
streamWriter.Close();
}
we're unable to find the reason.
Thanks in advance.
When you do your string.Split you may get empty entries if there are multiple spaces or tabs in sequence. These can't be replaced as the strings are 0 length.
Use the overload that strips empty results using the StringSplitOptions argument:
var words = line.Split(delimiterChars, StringSplitOptions.RemoveEmptyEntries);
The exception occurs because s1 is an empty string at some point. You can avoid this by replacing the line
String[] words = line.Split(delimiterChars);
with this:
String[] words = line.Split(delimiterChars, StringSplitOptions.RemoveEmptyEntries);
You want to change your Split method call like this:
String[] words = line.Split(delimiterChars,StringSplitOptions.RemoveEmptyEntries);
It means that s1 contains an empty string ("") which can happen if you have two consecutive white spaces or tabs in your file.
Related
I need to read all of .txt file and save data to array/list. File looks like this:
row11 row12 row13
row21 row22 row23
row31 row32 row33
between strings are only spaces.
Next I will insert data from array/list<> to mysql, but it is not problem.
Thanks.
EDIT: I need insert 3 columns to mysql like .txt file.
Use String.Split(Char[], StringSplitOptions) where the first parameter specifies that you want to split your string using spaces and tabs, and the second parameter specifies that you ignore empty entries (for cases where there are multiple spaces between entries)
Use this code:
var lines = System.IO.File.ReadAllLines(#"D:\test.txt");
var data = new List<List<string>>();
foreach (var line in lines)
{
var split = line.Split(new[]{' ', '\t'}, StringSplitOptions.RemoveEmptyEntries);
data.Add(split.ToList());
}
You can use File.ReadLines() to read the lines from the file, and then Regex.Split() to split each line into multiple strings:
static IEnumerable<String> SplitLines(string path, string splitPattern)
{
foreach (string line in File.ReadAllLines(path))
foreach (string part in Regex.Split(line, splitPattern))
yield return part;
}
To split by white space, you can use the regex pattern \s+:
var individualStrings = SplitLines(#"C:\path\to\file.txt", #"\s+");
You can use the ToList() extension method to convert it to a list:
List<string> individualStrings = SplitLines(#"D:\test\rows.txt", #"\s+").ToList();
As long as there are never spaces in the "values", then a simple line-by line parser will work.
A simple example
var reader = new StreamReader(filePath);
var resultList = new List<List<string>>();
string line;
while ((line = reader.ReadLine()) != null)
{
var currentValues = new List<string>();
// You can also use a StringBuilder
string currentValue = String.Empty;
foreach (char c in line)
{
if (Char.IsWhiteSpace(c))
{
if (currentValue.Length > 0)
{
currentValues.Add(currentValue);
currentValue = String.Empty;
}
continue;
}
currentValue += c;
}
resultList.Add(currentValues);
}
Here's a nifty one-liner based off Amadeusz's answer:
var lines = File.ReadAllLines(fileName).Select(l => l.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries)).SelectMany(words => words);
public static List<string> items = new List<string>() { "a","b","c","d","e" };
I am trying to change each of those from loading a file and replacing with their current inventory.
if (File.Exists("darColItems.txt") == true)
{
char c = ',';
StreamReader st = new StreamReader("darColItems.txt");
temp = st.ReadToEnd().ToCharArray();
foreach (c in temp)
{
}
st.Close();
}
Edit: Taking a file such as: iron,bronze,gold,diamond,iron and taking each name and place it into the list for each spot.
File.txt: "string1","string2","string3","string4","string5"
Startup of program:
List inventory (current):
"a","b","c","d","e"
Load inventory....
List inventory (final):
"string1","string2","string3","string4","string5"
Assuming that you actually want to replace all items in the list with all items in the file in the order of occurence and the delimiter is comma. You could use String.Split:
items = File.ReadAllText("path").Split(new [] { ',' }, StringSplitOptions.None).ToList();
If you have quotes around the words in the file which you want to remove, you can use String.Trim:
items = File.ReadAllText("path")
.Split(new char[] { ',' }, StringSplitOptions.None)
.Select(s => s.Trim('"', ' ')) // remove quotes + spaces at the beginning and end
.ToList();
//keep filename in a constant/variable for easy reuse (better, put it in a config file)
const string SourceFile = "darColItems.txt";
//what character separates data elements (if the elements may contain this character you may instead want to look into a regex; for now we'll keep it simple though, & assume that's not the case
const char delimeter = ',';
//here's where we'll store our values
var values = new List<string>();
//check that our input file exists
if (File.Exists(SourceFile))
{
//using statement ensures file is closed & disposed, even if there's an error mid-process
using (var reader = File.OpenText(SourceFile))
{
string line;
//read each line until the end of file (at which point the line read will be null)
while ((line = reader.ReadLine()) != null)
{
//split the string by the delimiter (',') and feed those values into our list
foreach (string value in line.Split(delimiter)
{
values.Add(value);
}
}
}
}
I am trying to get a list of words (below) to be put into an array. I want each word to be in it's own index.
Here is my code that I have so far.
string badWordsFilePath = openFileDialog2.FileName.ToString();
StreamReader sr = new StreamReader(badWordsFilePath);
string line = sr.ReadToEnd();
string[] badWordsLine = line.Split(' ');
int BadWordArrayCount = 0;
foreach (string word in badWordsLine)
{
badWords[BadWordArrayCount] = word;
BadWordArrayCount = BadWordArrayCount + 1;
}
int test = badWords.Length;
MessageBox.Show("Words have been imported!");
BadWordsImported = true;
Here is the list of words I want to import.
label
invoice
post
document
postal
calculations
copy
fedex
statement
financial
dhl
usps
8
notification
n
irs
ups
no
delivery
ticket
If someone could give me an example of how to get this to work, that would be a huge help.
Simplified code:
string badWordsFilePath = openFileDialog2.FileName.ToString();
string[] badWords = File.ReadAllLines(badWordsFilePath);
int test = badWords.Length;
MessageBox.Show("Words have been imported!");
BadWordsImported = true;
If every word starts on a new line then you do not need to create a for loop. The Split method will convert to an array for you.
string badWordsFilePath = openFileDialog2.FileName.ToString();
StreamReader sr = new StreamReader(badWordsFilePath);
string line = sr.ReadToEnd();
string[] badWords = line.Split('\n');
You are splitting on space, but there is a newline between each word. Split on newline instead:
string[] badWordsLine = line.Split(new string[]{ Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
Then you have to create the array to put the words in:
badWords = new string[badWordsLine.Length];
However, to loop through a string array just to copy the strings to a string array seems pointless. Just assing the string array to the variable. Also, you forgot to close the stream reader, which is best taken care of with a using block:
string badWordsFilePath = openFileDialog2.FileName.ToString();
string line;
using (StreamReader sr = new StreamReader(badWordsFilePath)) {}
line = sr.ReadToEnd();
}
badWords = line.Split(new string[]{ Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
int test = badWords.Length;
MessageBox.Show("Words have been imported!");
BadWordsImported = true;
Maybe try this modification? It allows on splitting on various white spaces.
string badWordsFilePath = openFileDialog2.FileName.ToString();
StreamReader sr = new StreamReader(badWordsFilePath);
string line = sr.ReadToEnd();
string[] badWordsLine = line.Split(new string[] {" ", "\t", "\r\n"}, StringSplitOptions.RemoveEmptyEntries);
int BadWordArrayCount = 0;
foreach (string word in badWordsLine)
{
badWords[BadWordArrayCount] = word;
BadWordArrayCount = BadWordArrayCount + 1;
}
int test = badWords.Length;
MessageBox.Show("Words have been imported!");
BadWordsImported = true;
Do you have to use a StreamReader? If you do not have to, then this code is clearer (in my opinion).
string text = File.ReadAllText(badWordsFilePath);
string[] words = Regex.Split(text, #"\s+");
If you're 100% certain that each word is on its own line and there are no empty lines, this might be overkill; and the File.ReadAllLines suggestion by #Ulugbek Umirov is simpler.
I have a text file having text below:
Contact Name | Contact Number
Above like Contact Name\t\t|\t\tContact Number And i am using the following code to remove \t\t|\t\t :
using (StreamReader sr = File.OpenText(fileName))
{
string s = String.Empty;
while ((s = sr.ReadToEnd()) != null)
{
string[] line = s.Split(new string[] {"\t\t|\t\t"}, StringSplitOptions.RemoveEmptyEntries );
}
}
I am using the breakpoint to check the values in the "line" variable below:
"Contact Name"
"Contact Number\r\n\r\n"
The above line of code remove \t\t|\t\t but add \r\n\r\n. How do I remove both \t\t|\t\t and \r\n\r\n at a time. Kindly suggest me. Waiting for reply. thanks
Split your text by | char and then trim each line by removing tabs, spaces and new line characters from start and end of each line (you can also use Trim() without parameters in this case, because all characters you want to remove are considered white space characters):
string text = "Contact Name | Contact Number";
var lines = text.Split('|').Select(s => s.Trim('\t', '\n', '\r', ' '));
That will produce sequence of two lines:
"Contact Name"
"Contact Number"
You can use:
s = s.TrimEnd(new char[] { '\r', '\n' });
This will remove all newline characters from end of your string.
You can also split on "\r\n\r\n" and it will be removed.
string[] line = s.Split(new string[] {"\t\t|\t\t", "\r\n\r\n"}, StringSplitOptions.RemoveEmptyEntries );
Since you try to remove all characters (like \t, \n or \r) from your file, I would recommend you to read all the filecontent as a string and perform a simple .Replace(string oldChar, string newChar), which is slightly faster than using the .Split('').Join('') method.
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(fileName))
{
String line;
while ((line = sr.ReadLine()) != null)
{
sb.AppendLine(line);
}
}
string content = sb.ToString();
// Remove all tabs and new lines
string cleanedContent = content.Replace('\t', String.Empty)
.Replace('\r', String.Empty)
.Replace('\n', String.Empty)
.Replace('|', String.Empty);
How can I remove empty lines in a string in C#?
I am generating some text files in C# (Windows Forms) and for some reason there are some empty lines. How can I remove them after the string is generated (using StringBuilder and TextWrite).
Example text file:
THIS IS A LINE
THIS IS ANOTHER LINE AFTER SOME EMPTY LINES!
If you also want to remove lines that only contain whitespace, use
resultString = Regex.Replace(subjectString, #"^\s+$[\r\n]*", string.Empty, RegexOptions.Multiline);
^\s+$ will remove everything from the first blank line to the last (in a contiguous block of empty lines), including lines that only contain tabs or spaces.
[\r\n]* will then remove the last CRLF (or just LF which is important because the .NET regex engine matches the $ between a \r and a \n, funnily enough).
Tim Pietzcker - it is not working for me. I have to change a little bit, but thanks!
Ehhh C# Regex.. I had to change it again, but this it working well:
private string RemoveEmptyLines(string lines)
{
return Regex.Replace(lines, #"^\s*$\n|\r", string.Empty, RegexOptions.Multiline).TrimEnd();
}
Example:
http://regex101.com/r/vE5mP1/2
You could try String.Replace("\n\n", "\n");
Try this
Regex.Replace(subjectString, #"^\r?\n?$", "", RegexOptions.Multiline);
private string remove_space(string st)
{
String final = "";
char[] b = new char[] { '\r', '\n' };
String[] lines = st.Split(b, StringSplitOptions.RemoveEmptyEntries);
foreach (String s in lines)
{
if (!String.IsNullOrWhiteSpace(s))
{
final += s;
final += Environment.NewLine;
}
}
return final;
}
private static string RemoveEmptyLines(string text)
{
var lines = text.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
var sb = new StringBuilder(text.Length);
foreach (var line in lines)
{
sb.AppendLine(line);
}
return sb.ToString();
}
None of the methods mentioned here helped me all the way, but I found a workaround.
Split text to lines - collection of strings (with or without empty strings, also Trim() each string).
Add these lines to multiline string.
public static IEnumerable<string> SplitToLines(this string inputText, bool removeEmptyLines = true)
{
if (inputText == null)
{
yield break;
}
using (StringReader reader = new StringReader(inputText))
{
string line;
while ((line = reader.ReadLine()) != null)
{
if (removeEmptyLines && !string.IsNullOrWhiteSpace(line))
yield return line.Trim();
else
yield return line.Trim();
}
}
}
public static string ToMultilineText(this string text)
{
var lines = text.SplitToLines();
return string.Join(Environment.NewLine, lines);
}
Based on Evgeny Sobolev's code, I wrote this extension method, which also trims the last (obsolete) line break using TrimEnd(TrimNewLineChars):
public static class StringExtensions
{
private static readonly char[] TrimNewLineChars = Environment.NewLine.ToCharArray();
public static string RemoveEmptyLines(this string str)
{
if (str == null)
{
return null;
}
var lines = str.Split(TrimNewLineChars, StringSplitOptions.RemoveEmptyEntries);
var stringBuilder = new StringBuilder(str.Length);
foreach (var line in lines)
{
stringBuilder.AppendLine(line);
}
return stringBuilder.ToString().TrimEnd(TrimNewLineChars);
}
}
I found a simple answer to this problem:
YourradTextBox.Lines = YourradTextBox.Lines.Where(p => p.Length > 0).ToArray();
Adapted from Marco Minerva [MCPD] at Delete Lines from multiline textbox if it's contain certain string - C#
I tried the previous answers, but some of them with regex do not work right.
If you use a regex to find the empty lines, you can’t use the same for deleting.
Because it will erase "break lines" of lines that are not empty.
You have to use "regex groups" for this replace.
Some others answers here without regex can have performance issues.
private string remove_empty_lines(string text) {
StringBuilder text_sb = new StringBuilder(text);
Regex rg_spaces = new Regex(#"(\r\n|\r|\n)([\s]+\r\n|[\s]+\r|[\s]+\n)");
Match m = rg_spaces.Match(text_sb.ToString());
while (m.Success) {
text_sb = text_sb.Replace(m.Groups[2].Value, "");
m = rg_spaces.Match(text_sb.ToString());
}
return text_sb.ToString().Trim();
}
This pattern works perfect to remove empty lines and lines with only spaces and/or tabs.
s = Regex.Replace(s, "^\s*(\r\n|\Z)", "", RegexOptions.Multiline)