Save text in a file without deleting in windows form c# - c#

I was creating a program in Windows forms and I wanted to save the username and the password in 2 separate files.
One is named: name. The second is named: password.
So first I check if the 2 files are empty but when I run the code it deletes the data on the files.
private void btn1_Click(object sender, EventArgs e)
{
int count = 0;
TextWriter name = new StreamWriter("C:\\Users\\skerd\\AppData\\Local\\Temp\\jvvhbbcp..txt");
TextWriter psswd = new StreamWriter("C:\\Users\\skerd\\AppData\\Local\\Temp\\x1pu0bds..txt");
if (new FileInfo("C:\\Users\\skerd\\AppData\\Local\\Temp\\jvvhbbcp..txt").Length == 0 && new FileInfo("C:\\Users\\skerd\\AppData\\Local\\Temp\\x1pu0bds..txt").Length == 0)
{
if (count < 1)
{
name.Write(txtB_1.Text);
psswd.Write(txtB_2.Text);
name.Close();
psswd.Close();
count++;
}
Close();
}
Let's suppose I insert Carl in the name and Jones in the surname when I restart the program I want that in the files it got in the first one the name and in the second one the surname without deleting anything.
Thanks!

You can load your files content or create new content and then modify your content and then - delete original and replace with new. Although, you could, as additional step, first - rename the original as backup and then save the new and then remove the original backup.
var nameFile = "PATH1";
var pwdFile = "PATH2";
bool nameExists = File.Exists(nameFile);
bool pwdExists = File.Exists(pwdFile);
StringBuilder nameContent = new StringBuilder();
if (nameExists)
nameContent.Append(File.ReadAllText(nameFile));
StringBuilder pwdContent = new StringBuilder();
if (pwdExists)
pwdContent.Append(File.ReadAllText(pwdFile));
// you can potencially do more text manipulations here
nameContent.AppendLine("NEW NAME");
pwdContent.AppendLine("NEW PASSWORD");
if (nameExists)
File.Delete(nameFile);
File.WriteAllText(nameFile, nameContent.ToString());
if (pwdExists)
File.Delete(pwdFile);
File.WriteAllText(pwdFile, pwdContent.ToString());

Related

Streamreader adds Column with opened File Dialog

in the following code I want to have my OpenFileDialog open in a method until a valid file is selected. This works only conditionally. For some reason it adds a column after the message is displayed. This causes correct data tables to also be read incorrectly if I have previously selected an incorrect file.
public static InputData GetCSVData()
{
InputData InputData = new InputData();
OpenFileDialog OFDReader = new OpenFileDialog();
//Filter OpenFileDialog; show only CSV-Files
OFDReader.Filter = "CSV files|*.csv;";
// check if data contains "Date/Time" .
OFDReader.FileOk += delegate (object s, CancelEventArgs ev)
{
//search for Line to start reader
int LineCounter = 0;
var readertmp = new StreamReader(OFDReader.FileName);
while (true)
{
string LineTmp = readertmp.ReadLine();
string record = "Date/Time";
if (LineTmp.Contains(record))
{ break; }
else if (readertmp.EndOfStream)
{
MessageBox.Show("Data has no DataPoints !", "Wrong Data", MessageBoxButtons.OK, MessageBoxIcon.Warning);
ev.Cancel = true;
{ break; }
}
LineCounter++;
}
//read InputData
var reader = new StreamReader(OFDReader.FileName);
for (int i = 0; i < LineCounter; i++)
{
reader.ReadLine();
}
// settings CSVHelper
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
Delimiter = ";", // Set delimiter
};
var csv = new CsvReader(reader, config);
var DataRead = new CsvDataReader(csv);
InputData.DataTable.Load(DataRead);
//check for enough columns
int ColumnCounter = 0;
ColumnCounter = InputData.DataTable.Columns.Count;
if (ColumnCounter <= 2)
{
MessageBox.Show("Data has not enough columns!", "Wrong Data", MessageBoxButtons.OK, MessageBoxIcon.Warning);
ev.Cancel = true;
}
};
if (OFDReader.ShowDialog() == DialogResult.OK)
{
InputData.FilePath = OFDReader.FileName;
}
return InputData;
}
}
It appears you are making this more complicated than it has to be. For starters it seems odd (at least to me) that you would bother with the FileOK delegate. I do not see what difference it would make if the user is presented with an OpenFileDialog once, twice or many times. Using a single OpenFileDialog for this just seems like a waste of effort.
If the user selects a file and it fails to meet the necessary requirements, then simply open another OpenFileDialog and let the user try again. Doing this in a single dialog is certainly possible, however, “where” else would you use this? It appears this dialog is “specific” to a “certain” type of file, why limit the dialog to the requirement we need. I would think a simple method that loops forever until the user selects a valid file or Cancels the OpenFileDialog would be an easier approach.
With that said, following your code is a little odd. The reason for your issue is that the code is reading the file into the InputData.DataTable regardless if the file FAILS having datapoints OR enough columns. Put a breakpoint on the line…
InputData.DataTable.Load(DataRead);
You will see that the DataTable is filled with the data even if the data has no “DataPoints.” After the above line of code executes the next few lines check to see if the DataTable has 2 or more columns of data. If there are not enough columns, then the code simply pops up a message box indicating this.
This appears straight forward, however, the InputData.DataTable STILL HAS THE DATA even if it was bad. Next time you call the above Load method, it will simply ADD the new table to the existing table. It will add the columns if needed and simply add the rows to the bottom of the existing DataTable. Try opening several BAD files then eventually open the good file and you will see many added columns and rows.
I will assume that you may be under the impression that when you call…
ev.Cancel = true;
That the code stops right there and goes back to the first line in the delegate…
int LineCounter = 0;
… this would not be true. The code continues after ev.Cancel = true; is executed.
This can be seen by the fact that you are getting extra columns and rows every time a BAD file is attempted to be opened. A simple solution is to simply create a “new” InputData object just before you call the load method. Something like…
InputData = new InputData();
InputData.DataTable.Load(DataRead);
This will fix the extra columns issue, however, IF the user selects a BAD file and the error message pops up and the user clicks the OK button to go back to the open file dialog… THEN… IF the user then clicks the open file dialogs “Cancel” button, the BAD file will still be displayed in the grid. I am confident you may not want this behavior.
Without going into detail about some of the other strange aspects of the posted code. I proffer one other possible simpler solution as described in the beginning. Granted, the code below uses multiple OpenFileDialogs, however the user still cannot escape until they pick a valid file or cancel the dialog.
Much of the code below is taken from the existing posted code however, it is structured differently. Initially some variables are created before we stat an endless loop. Specifically, the CsvConfiguration variable config has some added properties set that ignore some code crashing problems when reading the file. I am confident you will want to set up the CsvReader to handle these problems the way you want them to be handled.
Once inside the endless while loop, the code creates a new InputData object, initializes a new OpenFileDialog and sets its properties. Then the code displays the OpenFileDialog and when the dialog returns, the DialogResult result variable is set to the dialogs returned DialogResult.
If the dialog returns OK then the code checks to see if the file is an “empty” file. If the file is empty, a message box is displayed to inform the user, then we branch back up to the begging of the loop. If the dialog result is Cancel, then the code will return a “new” InputData object. The reason for the empty check is that an exception (No header record was found) will be throw on the line…
DataRead = new CsvDataReader(csv);
If the file is empty.
I am confident that there may be some CsvHelper property that I missed that would prevent this “empty” file exception. If there is some better way to check for this “empty” file or prevent the exception, I am open to suggestions.
If the file is NOT empty, we continue by opening the file and go ahead and read its data as intended using the CsvDataReader. The idea is that… IF the file reads correctly without errors and fits the requirements, then we will already have the InputData.DataTable set and all that is left to do is to set its FilePath property and return the InputData object.
Once we have the InputData.DataTable we can check the number of columns in the InputData.DataTable. If the number of columns is less than two (2), then pop up the error message box to the user and loop back to the begging of the while loop.
If the InputData.DataTable meets the two (2) or more columns requirement, then another check is made by looping through all the columns in the data table. If at least ONE (1) column name is “Date/Time” then we are done checking the requirements and simply set the InputData.FileName property and return the InputData object.
If none of the column names in the InputData.DataTable columns is named ”Date/Time,” then again we pop up the error message box and loop back to the begging of the while loop.
It should be noted that if the file fails the number of columns test or the column named Date/Time test… then as with your problem, the InputData.DataTable STILL HAS THE DATA. This is OK here since we will re-initialize a “new” InputData object when we loop back up to the begging of the while loop.
Lastly, you do not show the InputData Class, however it appears to have at least two (2) properties… 1) a string FilePath and 2) a DataTable named DataTable??? this looks odd and is ambiguous… I have renamed my InputData object’s DataTable property to DT. The same “ambiguity” applies to the InputData variable which I have changed to TempInputData.
Since the code may “potentially” create numerous InputData objects each time the user selects a BAD file, I have implemented the IDisposable interface in the InputData Class. This way we can use this Class in a using statement and properly dispose of the unused InputData objects the code creates. I hope I have implemented this correctly.
public class InputData : IDisposable {
public DataTable DT;
public string FilePath;
private bool isDisposed;
public InputData() {
DT = new DataTable();
FilePath = "";
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
if (isDisposed) {
return;
}
if (disposing) {
DT?.Dispose();
FilePath = null;
}
isDisposed = true;
}
}
private InputData GetInputDataFromSCV() {
InputData TempInputData;
OpenFileDialog OFDReader;
string initialDirectory = #"D:\Test\CSV";
DialogResult result;
CsvConfiguration config = new CsvConfiguration(CultureInfo.InvariantCulture) {
Delimiter = ";",
IgnoreBlankLines = true,
MissingFieldFound = null,
BadDataFound = null
};
CsvReader csv;
CsvDataReader DataRead;
StreamReader readertmp;
FileInfo fi;
while (true) {
using (TempInputData = new InputData()) {
using (OFDReader = new OpenFileDialog()) {
OFDReader.Filter = "CSV files|*.csv;";
OFDReader.InitialDirectory = initialDirectory;
result = OFDReader.ShowDialog();
if (result == DialogResult.OK) {
fi = new FileInfo(OFDReader.FileName);
if (fi.Length != 0) {
using (readertmp = new StreamReader(OFDReader.FileName)) {
csv = new CsvReader(readertmp, config);
DataRead = new CsvDataReader(csv);
TempInputData.DT.Load(DataRead);
if (TempInputData.DT.Columns.Count > 2) {
foreach (DataColumn column in TempInputData.DT.Columns) {
if (column.ColumnName == "Date/Time") {
TempInputData.FilePath = OFDReader.FileName;
return TempInputData;
}
}
// if we get here we know a column named "Date/Time" was NOT found
MessageBox.Show("Data has no DataPoints !", "Wrong Data", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else {
MessageBox.Show("Data has less than 2 columns?", "Wrong Data", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
}
else {
MessageBox.Show("File is empty!", "Wrong Data", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
else {
if (result == DialogResult.Cancel) {
return new InputData();
}
}
}
}
}
}
I hope this makes sense and helps.
Im sorry for the inconvenience. Sometimes I really make it too complicated for myself. I have now solved it as follows:
if (result == DialogResult.Cancel)
{
if (inputDataHistory.Loadcount != 0)
{
TempInputData.FilePath = inputDataHistory.FilePathCache;
TempInputData.LineCounter = inputDataHistory.LinecounterCache;
var reader = new StreamReader(TempInputData.FilePath);
for (int i = 0; i < TempInputData.LineCounter; i++)
{
reader.ReadLine();
}
csv = new CsvReader(reader, config);
DataRead = new CsvDataReader(csv);
TempInputData.DT.Load(DataRead);
TempInputData.IsDisposed = true;
return TempInputData;
}
else
{
return new InputData();
}
I don't know if it is the most efficient solution but I read the key variables into another class before. These are used when canceling to re-read the file before.

XDocument load multiple XML

I have an ASP.Net webform app.
I have one fileupload in page allow multiple files.
In a foreach loop I try to read all XML the user uploaded to the folder.
The problem occurs if I read the documents. I only get the first XML in the selection. I simple use XDocument.load(filename) in a foreach. What did I wrong?
I fire that loop in a button click event
protected void btnSaveDatabase_Click(object sender, EventArgs e)
{ //hiddenfield in page have name of xml in folder
var filesUploaded = hfXMLuploaded.Value.ToString().Split('-');
try
{
foreach (var file in filesUploaded)
{
string filename = Server.MapPath("~/SFA_XML_Upload/" + file);
var doc = XDocument.Load(filename);
Response.Write(doc.ToString()); // for testing
//SaveDataBaseMyTable(ReadMyTable(doc, filename));
}
my read method:
protected List<SFA_ORDCLI> ReadOrdcli(XDocument doc, string filename)
{
var ordcli = doc.Descendants("table")
.Where(i => (string)i.Attribute("name") == "ordcli")
.Descendants("row")
.Select(e => e.Elements());
List<SFA_ORDCLI> sfaOrdcliList = new List<SFA_ORDCLI>();
foreach (var row in ordcli)
{
SFA_ORDCLI sfaOrdcli = new SFA_ORDCLI();
sfaOrdcli.NomeFileXML = Path.GetFileNameWithoutExtension(filename);
foreach (var field in row)
{
var name = (string)field.Attribute("name");
switch (name)
{
case "RolCodEst"://key
sfaOrdcli.RolCodEst = (string)field;
break;
...other fields
}
}
if (sfaOrdcli != null) sfaOrdcliList.Add(sfaOrdcli);
}
return sfaOrdcliList;
}
in debug i see Load method receive the files name 'name.xml'
but the response print two time the first xml read.
Problem was on SaveAs method:
i did fileUpload.Saveas instead of
file.SaveAs(folderPath + Path.GetFileName(file.FileName));
where file is HttpPostedFile
sorry
bye and tks everybody

Create all the json files at a time by getting all the values from a text file using C#

I create a long text file name POI.txt which contain City name at first and then places name of that city. My Text File look like this-
Flensburg;Flensburger Brauerei;Flensburg station;Fachhochschule Flensburg;Flens-Arena;Duborg-Skolen;Nordertor
Kiel;Walther Schücking Institute of International Law;Ferdinand Tönnies Society;Zoological Museum of Kiel University
Berlin;Battle of Berlin;Timeline of Berlin;Warschauer Straße;Berlin Brandenburger Tor station;Embassy of the United Kingdom, Berlin
and many many city.........
After that I keep the city name in Combobox1 and the places name in Combobox2. So When One city comes in combobox1 it shows all the Places of that city in the 2nd combobox. I create a button after the 2nd Combobox. I use this button to create a json file of a places.
This is my json create method for each place.
public void ToJsonForLocation(string CityName,string PoiName)
{
var startPath = Application.StartupPath;
string folderName = Path.Combine(startPath, "OnePoiJson");
string SubfolderName = Path.Combine(folderName, CityName);
System.IO.Directory.CreateDirectory(SubfolderName);
string fileName = PoiName + ".json";
var path = Path.Combine(SubfolderName, fileName);
var Jpeg_File = new DirectoryInfo(startPath + #"\Image\" + CityName).GetFiles("*.jpg");
POIData Poi=new POIData();
Poi.Name = PoiName;
Poi.Shorttext = new WikiShortText().GetShortText(PoiName);
Poi.GeoCoordinates = GeosFromString(startPath + #"\Latitude Longitude\" + PoiName + ".txt");
Poi.Images = new List<string> { Jpeg_File[0].Name };
//Poi.Images =new List<string> { string.Format("{0:X}.jpg", new WikiImage().GetImage(PoiName).Image.GetHashCode())};
string json = JsonConvert.SerializeObject(Poi,Formatting.Indented);
File.WriteAllText(path,json);
}
I am calling this method in the main form in this way-
private void JSON_Click(object sender, EventArgs e)
{
JSON_Output poi_Json = new JSON_Output();
poi_Json.ToJsonForLocation(comboBox1.Text, comboBox2.Text);
}
Now my problem is that with my code, I need to click every places on the 2nd combobox to create a json file for that city.It takes too much time. I want to create all the file at a time. I know I need to create a dictionary to do this. But As I am very new to handle this situation I want to know how to proceed with it.

update value in file(web.config) present on another machine(shared folder/network) using C#

I have full access to the file present on another machine and while I type
\\username-txd\abcFolder\Configuration\MediaManagerConfig\Web.config
In run command line I am able to access the above mentioned file but when I try to update the value of any attribute in this particular file it is not allowing me to update.
public void updateFileData(string elementKey, string newElementValue)
{
// xmlDoc.Load("\\vinayb2-txd\\atish\\Configuration\\MediaManagerConfig\\Web.config");
// var path = System.Web.HttpContext.Current.Server.MapPath(#filename);
// string serverFilepath= Server.MapPath(#filename);
// FileStream xmlFile = new FileStream(filename, FileMode.Open,FileAccess.Read, FileShare.Read);
// xmlDoc.Load(xmlFile);
// string abc=new Uri(filename).LocalPath;
xmlDoc.Load(#filename);
XmlNodeList elementList = xmlDoc.GetElementsByTagName("add");
for (int i = 0; i < elementList.Count; i++)
{
if (elementList[i].Attributes["key"].Value == elementKey)
{
elementList[i].Attributes["value"].Value = newElementValue;
break;
}
xmlDoc.Save(abc);
}
}
when I am passing the value to xmlDoc.Load(#filename);
The filename is displayed as the passed value which I want. But as soon as I move ahead with debugging the code, I see my filepath gets appended with the d:/ value.
And then the filename becomes
filename="D:\\username-txd\abcFolder\Configuration\MediaManagerConfig\Web.config"
Why does D:// get appended, is it referring my local D drive?
Commented lines are some of the option I tried.
I guess you need to add an extra pair of backslashes before the hostname.
Not \\hostname but \\\\hostname.
So in your case \\\\vinayb2-txd\\atish\\Configuration\\MediaManagerConfig\\Web.config should do the trick.

Checking if a line in a file is obsolete, if yes then delete it

I've got a saved filed called records.txt on the phone. A line of it looks like this:
XY Family, 2015.11.10. 12:12 2
Name of family, date, time and another number.
Now, when the user opens the app, I'd like to check this file, and if there's a date there, that is already passed, then delete that line from the text file.
My logic was, first copy the lines to an array of string, then check each one if the date is passed, and if not, copy those into a new array of string. Delete the text file and create a new one with the 2nd string array.
The funny thing is, my code works with windows forms, but fails on android. Here it is:
var path = global::Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
var records = Path.Combine(path.ToString(), "records.txt");
string[] recordLines; // original lines
string[] newLines; // new lines, excluding the obsolete date lines
int counter = 0;
if (System.IO.File.Exists(records))
{
try
{
recordLines = System.IO.File.ReadAllLines(records);
newLines = new string[recordLines.Length];
foreach(string rl in recordLines)
{
Regex mypattern = new Regex(#"Család, ([ ._0-9A-Za-z-]+) \w");
string recordDate = mypattern.Match(rl).Groups[1].Value;
DateTime dt = Convert.ToDateTime(recordDate);
if (!((dt - DateTime.Today).TotalSeconds < 0))
{
newLines[counter] = rl;
counter++;
}
}
File.Delete(records);
using (StreamWriter sw = new StreamWriter(records))
{
foreach(string s in newLines)
{
sw.WriteLine(s);
}
}
}
catch (Exception)
{
// tba
}
}
EDIT: It fails by not even touching the text file. I tried to create a new one, but it won't do that either. I assume that means something is wrong with the arrays.
I have set two permissions:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
EDIT2: Apparently my phone wrapped the line of the file, therefore making the regex unusable. I'm fixing it right now.
EDIT3: It was indeed the phone's saving problem, it wrapped the text unusable.

Categories