I'm trying to convert some data into sql statements with the use of Streamreader and Streamwriter.
My problem is, when i split lines which in which between 2 delimiters is nothing, not even a space, they get ignored and i get a IndexOutOfRange error
because my temparray only goes till temparray[3] , but it should go to like temparray[6] ..
How can i split and use Null values or replace those null values with a simple char, so that i dont get an IndexOutOfRange error when i want to create my sql statements ?
foreach (string a in values)
{
int temp = 1;
String[] temparray = a.Split(';');
streamWriter.WriteLine("Insert into table Firma values({0},'{1}','{2}')", temp, temparray[1], temparray[4]);
temp++;
}
First of all, this is asking for trouble (SQL injection). You should at the very least escape the values parsed from the string.
And you seem to be mistaken, as String.Split does exactly what you want by default: "x;y;;z".Split(';') returns a four-element array {"x", "y", "", "z"}. You can achieve the described behavior by using StringSplitOptions.RemoveEmptyEntries: "x;y;;z".Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries) returns a three-element array {"x", "y", "z"}. Which is what you do not want, as you say.
Either way, "Überarbeitung der SAV Seite;b.i.b.;;;;PB;".Split(';') returns a seven-element array here for me, so check your inputs and implementation…
If you print out your string, I'm pretty sure it will not be what you expect it to be.
static void Main(string[] args)
{
var result = "Überarbeitung der SAV Seite;b.i.b.;;;;PB;".Split(';');
foreach (var part in result)
{
Console.WriteLine(" --> " + part);
}
Console.ReadLine();
}
This works great. It will not ignore the empty values. It will print
--> Überarbeitung der SAV Seite
--> b.i.b.
-->
-->
-->
--> PB
-->
including the empty values.
Greetings to bib Paderborn :)
If you're using SQL Server, you can return empty strings instead of null by using the ISNULL operator in your query.
For example:
SELECT ISNULL(PR_Arbeitstitel, '') FROM Table
Why don't you iterate over your temparray to build up a string of param values.
This is by no means perfect, but should point you in the direction
foreach (string a in values)
{
int temp = 1;
String[] temparray = a.Split(';');
var stringBuilder = new StringBuilder();
foreach (var s in temparray)
stringBuilder.Append("'" + s + "',");
var insertStatement = string.Format("Insert into table Firma values({0}, {1})", temp, stringBuilder.ToString().TrimEnd(','));
temp++;
}
Why would you have 2 delimiters in a row with nothing inbetween them? Do you not control the input?
In that case you could control it by inserting a so-called sentinel value, such as "IGNOREMEPLEASE":
String[] temparray = a.Replace(";;", ";IGNOREMEPLEASE;").Split(';');
Then the rest of your code knows that IGNOREMEPLEASE means there was an empty line, and it should be ignored.
That being said, be very careful about what you send to a database, and scrub incoming data that you use to build SQL statements with, to get rid of anything dangerous.
I don't see your issue occurring. The following outputs a string.Empty for string[2] and has all 5 elements
string[] str = "0,1,,3,4".Split(new char[] { ',' });
foreach (string s in str)
{
Debug.Print(s);
}
output
0
1
3
4
I've tried to reproduce with your example of string "Überarbeitung der SAV Seite;b.i.b.;;;;PB;" but everything was fine. I've got 7 items in array.
You can try to use
string s = "Überarbeitung der SAV Seite;b.i.b.;;;;PB;";
var result = s.Split(new[] { ';' }, StringSplitOptions.None);
To be sure that StringSplitOptions.RemoveEmptyEntries is not enabled.
Perhaps use the ?? operator:
streamWriter.WriteLine(
"Insert into table Firma values({0},'{1}','{2}')",
temp,
temparray[1] ?? 'x',
temparray[4] ?? 'x');
This still is only safe, though, if you know for sure that your input has at least 5 tokens after splitting. If you can't guarantee this you'll need to wrap it in a conditional:
if (temparray.Length < 5)
{
// handle invalid input
}
Related
for long time , I always append a string in the following way.
for example if i want to get all the employee names separated by some symbol , in the below example i opeted for pipe symbol.
string final=string.Empty;
foreach(Employee emp in EmployeeList)
{
final+=emp.Name+"|"; // if i want to separate them by pipe symbol
}
at the end i do a substring and remove the last pipe symbol as it is not required
final=final.Substring(0,final.length-1);
Is there any effective way of doing this.
I don't want to appened the pipe symbol for the last item and do a substring again.
Use string.Join() and a Linq projection with Select() instead:
finalString = string.Join("|", EmployeeList.Select( x=> x.Name));
Three reasons why this approach is better:
It is much more concise and readable
– it expresses intend, not how you
want to achieve your goal (in your
case concatenating strings in a
loop). Using a simple projection with Linq also helps here.
It is optimized by the framework for
performance: In most cases string.Join() will
use a StringBuilder internally, so
you are not creating multiple strings that are
then un-referenced and must be
garbage collected. Also see: Do not
concatenate strings inside loops
You don’t have to worry about special cases. string.Join()
automatically handles the case of
the “last item” after which you do
not want another separator, again
this simplifies your code and makes
it less error prone.
I like using the aggregate function in linq, such as:
string[] words = { "one", "two", "three" };
var res = words.Aggregate((current, next) => current + ", " + next);
You should join your strings.
Example (borrowed from MSDN):
using System;
class Sample {
public static void Main() {
String[] val = {"apple", "orange", "grape", "pear"};
String sep = ", ";
String result;
Console.WriteLine("sep = '{0}'", sep);
Console.WriteLine("val[] = {{'{0}' '{1}' '{2}' '{3}'}}", val[0], val[1], val[2], val[3]);
result = String.Join(sep, val, 1, 2);
Console.WriteLine("String.Join(sep, val, 1, 2) = '{0}'", result);
}
}
For building up like this, a StringBuilder is probably a better choice.
For your final pipe issue, simply leave the last append outside of the loop
int size = EmployeeList.length()
for(int i = 0; i < size - 1; i++)
{
final+=EmployeeList.getEmployee(i).Name+"|";
}
final+=EmployeeList.getEmployee(size-1).Name;
I am writing a program that finds every unique word in a text and prints it in a text box. I do this by printing each key in a dictionary however my dictionary is adding each word as a separate key instead of ignoring words that are already there.
The function is being called correctly and it does work it simpy prints the entire text I hand it however.
EDIT: I am reading the string from a text file then sending it to the function.
This is the input string and the output:
Output:
To be or not to that is the question Whether tis nobler in mind suffer
The slings and arrows of outrageous fortune Or take arms against a sea
troubles And by opposing end them die sleep No more sleep say we end
The heartache thousand natural shocks That flesh heir Tis consummation
public string FindUniqueWords(string text)
{
Dictionary<string, int> dictionary = new Dictionary<string, int>();
string uniqueWord = "";
text = text.Replace(",", ""); //Just cleaning up a bit
text = text.Replace(".", ""); //Just cleaning up a bit
string[] arr = text.Split(' '); //Create an array of words
foreach (string word in arr) //let's loop over the words
{
if (dictionary.ContainsKey(word)) //if it's in the dictionary
dictionary[word] = dictionary[word] + 1; //Increment the count
else
dictionary[word] = 1; //put it in the dictionary with a count 1
}
foreach (KeyValuePair<string, int> pair in dictionary) //loop through the dictionary
{
uniqueWord += (pair.Key + " ");
}
uniqueWords.Text = uniqueWord;
return ("");
}
You're reading the text with System.IO.File.ReadAllText, so text may also contain newline characters.
Replace arr = text.Split(' ') by arr = text.Split(' ', '\r', '\n') or add another replace: text = text.Replace(Environment.NewLine, " ");
Of course, by looking at arr in the debugger, you could have found out by yourself.
A shorter way: (Dont forget to use Using System.Linq)
string strInput = "TEST TEST Text 123";
var words = strInput.Split().Distinct();
foreach (var word in words )
{
Console.WriteLine(word);
}
Your code works as it's supposed to (ignoring case though). The problem almost certainly lies with showing the results in your application, or with how you are calling the FindUniqueWords method (not the complete text at once).
Also, pretty important to note here: a Dictionary<TKey, TValue> by default simply cannot contain a single key multiple times. It would defeat the whole purpose of the dictionary in the first place. It's only possible if you override the Equality comparison somewhere, which you aren't doing.
If I try your code, with the following input:
To be or not to that is is is is is is is the question
The output becomes :
To be or not to that is the question
It works like it's supposed to.
I am using ASP.NET Web Pages to create a project in which I am assigned to place each character of the user's (customer's) name in each seperate input block.
For that I am getting the value from the Sql Server CE Database and then I am trying to convert it into an array of one character for each input. I have tried the following code for that
var form_data = db.QuerySingle("SELECT * FROM Form_Data WHERE Form_Id =#0", form_id);
var name_emp = form_data.Name_Emig;
if(name_emp != null) {
name_emp = name_emp.ToString().Split('');
}
It generates the following Compiler error:
http://msdn.microsoft.com/en-us/library/8eb78ww7(v=vs.90).aspx (Compiler error: CS1011)
Which means that the character cannot be initialized by an empty value. I want to convert that value in one character each array.
The name is as: Afzaal Ahmad Zeeshan. So, in each input it would be placed inside the value of it. But the code I am using isn't working. Any suggestion to split the string at each character, so the result would be
{'A', 'F', 'Z', 'A', 'A', 'L' ...}
It doesn't matter whether result is Capital case or lower case. I will convert it to the desired one later.
You can try using ToCharArray().
So your code would be this:
var form_data = db.QuerySingle("SELECT * FROM Form_Data WHERE Form_Id =#0", form_id);
var name_emp = form_data.Name_Emig;
if(name_emp != null) {
name_emp = name_emp.ToCharArray();
}
You can use this to iterate with each item :
string yourString = "test";
foreach(var character in yourString)
{
// do something with each character.
}
Or this to get all characters in a char[]
char[] characters = yourstring.ToCharArray();
Try name_emp.ToArray(). A string implements IEnumerable<char>, so ToArray will return an array of the char.
Edit:
Actually I suppose ToCharArray is better in this case...
I have problems splitting this Line. I want to get each String between "#VAR;" and "#ENDVAR;". So at the End, there should be a output of:
Variable=Speed;Value=Fast;
Variable=Fabricator;Value=Freescale;Op==;
Later I will separate each Substring, using ";" as a delimiter but that I guess wont be that hard. This is how a line looks like:
#VAR;Variable=Speed;Value=Fast;Op==;#ENDVAR;#VAR;Variable=Fabricator;Value=Freescale;Op==;#ENDVAR;
I tried some split-options, but most of the time I just get an empty string. I also tried a Regex. But either the Regex was wrong or it wasnt suitable to my String. Probably its wrong, at school we learnt Regex different then its used in C#, so I was confused while implementing.
Regex.Match(t, #"/#VAR([a-z=a-z]*)/#ENDVAR")
Edit:
One small question: I am iterating over many lines like the one in the question. I use NoIdeas code on the line to get it in shape. The next step would be to print it as a Text-File. To print an Array I would have to loop over it. But in every iteration, when I get a new line, I overwrite the Array with the current splitted string. I put the Rest of my code in the question, would be nice if someone could help me.
string[] w ;
foreach (EA.Element theObjects in myPackageObject.Elements)
{
theObjects.Type = "Object";
foreach (EA.Element theElements in PackageHW.Elements)
{
if (theObjects.ClassfierID == theElements.ElementID)
{
t = theObjects.RunState;
w = t.Replace("#ENDVAR;", "#VAR;").Replace("#VAR;", ";").Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
foreach (string s in w)
{
tw2.WriteLine(s);
}
}
}
}
The piece with the foreach-loop is wrong pretty sure. I need something to print each splitted t. Thanks in advance.
you can do it without regex using
str.Replace("#ENDVAR;", "#VAR;")
.Split(new string[] { "#VAR;" }, StringSplitOptions.RemoveEmptyEntries);
and if you want to save time you can do:
str.Replace("#ENDVAR;", "#VAR;")
.Replace("#VAR;", ";")
.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
You can use a look ahead assertion here.
#VAR;(.*?)(?=#ENDVAR)
If your string never consists of whitespace between #VAR; and #ENDVAR; you could use the below line, this will not match empty instances of your lines.
#VAR;([^\s]+)(?=#ENDVAR)
See this demo
Answer using raw string manipulation.
IEnumerable<string> StuffFoundInside(string biggerString)
{
var closeDelimeterIndex = 0;
do
{
int openDelimeterIndex = biggerString.IndexOf("#VAR;", startingIndex);
if (openDelimeterIndex != -1)
{
closeDelimeterIndex = biggerString.IndexOf("#ENDVAR;", openDelimeterIndex);
if (closeDelimiterIndex != -1)
{
yield return biggerString.Substring(openDelimeterIndex, closeDelimeterIndex - openDelimiterIndex);
}
}
} while (closeDelimeterIndex != -1);
}
Making a list and adding each item to the list then returning the list might be faster, depending on how the code using this code would work. This allows it to terminate early, but has the coroutine overhead.
Use this regex:
(?i)#VAR;(.+?)#ENDVAR;
Group 1 in each match will be your line content.
(If you don't like regexs)
Code:
var s = "#VAR;Variable=Speed;Value=Fast;Op==;#ENDVAR;#VAR;Variable=Fabricator;Value=Freescale;Op==;#ENDVAR;";
var tokens = s.Split(new String [] {"#ENDVAR;#VAR;"}, StringSplitOptions.None);
foreach (var t in tokens)
{
var st = t.Replace("#VAR;", "").Replace("#ENDVAR;", "");
Console.WriteLine(st);
}
Output:
Variable=Speed;Value=Fast;Op==;
Variable=Fabricator;Value=Freescale;Op==;
Regex.Split works well but yields empty entries that have to be removed as shown here:
string[] result = Regex.Split(input, #"#\w+;")
.Where(s => s != "")
.ToArray();
I tried some split-options, but most of the time I just get an empty string.
In this case the requirements seem to be simpler than you're stating. Simply splitting and using linq will do your whole operation in one statement:
string test = "#VAR;Variable=Speed;Value=Fast;Op==;#ENDVAR;#VAR;Variable=Fabricator;Value=Freescale;Op==;#ENDVAR;";
List<List<string>> strings = (from s in test.Split(new string[]{"#VAR;",";#ENDVAR;"},StringSplitOptions.RemoveEmptyEntries)
let s1 = s.Split(new char[]{';'},StringSplitOptions.RemoveEmptyEntries).ToList<string>()
select (s1)).ToList<List<string>>();
the outpout is:
?strings[0]
Count = 3
[0]: "Variable=Speed"
[1]: "Value=Fast"
[2]: "Op=="
?strings[1]
Count = 3
[0]: "Variable=Fabricator"
[1]: "Value=Freescale"
[2]: "Op=="
To write the data to a file something like this will work:
foreach (List<string> s in strings)
{
System.IO.File.AppendAllLines("textfile1.txt", s);
}
for long time , I always append a string in the following way.
for example if i want to get all the employee names separated by some symbol , in the below example i opeted for pipe symbol.
string final=string.Empty;
foreach(Employee emp in EmployeeList)
{
final+=emp.Name+"|"; // if i want to separate them by pipe symbol
}
at the end i do a substring and remove the last pipe symbol as it is not required
final=final.Substring(0,final.length-1);
Is there any effective way of doing this.
I don't want to appened the pipe symbol for the last item and do a substring again.
Use string.Join() and a Linq projection with Select() instead:
finalString = string.Join("|", EmployeeList.Select( x=> x.Name));
Three reasons why this approach is better:
It is much more concise and readable
– it expresses intend, not how you
want to achieve your goal (in your
case concatenating strings in a
loop). Using a simple projection with Linq also helps here.
It is optimized by the framework for
performance: In most cases string.Join() will
use a StringBuilder internally, so
you are not creating multiple strings that are
then un-referenced and must be
garbage collected. Also see: Do not
concatenate strings inside loops
You don’t have to worry about special cases. string.Join()
automatically handles the case of
the “last item” after which you do
not want another separator, again
this simplifies your code and makes
it less error prone.
I like using the aggregate function in linq, such as:
string[] words = { "one", "two", "three" };
var res = words.Aggregate((current, next) => current + ", " + next);
You should join your strings.
Example (borrowed from MSDN):
using System;
class Sample {
public static void Main() {
String[] val = {"apple", "orange", "grape", "pear"};
String sep = ", ";
String result;
Console.WriteLine("sep = '{0}'", sep);
Console.WriteLine("val[] = {{'{0}' '{1}' '{2}' '{3}'}}", val[0], val[1], val[2], val[3]);
result = String.Join(sep, val, 1, 2);
Console.WriteLine("String.Join(sep, val, 1, 2) = '{0}'", result);
}
}
For building up like this, a StringBuilder is probably a better choice.
For your final pipe issue, simply leave the last append outside of the loop
int size = EmployeeList.length()
for(int i = 0; i < size - 1; i++)
{
final+=EmployeeList.getEmployee(i).Name+"|";
}
final+=EmployeeList.getEmployee(size-1).Name;