How to read and create new user by every 4th line - c#

So, I read a text file. It looks like this:
TEACHER - TEACHER/STUDENT
adamsmith - ID
Adam Smith - Name
B1u2d3a4 - Password
STUDENT
marywilson
Mary Wilson
s1Zeged
TEACHER
sz12gee3
George Johnson
George1234
STUDENT
sophieb
Sophie Black
SophieB12
And so on, there are all the users.
The user class:
class User
{
private string myID;
private string myName;
private string myPW;
private bool isTeacher;
public string ID
{
get
{
return myID;
}
set
{
myID = value;
}
}
public string Name
{
get
{
return myName;
}
set
{
myName = value;
}
}
public string PW
{
get
{
return myPW;
}
set
{
PW = value;
}
}
public bool teacher
{
get
{
return teacher;
}
set
{
isTeacher = value;
}
}
public override string ToString()
{
return myName;
}
}
The Form1_Load method:
private void Form1_Load(object sender, EventArgs e)
{
List<User> users = new List<User>();
string line;
using (StreamReader sr = new StreamReader("danet.txt"))
{
while ((line=sr.ReadLine())!=null)
{
User user = new User();
user.ID=line;
user.Name=sr.ReadLine();
user.PW=sr.ReadLine();
if(sr.ReadLine=="TEACHER")
{
teacher=true;
}
else
{
teacher=false;
}
users.Add(user);
}
}
}
I want to read the text and store the informations. By this method I get 4 times more user than I should. I was thinking of using for and a couple of things, but I didn't get to a solution.

New answer
Your reader assumes the every fourth line is the user-id, it is not, the absolute first line is a STUDENT/TEACHER line. Either this is a typo, or you have to change your format.
Your PW property will cause a StackOverflowException,
public string PW
{
get
{
return myPW;
}
set
{
PW = value;
}
}
Change the setter to myPW = value;, or just convert them to auto-properties.
Your teacher property has the same error, but on the getter.
You have also missed the () on one of your ReadLine's, but let's just assume this is a typo.
Not using a text-file, but just a string so I'm using a StringReader instead, but it's the same concept.
string stuff =
#"adamsmith
Adam Smith
B1u2d3a4
STUDENT
marywilson
Mary Wilson
s1Zeged
TEACHER
sz12gee3
George Johnson
George1234
STUDENT
sophieb
Sophie Black
SophieB12
STUDENT";
public void Main(string[] args)
{
string line;
var users = new List<User>();
using (var sr = new StringReader(stuff))
{
while ((line = sr.ReadLine()) != null)
{
User user = new User();
user.ID = line;
user.Name = sr.ReadLine();
user.PW = sr.ReadLine();
user.teacher = sr.ReadLine() == "TEACHER";
users.Add(user);
}
}
}
Old answer
There is nothing inherently erroneous with you code. But since you have not provided an actual example of what your "danet.txt" looks like, one must assume the error lies within the data itself.
Your "parser" (if you want to call it that) is not forgiving, i.e. if there is an empty line in your source file or if you just mess up one line (say forget putting in a password or ID) then everything would get offset – but as far as your "parser" is concerned, nothing is wrong.
By default formats which depend on "line positions" or "line offset" are prone to break, especially if the file itself is created by hand versus being auto-generated.
Why not use a denoted format instead? Such as XML, JSON or even just INI. C# can handle either of these, either built in or by external libraries (see the links).
There will never be any way for your "line-by-line" parser to not break if the user makes a faulty input, that is unless you have very strict formats for IDs, names, passwords and "student/teachers". and then validate them, using regular expressions (or similar). But that would defeat the purpose of a simple "line-by-line" format. And by then, you might as well go with a more "complex" format.

while ((line=sr.ReadLine())!=null)
{
User user = new User();
for (int i = 0; i < 4; i++)
{
switch (i)
{
case 1:
user.ID = line;
break;
case 2:
user.Name=sr.ReadLine();
break;
....
}
}
}

Related

Question about file reading and comparing

First Off I have a File That Looks Like This:
//Manager Ids
ManagerName: FirstName_LastName
ManagerLoginId: 12345
And a Text Box That has a five digit code(ex. 12345) That gets entered. When the Enter Key Is pressed it is assigned to a String called: "EnteredEmployeeId", Then What I need is to search the Entire file above for "EnteredEmployeeId" and if it matches then it will open another page, if it doesn't find that number then display a message(That tells you no employee Id found).
So essentially Im trying to open a file search the entire document for the Id then return true or false to allow it too either display an error or open a new page, and reset the EnteredEmployeeId to nothing.
My Code So Far:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Rent_a_Car
{
public partial class Employee_Login_Page : Form
{
public Employee_Login_Page()
{
InitializeComponent();
}
string ManagersPath = #"C:\Users\Name\Visual Studios Project Custom Files\Rent A Car Employee Id's\Managers\Manager_Ids.txt"; //Path To Manager Logins
string EnteredEmployeeId;
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void Employee_Id_TextBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && //Checks Characters entered are Numbers Only and allows them
(e.KeyChar != '0'))
{
e.Handled = true;
}
else if (e.KeyChar == (char)13) //Checks if The "Enter" Key is pressed
{
EnteredEmployeeId = Employee_Id_TextBox.Text; //Assigns EnteredEmployeeId To the Entered Numbes In Text Box
bool result = ***IsNumberInFile***(EnteredEmployeeId, "ManagerLoginId:", ManagersPath);
if (result)
{
//open new window
}
else
{
MessageBox.Show("User Not Found");
}
}
}
}
}
This function will read through whole file and find if there is inserted code. It will work with strings (as it is output of your text box) and will return only true or false (employee is or is not in file) not his name, surname etc.
static bool IsNumberInFile(string numberAsString, string LineName, string FileName)
{
var lines = File.ReadAllLines(FileName);
foreach(var line in lines)
{
var trimmedLine = line.Replace(" ", ""); //To remove all spaces in file. Not expecting any spaces in the middle of number
if (!string.IsNullOrEmpty(trimmedLine) && trimmedLine.Split(':')[0].Equals(LineName) && trimmedLine.Split(':')[1].Equals(numberAsString))
return true;
}
return false;
}
//Example of use
String ManagersPath = #"C:\Users\Name\Visual Studios Project Custom Files\Employee Id's\Managers\Manager_Ids.txt"; //Path To Manager Logins
String EnteredEmployeeId;
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void Employee_Id_TextBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && //Checks Characters entered are Numbers Only and allows them
(e.KeyChar != '0'))
{
e.Handled = true;
}
else if (e.KeyChar == (char)13) //Checks if The "Enter" Key is pressed
{
EnteredEmployeeId = Employee_Id_TextBox.Text; //Assigns EnteredEmployeeId To the Entered Numbes In Text Box
bool result = IsNumberInFile(EnteredEmployeeId, "ManagerLoginId" , ManagersPath)
if(result)
//User is in file
else
//User is not in file
}
}
}
Short answer
Is your question about how to read your file?
private bool ManagerExists(int managerId)
{
return this.ReadManagers().Where(manager => manager.Id == managerId).Any();
}
private IEnumerable<Manager> ReadManagers()
{
using (var reader = System.IO.File.OpenText(managersFileName))
{
while (!reader.EndOfStream)
{
string lineManagerName = reader.ReadLine();
string lineMangerId = reader.ReadLine();
string managerName = ExtractValue(lineManagerName);
int managerId = Int32.Parse(ExtractValue(lineManagerId));
yield return new Manager
{
Id = managerId,
Name = managerName,
}
}
}
private string ExtractValue(string text)
{
// the value of the read text starts after the space:
const char separator = ' ';
int indexSeparator = text.IndexOf(separator);
return text.SubString(indexSeparator + 1);
}
Long Answer
I see several problems in your design.
The most important thing is that you intertwine your manager handling with your form.
You should separate your concerns.
Apparently you have the notion of a sequence of Managers, each Manager has a Name (first name, last name) and a ManagerId, and in future maybe other properties.
This sequence is persistable: it is saved somewhere, and if you load it again, you have the same sequence of Managers.
In this version you want to be able to see if a Manager with a given ManagerId exists. Maybe in future you might want more functionality, like fetching information of a Manager with a certain Id, or Fetch All managers, or let's go crazy: Add / Remove / Change managers!
You see in this description I didn't mention your Forms at all. Because I separated it from your Forms, you can use it in other forms, or even in a class that has nothing to do with a Form, for instance you can use it in a unit test.
I described what I needed in such a general from, that in future I might even change it. Users of my persistable manager collection wouldn't even notice it: I can put it in a JSON file, or XML; I can save the data in a Dictionary, a database, or maybe even fetch it from the internet.
All that users need to know, is that they have to create an instance of the class, using some parameters, and bingo, you can fetch Managers.
You also give users the freedom to decide how the data is to be saved: if they want to save it in a JSON file, changes in your form class will be minimal.
An object that stores sequences of objects is quite often called a Repository.
Let's create some classes:
interface IManager
{
public int Id {get;}
public string Name {get; set;}
}
interface IManagerRepository
{
bool ManagerExists(int managerId);
// possible future extensions: Add / Retrieve / Update / Delete (CRUD)
IManager Add(IManager manager);
IManager Find(int managerId);
void Update(IManager manager);
void Delete(int ManagerId);
}
class Manager : IManager
{
public Id {get; set;}
public string Name {get; set;}
}
class ManagerFileRepository : IManagerRepository,
{
public ManagerFileRepository(string fileName)
{
// TODO implement
}
// TODO: implement.
}
The ManagerFileRepository saves the managers in a file. It hides for the outside world how the file is internally structured. It could be your file format, it could be a CSV-file, or JSON / XML.
I also separated an interface, so if you later decide to save the data somewhere else, for instance in a Dictionary (for unit tests), or in a database, users of your Repository class won't see the difference.
Let's first see if you can use this class.
class MyForm : Form
{
const string managerFileName = ...
private IManagerRepository ManagerRepository {get;}
public MyForm()
{
InitializeComponent();
this.ManagerRepository = new ManagerFileRepository(managerFileName);
}
public bool ManagerExists(int managerId)
{
return this.ManagerRepository.ManagerExists(managerId);
}
Now let's handle your keyPress:
private void Employee_Id_TextBox_KeyPress(object sender, KeyPressEventArgs e)
{
TextBox textBox = (TextBox)sender;
... // code about numbers and enter key
int enteredManagerId = Int32.Parse(textBox.Text);
bool managerExists = this.ManagerExists(enteredManagerId);
if (managerExists) { ... }
}
This code seems to do what you want in an easy way. It looks transparent. The managerRepository is testable, reusable, simple to extend or change, because users won't notice this. So the class looks good. Let's implement
Implement ManagerFileRepository
There are several ways to implement reading the file:
(1) Read everything at construction time
and keep the read data in memory. If you add Managers they are not saved until you say so. Advantages: after initial startup it is fast. You can make changes and later decide not to save them anyway, so it is just like editing any other file. Disadvantage: if your program crashes, you have lost your changes.
(2) Read the file every time you need information
Advantage: data is always up-to-date, even if others edited the file while your program runs. If you change the manager collection it is immediately saved, so other can use it.
Which solution you choose depends on the size of the file and the importance of never losing data. If you file contains millions of records, then maybe it wasn't very wise to save the data in a file. Consider SQLite to save it in a small fairly fast database.
class ManagerFileRepository : IManagerRepository, IEnumerable<IManager>
{
private readonly IDictionary<int, IManager> managers;
public ManagerFileRepository(string FileName)
{
this.managers = ReadManagers(fileName);
}
public bool ManagerExists(int managerId)
{
return this.Managers.HasKey(managerId);
}
private static IEnumerable<IManager> ReadManagers(string fileName)
{
// See the short answer above
}
}
Room for improvement
If you will be using your manager repository for more things, consider to let the repository implement ICollection<IManager> and IReadOnlyCollection<IManager>. This is quite simple:
public IEnumerable<IManager> GetEnumerator()
{
return this.managers.Values.GetEnumerator();
}
public void Add(IManager manager)
{
this.managers.Add(manager.Id, manager);
}
// etc.
If you add functions to change the manager collection you'll also need a Save method:
public void Save()
{
using (var writer = File.CreateText(FullFileName))
{
const string namePrefix = "ManagerName: ";
const string idPrefix = "ManagerLoginId: ";
foreach (var manager in managers.Values)
{
string managerLine = namePrefix + manager.Name;
writer.WriteLine(managerLine);
string idLine = idPrefix + manager.Id.ToString();
writer.WriteLine(idLine);
}
}
}
Another method of improvement: your file structure. Consider using a more standard file structure: CSV, JSON, XML. There are numerous NUGET packages (CSVHelper, NewtonSoft.Json) that makes reading and writing Managers much more robust.
Summary
Because you separated the concerns of persisting your managers from your form, you can reuse the manager repository, especially if you need functionality to Add / Retrieve / Update / Delete managers.
Because of the separation it is much easier to unit test your functions. And future changes won't hinder users of the repository, because they won't notice that the data has changed.
If your Manager_Ids.txt is in the following format, you can use File.ReadLine() method to traverse the text and query it.
ManagerName: FirstName_LastName1
ManagerLoginId: 12345
ManagerName: FirstName_LastName2
ManagerLoginId: 23456
...
Here is the demo that traverse the .txt.
string ManagersPath = #"D:\Manager_Ids.txt";
string EnteredEmployeeId;
private void textBox_id_KeyDown(object sender, KeyEventArgs e)
{
int counter = 0;
bool exist = false;
string line;
string str = "";
if (e.KeyCode == Keys.Enter)
{
EnteredEmployeeId = textBox_id.Text;
System.IO.StreamReader file =
new System.IO.StreamReader(ManagersPath);
while ((line = file.ReadLine()) != null)
{
str += line + "|";
if (counter % 2 != 0)
{
if (str.Split('|')[1].Split(':')[1].Trim() == EnteredEmployeeId)
{
str = str.Replace("|", "\n");
MessageBox.Show(str);
exist = true;
break;
}
str = "";
}
counter++;
}
if (!exist)
{
MessageBox.Show("No such id");
}
file.Close();
}
}
Besides, I recommend to use "xml", "json" or other formats to serialize the data. About storing the data in "xml", you can refer to the following simple demo.
<?xml version="1.0"?>
<Managers>
<Manager>
<ManagerName>FirstName_LastName1</ManagerName>
<ManagerLoginId>12345</ManagerLoginId>
</Manager>
<Manager>
<ManagerName>FirstName_LastName2</ManagerName>
<ManagerLoginId>23456</ManagerLoginId>
</Manager>
</Managers>
And then use LINQ to XML to query the id.
string ManagersPath = #"D:\Manager_Ids.xml";
string EnteredEmployeeId;
private void textBox_id_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
EnteredEmployeeId = textBox_id.Text;
XElement root = XElement.Load(ManagersPath);
IEnumerable<XElement> manager =
from el in root.Elements("Manager")
where (string)el.Element("ManagerLoginId") == EnteredEmployeeId
select el;
if(manager.Count() == 0)
{
MessageBox.Show("No such id");
}
foreach (XElement el in manager)
MessageBox.Show("ManagerName: " + (string)el.Element("ManagerName") + "\n"
+ "ManagerLoginId: " + (string)el.Element("ManagerLoginId"));
}
}

How to get previous data in Xamarin.Forms

I am working on an application which is going to show updated dollar and euro rates for Turkey. I want to print green and red arrows depending on if rates went up or down since the last time user opened the app. So my question is how can I get previous data and how can I compare them with the current data?
CODE-BEHIND;
namespace Subasi.A.M.D
{
public partial class MainPage : ContentPage
{
float banknoteSellingUSD = 0;
float banknoteBuyingUSD = 0;
public MainPage()
{
InitializeComponent();
if (Device.OS == TargetPlatform.iOS)
Padding = new Thickness(10, 50, 0, 0);
else if (Device.OS == TargetPlatform.Android)
Padding = new Thickness(10, 20, 0, 0);
else if (Device.OS == TargetPlatform.WinPhone)
Padding = new Thickness(30, 20, 0, 0);
}
private void Button_Clicked(object sender, EventArgs e)
{
XmlDocument doc1 = new XmlDocument();
doc1.Load("http://www.tcmb.gov.tr/kurlar/today.xml");
XmlElement root = doc1.DocumentElement;
XmlNodeList nodes = root.SelectNodes("Currency");
foreach (XmlNode node in nodes)
{
var attributeKod = node.Attributes["Kod"].Value;
if (attributeKod.Equals("USD"))
{
var GETbanknoteSellingUSD = node.SelectNodes("BanknoteSelling")[0].InnerText;
var GETbanknoteBuyingUSD = node.SelectNodes("BanknoteBuying")[0].InnerText;
//if (banknoteSellingUSD > float.Parse(GETbanknoteSellingUSD)) isusdup = false;
//else isusdup = true;
banknoteSellingUSD = float.Parse(GETbanknoteSellingUSD);
banknoteBuyingUSD = float.Parse(GETbanknoteBuyingUSD);
labelUSDBuying.Text = banknoteSellingUSD.ToString("0.00");
labelUSDSelling.Text = banknoteBuyingUSD.ToString("0.00");
}
var attributeKod1 = node.Attributes["Kod"].Value;
if (attributeKod1.Equals("EUR"))
{
var GETbanknoteSellingEU = node.SelectNodes("BanknoteSelling")[0].InnerText;
var GETbanknoteBuyingEU = node.SelectNodes("BanknoteBuying")[0].InnerText;
var banknoteSellingEU = float.Parse(GETbanknoteSellingEU);
var banknoteBuyingEU = float.Parse(GETbanknoteBuyingEU);
labelEUSelling.Text = banknoteSellingEU.ToString("0.00");
labelEUBuying.Text = banknoteBuyingEU.ToString("0.00");
}
}
}
}
}
print green and red arrows depending on if rates went up or down since the last time user opened the app
To achieve this, you will have to store the previous value. The easiest way may be to use the properties dictionary (see here). You can store simple properties within that.
You could capsule the behavior in a class
public class ExchangeCourseSource : IExchangeCourseSource
{
public ExchangeCourseSource(XmlDocument sourceDocument)
{
this.sourceDocument = sourceDocument;
}
public ExchangeCourse GetCourse(string currency)
{
// parse from XML (see your code)
}
}
class ExchangeCourse
{
public string Currency { get; set; }
public double ExchangeRate { get; set; }
public double Difference { get; set; }
}
and decorate this with a class that stores and retrieved the courses to and fro the properties dictionary
public class StoredExchangeCourseSourceDecorator : IExchangeCourseSource
{
public ExchangeCourseSource(IExchangeCourceSource source, Application application)
{
this.source = source;
this.application = application;
}
public ExchangeCourse GetCourse(string currency)
{
var exchangeCourse = source.GetCourse(currency);
if(HasStoredCourse())
{
var storedCourse = GetStoredCourse(currency);
exchangeCourse.Difference = exchangeCourse.ExchangeRate - storedCourse;
}
StoreCourse(exchangeCourse);
return exchangeCourse;
}
private bool HasStoredCourse(string currency)
{
return application.Properties.ContainsKey(currency);
}
private double GetStoredCourse(string currency)
{
return (double)application.Properties[currency];
}
private void StoreCourse(ExchangeCourse exchangeCourse)
{
application.Properties[exchangeCourse.Currency] = exchangeCourse.ExchangeRate;
application.SavePropertiesAsync().Wait();
}
}
OK, so to answer the question, You have to store data somewhere, the easiest method will be in ISharedPreferences to save and restore data.
From AndroidDeveloper :
If you don't need to store a lot of data and it doesn't require
structure, you should use SharedPreferences. The SharedPreferences
APIs allow you to read and write persistent key-value pairs of
primitive data types: booleans, floats, ints, longs, and strings.
The key-value pairs are written to XML files that persist across user
sessions, even if your app is killed. You can manually specify a name
for the file or use per-activity files to save your data.
So it's a good place to store some info and retrieve them.
All you have to do is to get an instance from ISharedPreferences and use ISharedPreferencesEditor to insert and retrieve data.
You find it in Android.Content Namespace
To save your data you can apply this code :
ISharedPreferences preference = PreferenceManager.GetDefaultSharedPreferences(this);
ISharedPreferencesEditor editor = preference.Edit();
editor.PutString("key", "Value");
editor.Apply();
In your case, you can PutFloat
So your data which is "Value" is saved with a key named "key" is now saved
then you can retrieve data by :
ISharedPreferences preference = PreferenceManager.GetDefaultSharedPreferences(this);
var a = preference .GetString("key", "null");//"null" is the default value if the value not found. and the key, it to retrieve a specific data as we stored the data with the key named "key"
In your case, use GetFloat
So you get your value stored in a variable a.
All you have to do is : Store your data in the Sharedpreference when a new data changed or OnSleep() method which will be called when the app closed, then in OnCreate() method in your app, call the data saved in the SharedPreference and compare it with the new data.

How to write and read list<> from text files in C#

English is not my native language and I am newbie, so don't laugh at me.
I want to create a class in C# that help me to save data to file and read them easily. It works like this:
RealObject john = new RealObject("John");
john.AddCharacter("Full Name", "Something John");
john.AddCharacter("Grade", new List<double> { 9.9, 8.8, 7.7 });
await john.SaveToFileAsync("Test.ini");
RealObject student = new RealObject("John");
await student.ReadFromFileAsync("Test.ini");
Type valueType = student.GetCharacter("Grade").Type;
List<double> johnGrade = (List<double>) student.GetCharacter("Grade").Value;
The file "Test.ini" looks like this:
S_Obj_John
Name System.String Something John
Grade System.Collections.Generic.List`1[System.Double] 9.9;8.8;7.7
E_Obj_John
I have some questions:
Question 1. Can you give me some libraries that do this job for me, please?
Question 2. My code is too redundant, how can I optimize it?
2.1 Saving code: I have to write similar functions: ByteListToString, IntListToString, DoubleListToString,...
private static string ListToString(Type listType, object listValue)
{
string typeString = GetBaseTypeOfList(listType);
if (typeString == null)
{
return null;
}
switch (typeString)
{
case "Byte":
return ByteListToString(listValue);
..........
default:
return null;
}
}
private static string ByteListToString(object listValue)
{
List<byte> values = (List<byte>) listValue;
string text = "";
for (int i = 0; i < values.Count; i++)
{
if (i > 0)
{
text += ARRAY_SEPARATING_SYMBOL;
}
text += values[i].ToString();
}
return text;
}
2.2 Reading code: I have to write similar functions: StringToByteList, StringToIntList, StringToDoubleList,...
public static object StringToList(Type listType, string listValueString)
{
string typeString = GetBaseTypeOfList(listType);
if (typeString == null)
{
return null;
}
switch (typeString)
{
case "Byte":
return StringToByteList(listValueString);
..........
default:
return null;
}
}
private static List<byte> StringToByteList(string listValueString)
{
var valuesString = listValueString.Split(ARRAY_SEPARATING_SYMBOL);
List<byte> values = new List<byte>(valuesString.Length);
foreach (var v in valuesString)
{
byte tmp;
if (byte.TryParse(v, out tmp))
{
values.Add(tmp);
}
}
return values;
}
Thank you for your help
There are two ways two common ways to "serialize" data, which is a fancy way of taking an object and turning it into a string. Then on the other side you can "deserialize" that string and turn it back into an object. Many folks like JSON because it is really simple, XML is still used and can be useful for complex structures but for simple classes JSON is really nice.
I would check out https://www.json.org/ and explore, libraries exist that will serialize and deserialize for you which is nice. Trying to do it with string manipulation is not recommended as most people (including me) will mess it up.
The idea though is to start and end with objects, so take an object and serialize it to save it to the file. Then read that object (really just a string or line of text in the file) and deserialize it back into an object.

How to complete aspx connection string from text file

I must use a text file "db.txt" which inherits the names of the Server and Database to make my connection string complete.
db.txt looks like this:
<Anfang>
SERVER==dbServer\SQLEXPRESS
DATABASE==studentweb
<Ende>
The connection string:
string constr = ConfigurationManager.ConnectionStrings["DRIVER={SQL Server}; SERVER=SERVER DATABASE=DB UID=;PWD=;LANGUAGE=Deutsch;Trusted_Connection=YES"].ConnectionString;
Unfortunatly we are only allowed to use Classic ASPX.net (C# 2.0) and not the web.config.
I've searched a lot, but found nothing close to help me.
Somebody got an Idea how to make it work?
Here is something to get you going.
In a nutshell, I put the DBInfo file through a method that reads the file line by line. When I see the line <anfang> I know the next line will be important, and when I see the line <ende> I know it's the end, so I need to grab everything in between. Hence why I came up with the booleans areWeThereYet and isItDoneYet which I use to start and stop gathering data from the file.
In this snippet I use a Dictionary<string, string> to store and return the values but, you could use something different. At first I was going to create a custom class that would hold all the DB information but, since this is a school assignment, we'll go step by step and start by using what's already available.
using System;
using System.Collections.Generic;
namespace _41167195
{
class Program
{
static void Main(string[] args)
{
string pathToDBINfoFile = #"M:\StackOverflowQuestionsAndAnswers\41167195\41167195\sample\DBInfo.txt";//the path to the file holding the info
Dictionary<string, string> connStringValues = DoIt(pathToDBINfoFile);//Get the values from the file using a method that returns a dictionary
string serverValue = connStringValues["SERVER"];//just for you to see what the results are
string dbValue = connStringValues["DATABASE"];//just for you to see what the results are
//Now you can adjust the line below using the stuff you got from above.
//string constr = ConfigurationManager.ConnectionStrings["DRIVER={SQL Server}; SERVER=SERVER DATABASE=DB UID=;PWD=;LANGUAGE=Deutsch;Trusted_Connection=YES"].ConnectionString;
}
private static Dictionary<string, string> DoIt(string incomingDBInfoPath)
{
Dictionary<string, string> retVal = new Dictionary<string, string>();//initialize a dictionary, this will be our return value
using (System.IO.StreamReader sr = new System.IO.StreamReader(incomingDBInfoPath))
{
string currentLine = string.Empty;
bool areWeThereYet = false;
bool isItDoneYet = false;
while ((currentLine = sr.ReadLine()) != null)//while there is something to read
{
if (currentLine.ToLower() == "<anfang>")
{
areWeThereYet = true;
continue;//force the while to go into the next iteration
}
else if (currentLine.ToLower() == "<ende>")
{
isItDoneYet = true;
}
if (areWeThereYet && !isItDoneYet)
{
string[] bleh = currentLine.Split(new string[] { "==" }, StringSplitOptions.RemoveEmptyEntries);
retVal.Add(bleh[0], bleh[1]);//add the value to the dictionary
}
else if (isItDoneYet)
{
break;//we are done, get out of here
}
else
{
continue;//we don't need this line
}
}
}
return retVal;
}
}
}

500 error when querying yahoo placefinder with a particular character?

I am using the Yahoo Placefinder service to find some latitude/longitude positions for a list of addresses I have in a csv file.
I am using the following code:
String reqURL = "http://where.yahooapis.com/geocode?location=" + HttpUtility.UrlEncode(location) + "&appid=KGe6P34c";
XmlDocument xml = new XmlDocument();
xml.Load(reqURL);
XPathNavigator nav = xml.CreateNavigator();
// process xml here...
I just found a very stubborn error, that I thought (incorrectly) for several days was due to Yahoo forbidding further requests from me.
It is for this URL:
http://where.yahooapis.com/geocode?location=31+Front+Street%2c+Sedgefield%2c+Stockton%06on-Tees%2c+England%2c+TS21+3AT&appid=KGe6P34c
My browser complains about a parsing error for that url. My c# program says it has a 500 error.
The location string here comes from this address:
Agape Business Consortium Ltd.,michael.cutbill#agapesolutions.co.uk,Michael A Cutbill,Director,,,9 Jenner Drive,Victoria Gardens,,Stockton-on-Tee,,TS19 8RE,,England,85111,Hospitals,www.agapesolutions.co.uk
I think the error comes from the first hyphen in Stockton-on-Tee , but I can't explain why this is. If I replace this hypen with a 'normal' hyphen, the query goes through successfully.
Is this error due to a fault my end (the HttpUtility.UrlEncode function being incorrect?) or a fault Yahoo's end?
Even though I can see what is causing this problem, I don't understand why. Could someone explain?
EDIT:
Further investigation on my part indicates that the character this hypen is being encoded to, "%06", is the ascii control character "Acknowledge", "ACK". I have no idea why this character would turn up here. It seems that differrent places render Stockton-on-Tee in different ways - it appears normal opened in a text editor, but by the time it appears in Visual Studio, before being encoded, it is Stocktonon-Tees. Note that, when I copied the previous into this text box in firefox, the hypen rendered as a weird, square box character, but on this subsequent edit the SO software appears to have santized the character.
I include below the function & holder class I am using to parse the csv file - as you can see, I am doing nothing strange that might introduce unexpected characters. The dangerous character appears in the "Town" field.
public List<PaidBusiness> parseCSV(string path)
{
List<PaidBusiness> parsedBusiness = new List<PaidBusiness>();
List<string> parsedBusinessNames = new List<string>();
try
{
using (StreamReader readFile = new StreamReader(path))
{
string line;
string[] row;
bool first = true;
while ((line = readFile.ReadLine()) != null)
{
if (first)
first = false;
else
{
row = line.Split(',');
PaidBusiness business = new PaidBusiness(row);
if (!business.bad) // no problems with the formatting of the business (no missing fields, etc)
{
if (!parsedBusinessNames.Contains(business.CompanyName))
{
parsedBusinessNames.Add(business.CompanyName);
parsedBusiness.Add(business);
}
}
}
}
}
}
catch (Exception e)
{ }
return parsedBusiness;
}
public class PaidBusiness
{
public String CompanyName, EmailAddress, ContactFullName, Address, Address2, Address3, Town, County, Postcode, Region, Country, BusinessCategory, WebAddress;
public String latitude, longitude;
public bool bad;
public static int noCategoryCount = 0;
public static int badCount = 0;
public PaidBusiness(String[] parts)
{
bad = false;
for (int i = 0; i < parts.Length; i++)
{
parts[i] = parts[i].Replace("pithawala", ",");
parts[i] = parts[i].Replace("''", "'");
}
CompanyName = parts[0].Trim();
EmailAddress = parts[1].Trim();
ContactFullName = parts[2].Trim();
Address = parts[6].Trim();
Address2 = parts[7].Trim();
Address3 = parts[8].Trim();
Town = parts[9].Trim();
County = parts[10].Trim();
Postcode = parts[11].Trim();
Region = parts[12].Trim();
Country = parts[13].Trim();
BusinessCategory = parts[15].Trim();
WebAddress = parts[16].Trim();
// data testing
if (CompanyName == "")
bad = true;
if (EmailAddress == "")
bad = true;
if (Postcode == "")
bad = true;
if (Country == "")
bad = true;
if (BusinessCategory == "")
bad = true;
if (Address.ToLower().StartsWith("po box"))
bad = true;
// its ok if there is no contact name.
if (ContactFullName == "")
ContactFullName = CompanyName;
//problem if there is no business category.
if (BusinessCategory == "")
noCategoryCount++;
if (bad)
badCount++;
}
}
Welcome to real world data. It's likely that the problem is in the CSV file. To verify, read the line and inspect each character:
foreach (char c in line)
{
Console.WriteLine("{0}, {1}", c, (int)c);
}
A "normal" hyphen will give you a value of 45.
The other problem could be that you're reading the file using the wrong encoding. It could be that the file is encoded as UTF8 and you're reading it with the default encoding. You might try specifying UTF8 when you open the file:
using (StreamReader readFile = new StreamReader(path, Encoding.UTF8))
Do that, and then output each character on the line again (as above), and see what character you get for the hyphen.

Categories