I have declared a class variable in here
void downloader_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error == null)
{
Stream responseStream = e.Result;
StreamReader responseReader = new StreamReader(responseStream);
string response = responseReader.ReadToEnd();
string[] split1 = Regex.Split(response, "},{");
List<string> pri1 = new List<string>(split1);
pri1.RemoveAt(0);
string last = pri1[pri1.Count() - 1];
pri1.Remove(last);
}
}
and I want to use the class variable str in this method
void AddPrimaryMarkerGraphics(object sender, getPrimaryListCompletedEventArgs e)
{
List<PrimaryClass> primaryList = new List<PrimaryClass>(e.Result);
PrimaryClass sc = new PrimaryClass();
for (int a = 0; a <= e.Result.Count - 1; a++)
{
string schname = e.Result.ElementAt(a).PrimarySchool;
string tophonour = e.Result.ElementAt(a).TopHonour;
string cca = e.Result.ElementAt(a).Cca;
string topstudent = e.Result.ElementAt(a).TopStudent;
string topaggregate = e.Result.ElementAt(a).TopAggregate;
string topimage = e.Result.ElementAt(a).TopImage;
foreach (string item in str)
{
string abc = "[{" + item + "}]";
byte[] buf = System.Text.Encoding.UTF8.GetBytes(abc);
MemoryStream ms = new MemoryStream(buf);
JsonArray users = (JsonArray)JsonArray.Load(ms);
var members = from member in users
//where member["SEARCHVAL"]
select member;
foreach (JsonObject member in members)
{
string schname = member["SEARCHVAL"];
string axisX = member["X"];
string axisY = member["Y"];
// Do something...
string jsonCoordinateString = "{'Coordinates':[{'X':" + axisX + ",'Y':" + axisY + "}]}";
CustomCoordinateList coordinateList = DeserializeJson<CustomCoordinateList>(jsonCoordinateString);
GraphicsLayer graphicsLayer = MyMap.Layers["MyGraphicsLayer_Primary"] as GraphicsLayer;
for (int i = 0; i < coordinateList.Coordinates.Count; i++)
{
Graphic graphic = new Graphic()
{
Geometry = new MapPoint(coordinateList.Coordinates[i].X, coordinateList.Coordinates[i].Y),
Symbol = i > 0 ? PrimarySchoolMarkerSymbol : PrimarySchoolMarkerSymbol
};
graphic.Attributes.Add("PrimarySchool", schname);
graphic.Attributes.Add("xcoord", axisX);
graphic.Attributes.Add("ycoord", axisY);
graphicsLayer.Graphics.Add(graphic);
}
}
}
}
}
That's where the error shows.
You've almost certainly declared the variable in a method (i.e. as a local variable), instead of directly in the class itself (as an instance variable). For example:
// Wrong
class Bad
{
void Method1()
{
List<string> str = new List<string>();
}
void Method2()
{
foreach (string item in str)
{
...
}
}
}
// Right
class Good
{
private List<string> str = new List<string>();
void Method1()
{
str = CreateSomeOtherList();
}
void Method2()
{
foreach (string item in str)
{
...
}
}
}
As a side-note: if you're very new to C#, I would strongly recommend that you stop working on Silverlight temporarily, and write some console apps just to get you going, and to teach you the basics. That way you can focus on C# as a language and the core framework types (text, numbers, collections, I/O for example) and then start coding GUIs later. GUI programming often involves learning a lot more things (threading, XAML, binding etc) and trying to learn everything in one go just makes things harder.
It doesn't work because str is not declared in the other variable. It's sscopong problem. Can you pass str as an input to the other function?
Related
I Want to develope an app I give Url of a specific website to it,and it extract all links from that Web page. For each extracted link I want to get the HTML content. I am based in the concept of deep crawling.
My purpose is to get all email addresses of website. Below is my source code:
static string ExtractEmails(string data)
{
//instantiate with this pattern
Regex emailRegex = new Regex(#"\w+([-+.]\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.IgnoreCase);
//find items that matches with our pattern
MatchCollection emailMatches = emailRegex.Matches(data);
//StringBuilder sb = new StringBuilder();
string s = "";
foreach (Match emailMatch in emailMatches)
{
//sb.AppendLine(emailMatch.Value);
s += emailMatch.Value + ",";
}
return s;
}
static readonly List<ParsResult> _results = new List<ParsResult>();
static Int32 _maxDepth = 4;
static String Foo(String urlToCheck = null, Int32 depth = 0, ParsResult parent = null)
{
string email = "";
if (depth >= _maxDepth) return email;
String html;
using (var wc = new WebClient())
html = wc.DownloadString(urlToCheck ?? parent.Url);
var doc = new HtmlDocument();
doc.LoadHtml(html);
var aNods = doc.DocumentNode.SelectNodes("//a");
if (aNods == null || !aNods.Any()) return email;
foreach (var aNode in aNods)
{
var url = aNode.Attributes["href"];
if (url == null)
continue;
var wc2 = new WebClient();
String html2 = wc2.DownloadString(url.Value);
email = ExtractEmails(html2);
Console.WriteLine(email);
var result = new ParsResult
{
Depth = depth,
Parent = parent,
Url = url.Value
};
_results.Add(result);
Console.WriteLine("{0} - {1}", depth, result.Url);
Foo(depth: depth + 1, parent: result);
return email;
}
return email;
}
static void Main(string[] args)
{
String res = Foo("http://www.mobileridoda.com", 0);
Console.WriteLine("emails " + res);
}
I want to dispaly in console all emails extracted by all pages of all links that are inside DOM of Main page, But it dispalys no emails in console. How can I solve this issue ?
Thank you
Found a few things wrong but no worries, got the details on why and what to do to fix them.
In your foreach loop, when you go through the first URL, you are using a return statement at the end essentially breaking the loop and terminating. Use return only after you have processed ALL the URLs and accumulated the email addresses.
You are overwriting the email (i see it as a csv) when you go over the loop. Use += to continue adding. email = ExtractEmails(html2);
You are not returning anything when you call Foo within your forEach loop. You need to use email += Foo(xyz). Foo(depth: depth + 1, parent: result);
You are going through a URL that you have already processed... possibly causing an infinite cycle. I added a list of strings that keeps track of URLs you have already visited so as to prevent the infinite loop you might get into.
Here is a complete working solution.
static string ExtractEmails(string data)
{
//instantiate with this pattern
Regex emailRegex = new Regex(#"\w+([-+.]\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.IgnoreCase);
//find items that matches with our pattern
MatchCollection emailMatches = emailRegex.Matches(data);
//StringBuilder sb = new StringBuilder();
string s = "";
foreach (Match emailMatch in emailMatches)
{
//sb.AppendLine(emailMatch.Value);
s += emailMatch.Value + ",";
}
return s;
}
static readonly List<ParsResult> _results = new List<ParsResult>();
static Int32 _maxDepth = 4;
static List<string> urlsAlreadyVisited = new List<string>();
static String Foo(String urlToCheck = null, Int32 depth = 0, ParsResult parent = null)
{
if (urlsAlreadyVisited.Contains(urlToCheck))
return string.Empty;
else
urlsAlreadyVisited.Add(urlToCheck);
string email = "";
if (depth >= _maxDepth) return email;
String html;
using (var wc = new WebClient())
html = wc.DownloadString(urlToCheck ?? parent.Url);
var doc = new HtmlDocument();
doc.LoadHtml(html);
var aNods = doc.DocumentNode.SelectNodes("//a");
if (aNods == null || !aNods.Any()) return email;
// Get Distinct URLs from all the URls on this page.
List<string> allUrls = aNods.ToList().Select(x => x.Attributes["href"].Value).Where(url => url.StartsWith("http")).Distinct().ToList();
foreach (string url in allUrls)
{
var wc2 = new WebClient();
try
{
email += ExtractEmails(wc2.DownloadString(url));
}
catch { /* Swallow Exception ... URL not found or other errors. */ continue; }
Console.WriteLine(email);
var result = new ParsResult
{
Depth = depth,
Parent = parent,
Url = url
};
_results.Add(result);
Console.WriteLine("{0} - {1}", depth, result.Url);
email += Foo(depth: depth + 1, parent: result);
}
return email;
}
public class ParsResult
{
public int Depth { get; set; }
public ParsResult Parent { get; set; }
public string Url { get; set; }
}
// ========== MAIN CLASS ==========
static void Main(string[] args)
{
String res = Foo("http://www.mobileridoda.com", 0);
Console.WriteLine("emails " + res);
}
I have data in tab-separated values (TSV) text files that I want to read and (eventually) store in database tables. With the TSV files, each line contains one record, but in one file the record can have 2 fields, in another file 4 fields, etc. I wrote working code to handle the 2-field records, but I thought this might be a good case for a generic method (or two) rather than writing new methods for each kind of record. However, I have not been able to code this because of 2 problems: I can't create a new object for holding the record data, and I don't know how to use reflection to generically fill the instance variables of my objects.
I looked at several other similar posts, including Datatable to object by using reflection and linq
Below is the code that works (this is in Windows, if that matters) and also the code that doesn't work.
public class TSVFile
{
public class TSVRec
{
public string item1;
public string item2;
}
private string fileName = "";
public TSVFile(string _fileName)
{
fileName = _fileName;
}
public TSVRec GetTSVRec(string Line)
{
TSVRec rec = new TSVRec();
try
{
string[] fields = Line.Split(new char[1] { '\t' });
rec.item1 = fields[0];
rec.item2 = fields[1];
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("Bad import data on line: " +
Line + "\n" + ex.Message, "Error",
System.Windows.Forms.MessageBoxButtons.OK,
System.Windows.Forms.MessageBoxIcon.Error);
}
return rec;
}
public List<TSVRec> ImportTSVRec()
{
List<TSVRec> loadedData = new List<TSVRec>();
using (StreamReader sr = File.OpenText(fileName))
{
string Line = null;
while ((Line = sr.ReadLine()) != null)
{
loadedData.Add(GetTSVRec(Line));
}
}
return loadedData;
}
// *** Attempted generic methods ***
public T GetRec<T>(string Line)
{
T rec = new T(); // compile error!
Type t = typeof(T);
FieldInfo[] instanceVars = t.GetFields();
string[] fields = Line.Split(new char[1] { '\t' });
for (int i = 0; i < instanceVars.Length - 1; i++)
{
rec. ??? = fields[i]; // how do I finish this line???
}
return rec;
}
public List<T> Import<T>(Type t)
{
List<T> loadedData = new List<T>();
using (StreamReader sr = File.OpenText(fileName))
{
string Line = null;
while ((Line = sr.ReadLine()) != null)
{
loadedData.Add(GetRec<T>(Line));
}
}
return loadedData;
}
}
I saw the line
T rec = new T();
in the above-mentioned post, but it doesn't work for me...
I would appreciate any suggestions for how to make this work, if possible. I want to learn more about using reflection with generics, so I don't only want to understand how, but also why.
I wish #EdPlunkett had posted his suggestion as an answer, rather than a comment, so I could mark it as the answer...
To summarize: to do what I want to do, there is no need for "Assigning instance variables obtained through reflection in generic method". In fact, I can have a generic solution without using a generic method:
public class GenRec
{
public List<string> items = new List<string>();
}
public GenRec GetRec(string Line)
{
GenRec rec = new GenRec();
try
{
string[] fields = Line.Split(new char[1] { '\t' });
for (int i = 0; i < fields.Length; i++)
rec.items.Add(fields[i]);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("Bad import data on line: " + Line + "\n" + ex.Message, "Error",
System.Windows.Forms.MessageBoxButtons.OK,
System.Windows.Forms.MessageBoxIcon.Error);
}
return rec;
}
public List<GenRec> Import()
{
List<GenRec> loadedData = new List<GenRec>();
using (StreamReader sr = File.OpenText(fileName))
{
string Line = null;
while ((Line = sr.ReadLine()) != null)
loadedData.Add(GetRec(Line));
}
return loadedData;
}
I just tested this, and it works like a charm!
Of course, this isn't helping me to learn how to write generic methods or use reflection, but I'll take it...
I'm relatively new to c# and I am trying to write a program that finds the mean of every xth value in a file using Streamreader. (For example if I wanted to find the mean of every fifth value in that file)
I written some code that reads the file and splits it into a new line for each comma, and this works fine, when I try and read each specific value.
However I'm struggling to think of a way to find every specific value, such as every 4th one and then find the mean of these and output it in the same program.
static void Main(string[] args)
{
using (var reader = new StreamReader(#"file"))
{
List<string> list = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
list.Add(values[0]);
}
}
}
Any suggestions or help would be greatly appreciated
Try like this;
static void Main()
{
using (var reader = new StreamReader(#"file"))
{
int lineNumber = 4;
bool streamEnded = false;
List<string> list = new List<string>();
while (!streamEnded)
{
var line = ReadSpecificLine(reader, lineNumber,out streamEnded);
if (string.IsNullOrEmpty(line))
{
continue;
}
var values = line.Split(',');
list.Add(values[0]);
}
}
}
public static string ReadSpecificLine(StreamReader sr, int lineNumber,out bool streamEnded)
{
streamEnded = false;
for (int i = 1; i < lineNumber; i++)
{
if (sr.EndOfStream)
{
streamEnded = true;
return "";
}
sr.ReadLine();
}
if (sr.EndOfStream)
{
streamEnded = true;
return "";
}
return sr.ReadLine();
}
I have 2 listbox,
lbProxy = contain proxy list
lbKeyword = contain keyword list.
I want to process the keyword list, 1 keyword using 1 proxy. If number of proxy list less than keyword list, then loop proxy list again.
I don't know how to change proxy after 1 keyword is processed.
Full Code
private void useproxy()
{
foreach (string prox in lbProxy.Items)
{
WebClient fetch = new WebClient();
string numResults = nudPages.Value.ToString();
int delay = Convert.ToInt32(nudDelay.Value);
if (lblStatusProxy.InvokeRequired)
{
lblStatusProxy.Invoke(new MethodInvoker(delegate
{
lblStatusProxy.Text = "Using: " + prox;
}));
}
WebProxy wp = new WebProxy(prox);
fetch.Proxy = wp;
foreach (string kw in lbKeyword.Items)
{
keywords = kw;
if (lblStatusKeyword.InvokeRequired)
{
lblStatusKeyword.Invoke(new MethodInvoker(delegate
{
lblStatusKeyword.Text = "Processing Keyword :" + kw;
}));
}
string downloadUrl = "https://www.google.com" + "/search?q=" + kw + "&num=" + numResults + "&as_qdr=all&ei=LrUVVf7UMrPfsAS7lICgCw&sa=N&biw=1440&bih=690";
fetch.Headers.Set(HttpRequestHeader.Host, "www.google.com");
string data = fetch.DownloadString(downloadUrl);
string[] results = TopUrls(data);
foreach (string lines in results)
{
if (lbBlog.InvokeRequired)
{
lbBlog.Invoke(new MethodInvoker(delegate
{
lbBlog.Items.Add(lines);
}
));
}
}
}
}
}
Thank you,
You can use a plain for and the modulus operand:
for(int buc = 0; buc < lbKeyword.Items.Count; buc++)
{
var proxy = lbProxy.Items[buc % lbProxy.Items.Count];
var keyword = lbKeyword.Items[buc];
//Now you have keyword and proxy to continue with your code.
}
The trick here is the modulus operand, as it's aplied over lbProxy.Items.Count it will give you a value between 0 and lbProxy.Items.Count - 1, just the index you were looking for.
Here is a sample of my code.
Here I recieve a string variable from another page.
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
string newparameter = this.NavigationContext.QueryString["search"];
weareusingxml();
displayResults(newparameter);
}
private void displayResults(string search)
{
bool flag = false;
try
{
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = myIsolatedStorage.OpenFile("People.xml", FileMode.Open))
{
XmlSerializer serializer = new XmlSerializer(typeof(List<Person>));
List<Person> data = (List<Person>)serializer.Deserialize(stream);
List<Result> results = new List<Result>();
for (int i = 0; i < data.Count; i++)
{
string temp1 = data[i].name.ToUpper();
string temp2 = "*" + search.ToUpper() + "*";
if (temp1 == temp2)
{
results.Add(new Result() {name = data[i].name, gender = data[i].gender, pronouciation = data[i].pronouciation, definition = data[i].definition, audio = data[i].audio });
flag = true;
}
}
this.listBox.ItemsSource = results;
}
catch
{
textBlock1.Text = "error loading page";
}
if(!flag)
{
textBlock1.Text = "no matching results";
}
}
Nothing is loaded into the list when the code is run, I just get the message "no matching results".
Looks like you are trying to do a contains search (my guess based on your addition of the * around the search string. You can remove the '*' and do a string.Contains match.
Try this.
string temp1 = data[i].name.ToUpper();
string temp2 = search.ToUpper()
if (temp1.Contains(temp2))
{
It looks like you are trying to check if one string contains another (ie substring match) and not if they are equal.
In C#, you do this like this:
haystack = "Applejuice box";
needle = "juice";
if (haystack.Contains(needle))
{
// Match
}
Or, in your case (and skip the * you added to the string temp2)
if (temp1.Contains(temp2))
{
// add them to the list
}
Have you checked to make sure data.Count > 0?