How to serialize a few times in Windows 8 apps - c#

Hi I tried everything :D
I have problem when i try deserialize file.xml a few times in windows app. Thx for help :)
Windows 8 app
I have MainPage, when I have menu
Someone picks "show data"
it goes on "dataPage"
I deserialize plik.xml, and show data, app shows data, everthing is good
I back to MainPage, and again i want to show data from the same file, but now i Cant read nothing, i mean 'word's doesnt contain data
DESERIALIZATION
StorageFile sessionFile;
var serializer = new XmlSerializer(typeof(List<word>));
words = new List<word>();
try
{
if (await XMLModifier.IsFileExists(XMLModifier.wordsContainter, ApplicationData.Current.LocalFolder) == true)
{
sessionFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(XMLModifier.wordsContainter, CreationCollisionOption.OpenIfExists);
IInputStream sessionInputStream = await sessionFile.OpenReadAsync();
words = (List<word>)serializer.Deserialize(sessionInputStream.AsStreamForRead());
sessionInputStream.Dispose();
}
else
{
string data = DateTime.Now.Day + "-" + DateTime.Now.Month + "-" + DateTime.Now.Year;
word w = new word("Base is empty", "Base is empty", data, 0, 0, 0);
words.Add(w);
}
}
catch (Exception e)
{
..............
}

Related

Cleaning up nested if statements to be more readable?

I'm writing a project, and the part I'm doing now is getting arrow shaped real fast. How can I remove the nested if statements, but still have the same behaviour?
The code below might not look so bad now, but I'm planning on refactoring to include more methods.
public async Task FirstDiffTestAsync()
{
string folderDir = "../../../";
string correctReportDir = folderDir + "Reports To Compare/Testing - Copy.pdf";
string OptyNumber = "122906";
//Making a POST call to generate report
string result = ReportGeneration(OptyNumber).Result;
Response reportResponse = JsonConvert.DeserializeObject<Response>(result);
string newURL = reportResponse.documentUrl;
//Logging the Response to a text file for tracking purposes
await File.WriteAllTextAsync(Context.TestRunDirectory + "/REST_Response.txt", result);
using (StreamWriter w = File.AppendText(Context.TestDir + "/../log.txt"))
{
//Checking if the Integration failed
if (reportResponse.Error == null)
{
//now we have the url, reading in the pdf reports
List<string> Files = new List<string> { correctReportDir, newURL };
List<string> parsedText = PdfToParsedText(Files);
DiffPaneModel diff = InlineDiffBuilder.Diff(parsedText[0], parsedText[1]);
// DiffReport is a customised object
DiffReport diffReport = new DiffReport(correctReportDir, newURL);
diffReport.RunDiffReport(diff);
//In-test Logging
string indent = "\n - ";
string logMsg = $"{indent}Opty Number: {OptyNumber}{indent}Activity Number: {reportResponse.ActivityNumber}{indent}File Name: {reportResponse.FileName}";
if (diffReport.totalDiff != 0)
{
await File.WriteAllTextAsync(Context.TestRunDirectory + "/DiffReport.html", diffReport.htmlDiffHeader + diffReport.htmlDiffBody);
logMsg += $"{indent}Different lines: {diffReport.insertCounter} Inserted, {diffReport.deleteCounter} Deleted";
}
LogTesting(logMsg, w);
//Writing HTML report conditionally
if (diffReport.totalDiff != 0)
{
await File.WriteAllTextAsync(Context.TestRunDirectory + "/DiffReport.html", diffReport.htmlDiffHeader + diffReport.htmlDiffBody);
}
Assert.IsTrue(diffReport.insertCounter + diffReport.deleteCounter == 0);
}
else
{
LogTesting($" Integration Failed: {reportResponse.Error}", w);
Assert.IsNull(reportResponse.Error);
}
}
}
As mentioned in the comment, the indentation level is fine for now, but its always better to minimize when possible, especially when you are repeating same blocks of code.
The best way to do this is to write a separate function that contains that block of code and then call that function instead of the nested if statements.
In your case it would be something like this:
private async void checkTotalDiff(diffReport) {
...
}
You could pass anything you might need in the parameters. This way in your main code, you could replace the if statements with checkTotalDiff(diffReport) and save the return (if any) to a variable.
Also note I used void for return but you could change the type depending on what the function returns.
I wouldn't consider this as having an excessive amount of nested if-statements. It is fine as is. Otherwise you could do the following (also suggested by #Caius Jard):
public async Task FirstDiffTestAsync()
{
string folderDir = "../../../";
string correctReportDir = folderDir + "Reports To Compare/Testing - Copy.pdf";
string OptyNumber = "122906";
//Making a POST call to generate report
string result = ReportGeneration(OptyNumber).Result;
Response reportResponse = JsonConvert.DeserializeObject<Response>(result);
//Checking if the Integration failed
if (reportResponse.Error != null)
{
LogTesting($" Integration Failed: {reportResponse.Error}", w);
Assert.IsNull(reportResponse.Error);
return;
}
string newURL = reportResponse.documentUrl;
//Logging the Response to a text file for tracking purposes
await File.WriteAllTextAsync(Context.TestRunDirectory + "/REST_Response.txt", result);
using (StreamWriter w = File.AppendText(Context.TestDir + "/../log.txt"))
{
//now we have the url, reading in the pdf reports
List<string> Files = new List<string> { correctReportDir, newURL };
List<string> parsedText = PdfToParsedText(Files);
DiffPaneModel diff = InlineDiffBuilder.Diff(parsedText[0], parsedText[1]);
// DiffReport is a customised object
DiffReport diffReport = new DiffReport(correctReportDir, newURL);
diffReport.RunDiffReport(diff);
//In-test Logging
string indent = "\n - ";
string logMsg = $"{indent}Opty Number: {OptyNumber}{indent}Activity Number: {reportResponse.ActivityNumber}{indent}File Name: {reportResponse.FileName}";
if (diffReport.totalDiff != 0)
{
await File.WriteAllTextAsync(Context.TestRunDirectory + "/DiffReport.html", diffReport.htmlDiffHeader + diffReport.htmlDiffBody);
logMsg += $"{indent}Different lines: {diffReport.insertCounter} Inserted, {diffReport.deleteCounter} Deleted";
}
LogTesting(logMsg, w);
//Writing HTML report conditionally
if (diffReport.totalDiff != 0)
{
await File.WriteAllTextAsync(Context.TestRunDirectory + "/DiffReport.html", diffReport.htmlDiffHeader + diffReport.htmlDiffBody);
}
Assert.IsTrue(diffReport.insertCounter + diffReport.deleteCounter == 0);
}
}

EPPlus Dispose Doesn't Work

I want to create workbook and then write data using EPPlus. When I create new workbook, it can create successfully. But when I want to write some data to that worksheet, it failed and error says
The process cannot access the file 'filename' because it is being
used by another process.
I have disposed previous ExcelPackage but the error still show when I write data.
//Create new Workbook
private void PengisianBaruBW_DoWork(object sender, DoWorkEventArgs e)
{
this.Invoke(new MethodInvoker(delegate
{
SetPengisianBtn.Enabled = false;
}));
FileInfo filePath = new FileInfo("D:\\Data Pengisian SLA Surabaya\\" + day + "_" + date + ".xlsx");
if (File.Exists(filePath.ToString()))
{
File.Delete(filePath.ToString());
}
using (ExcelPackage pck = new ExcelPackage(filePath))
{
var schedule = pck.Workbook.Worksheets.Add("Schedule");
var cart = pck.Workbook.Worksheets.Add("Cartridge");
var unsche = pck.Workbook.Worksheets.Add("Unschedule");
var rekap = pck.Workbook.Worksheets.Add("Rekap");
//My Code here
pck.SaveAs(filePath);
pck.Dispose(); //I have disposed ExcelPakcage here
}
}
//Write Data to Excel File
private void PrintScheduleBtn_Click(object sender, EventArgs e)
{
if (StaffATB.Text != "" && HelperTeamATB.Text != "" && StaffBTB.Text != "" && HelperTeamBTB.Text != "" && StaffCTB.Text != "" && HelperTeamCTB.Text != "" && StaffDTB.Text != "" && HelperTeamDTB.Text != "")
{
DialogResult dialogResult = MessageBox.Show("Apakah Anda yakin ingin menyimpan jadwal pengisian ?", "", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
FileInfo file = new FileInfo("D:\\Data Pengisian SLA Surabaya\\" + day + "_" + date + ".xlsx");
using (ExcelPackage pck = new ExcelPackage(file)) //error here
{
var rekap = pck.Workbook.Worksheets["Rekap"];
var data = pck.Workbook.Worksheets["Data"];
//my code to write data here
pck.SaveAs(file);
pck.Dispose();
}
}
}
else
{
MessageBox.Show("Silakan isi PIC terlebih dahulu !");
}
}
I have added this code to check whether my excel file is active or not. But the error still exsit. I set breakpoint and I see that stream value is null that indicate that my excel file is close. But why the error still exists ? Can anyone help me ?
string file = "D:\\Data Pengisian SLA Surabaya\\" + day + "_" + date + ".xlsx";
var path = Path.Combine(Path.GetTempPath(), "D:\\Data Pengisian SLA Surabaya\\" + day + "_" + date + ".xlsx");
var tempfile = new FileInfo(path);
FileStream stream = null;
try
{
stream = tempfile.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch (IOException)
{
}
finally
{
if (stream != null)
stream.Close();
}
I simplified your snippet for testing. It all worked as it should. Are you sure there is no other cause of the file access problem, like a virus scanner, backup program etc. since you also have another question with the same basic problem.
Take a look at the snippet below, try it and see if this one works. If not the problem is not in the code.
FileInfo filePath = new FileInfo("ExcelDemo.xlsx");
if (File.Exists(filePath.ToString()))
{
File.Delete(filePath.ToString());
}
using (ExcelPackage pck = new ExcelPackage(filePath))
{
var schedule = pck.Workbook.Worksheets.Add("Schedule");
var cart = pck.Workbook.Worksheets.Add("Cartridge");
var unsche = pck.Workbook.Worksheets.Add("Unschedule");
var rekap = pck.Workbook.Worksheets.Add("Rekap");
pck.SaveAs(filePath);
}
using (ExcelPackage pck = new ExcelPackage(filePath))
{
var rekap = pck.Workbook.Worksheets["Rekap"];
var schedule = pck.Workbook.Worksheets["Schedule"];
rekap.Cells[4, 1].Value = "Added data";
schedule.Cells[4, 1].Value = "Added data";
pck.SaveAs(filePath);
}
As already stated, the basic code should work just fine. However, looking at your code, I sense that you are using some kind of BackgroundWorker (PengisianBaruBW_DoWork name suggests this).
If so, you might run into accessing the same file from another thread (PengisianBaruBW_DoWork executes in parallel with PrintScheduleBtn_Click).
To help you more, you should add where (what line) do you receive this error and the call stack.
[Edit]
Based on additional comments, I think of one of these scenarios:
1) PengisianBaruBW_DoWork gets called many times and sometimes it happens to do work with the file, while PrintScheduleBtn_Click is trying to do work with the same file
2) An unhandled exception in _DoWork might get swallowed and leave the file opened (highly improbable since you have a disposable context).
Either way, put a breakpoint at the start of your _DoWork and one at beginning of PrintScheduleBtn_Click and use step over (F10).
I know this an old post, but it never got solved. I ran into the same problem, but i think i found the solution for it (at least it unlocked my excel file):
excelPackage.Dispose();
excelPackage = null;
GC.Collect();

How to override a specific line in a text file in c#

I have the following situation. I am creating a quiz game in c# visual studio and want to create a Register and Login forms. When a user registers a new account the text file will store their username and password and will set the high score to 0. Each line in the text file looks like that: username;password;highscore. ';' is the delimiter. I have created a new project to create a practice login/ register form. Here is my code for the register form:
private void btnRegister_Click(object sender, EventArgs e)
{
if (txtPassword.Text == txtConfirmPassword.Text)
{
string newAccount = txtName.Text + ";" + txtConfirmPassword.Text + ";" + "0";
TextWriter account = new StreamWriter("../../TextFile/LogonDetails.txt", true);
account.WriteLine(newAccount);
account.Close();
MessageBox.Show("Account created");
}
and here is my code for the login form
string line = "";
StreamReader myReader = new StreamReader("../../TextFile/LogonDetails.txt");
string[] accounts = new string[900000]; int value = 0;
while ((line=myReader.ReadLine()) != null)
{
string[] data = line.Split(';');
if ((data[0] == txtLoginName.Text) && (data[1] == txtLoginPassword.Text) && (int.Parse(data[2]) > int.Parse(txtScore.Text)))
{
value = 1;
break;
}
if ((data[0] == txtLoginName.Text) && (data[1] == txtLoginPassword.Text) && (int.Parse(data[2]) < int.Parse(txtScore.Text)))
{
value = 2;
break;
}
else
{
value = 3;
}
}
if (value == 1)
{
MessageBox.Show("Your score remains the same");
}
else if (value == 2)
{
string updatedAccount = txtLoginName.Text + ";" + txtLoginPassword.Text + ";" + txtScore;
TextWriter textAccounts = new StreamWriter("../../TextFile/LogonDetails.txt");
textAccounts.WriteLine(updatedAccount);
textAccounts.Close();
}
else if (value == 3)
{
MessageBox.Show("Account not found");
}
}
So my question is how can I override the line stored in the text file if in this case 'txtScore' is greater than data[2]? I have tried creating a new line each time the score is greater but that seems inefficient. Is there a way that i can override the line to change the score value? Any help is greatly appreciated
If the file is not that long you can do something like this:
String fileName = #"C:\LogonDetails.txt";
var data = File
.ReadLines(fileName)
.Select(line => line.Split(';'))
.Select(items => {
if ((items[0] == txtLoginName.Text) &&
(items[1] == txtLoginName.Text) &&
(int.Parse(items[2]) < int.Parse(txtScore.Text)))
items[2] = int.Parse(txtScore.Text);
return items;
})
.ToList(); // materialize in oreder to prevent file read/write collision
File.WriteAllLines(fileName, data);
There is no straightforward way to target a specific line in a text file to update the contents on that line. I would suggest storing your information in an XML (structured data) format; .NET already has the capabilities built in for reading and writing to specific nodes in an XML file.
If you don't want to do that, then my suggestion would be that you load all the lines from the text file into memory as instances of, e.g. a User class that has as properties your username, password, and score, and then write them all back out to your data file all at once with any updates to the scores.
By the way, it's generally not a good idea to store passwords in plain text, so I would hope you're at least employing a hashing algorithm.
Well, based on your question you know the line number, so do something like this:
var lines = File.ReadAllLines(#"path to file");
if (lines.Contains("1234"))
{
lines[Array.IndexOf(lines, "1234")] = "new york";
}
File.WriteAllLines(#"path to file", lines);
try like this.

Cancel a method by user input or non response

The website I am working on allows users to generate reports between two dates that are selected by the user. The problem I am having is that if a user accidently requests a report between a massive date difference i.e. one year the server is put under a lot of pressure and sometimes can crash for all users. What I what to do is have some kind of a progress bar showing the user how long the report is going to take and a cancel button or a button to check if they are still there. I was looking at using a cancel token with a task but am not sure is this is what I want. was also thinking about a global linked list with random numbers linked to true false, as the user can open many reports at the same time. I have included some of the relevant code below . I would appreciate any help or a point in the right direction, Thanks
//java script which is passed from and too date and calls method genonereport
window.open('genonereport?idd=' + idd + '&fromm=' +
fromm + '&too=' + too + '&filetype=' + outputValue ,
'_blank');
// genonereport passes on the values to the class below which contains the relevant method
---report.render which is the method that I want to cancel if user cancels report or if they leave
public byte[] genReportBytes(int id, string fromm, string too, string filetype)
{
reportDetails repD = new reportDetails();
repD = getOneReport(id);
LocalReport report = new LocalReport();
if (fromm != null)
repD.ParametersCommandLine = "#startdate=" + fromm;
if (too != null)
repD.ParametersCommandLine += " #enddate=" + too;
string RDLCPath = ConfigurationManager.AppSettings["RDLCPath"];
string ReportOutputPath = ConfigurationManager.AppSettings["ReportOutputPath"];
string RDLCName = repD.RDLCName;
RDLCPath += #"\" + RDLCName;
report.ReportPath = RDLCPath;
string sqlGet = repD.SQLOfReport;
report.DataSources.Add(new ReportDataSource(repD.DatasetName, getReportData(sqlGet, repD.ParametersCommandLine)));
// export to byte array
Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string filenameExtension;
string deviceInf = "";
byte[] bytes = new byte[64];
byte[] empty = null;
string extension;
bool Completed;
if (filetype == "pdf")
{
deviceInf = "<DeviceInfo><PageHeight>8.5in</PageHeight><PageWidth>11in</PageWidth><MarginLeft>0in</MarginLeft><MarginRight>0in</MarginRight></DeviceInfo>";
//fileName = ReportOutputPath + #"\" + repD.NameOfOutputPDF + ".PDF";
//Completed = ExecuteWithTimeLimit(TimeSpan.FromMilliseconds(5000), () =>
//{
bytes = report.Render("pdf", deviceInf, out mimeType, out encoding, out filenameExtension,
out streamids, out warnings);
//});
}
else
{
//fileName = ReportOutputPath + #"\" + repD.NameOfOutputPDF + ".XLS";
//Completed = ExecuteWithTimeLimit(TimeSpan.FromMilliseconds(5000), () =>
//{
bytes = report.Render(
"Excel");
//});
}
//if (Completed == true)
//{
return bytes;
//}
//else
//return empty;
}
// I have gotten this far but this only cancels after a certain amount of time which isn't much good to me
public static bool ExecuteWithTimeLimit(TimeSpan timeSpan, Action codeBlock)
{
try
{
Task task = Task.Factory.StartNew(() => codeBlock());
task.Wait(timeSpan);
return task.IsCompleted;
}
catch (AggregateException ae)
{
throw ae.InnerExceptions[0];
}
}
sorry about the long winded question, Thanks again
You are going to need at least three web endpoints:
one to generate the report and return the results
one that your Javascript can request periodically to check on progress
one that your browser can request to cancel the task
You would need to store a handle to each task in a dictionary with some sort of id, so you can pass the id into queries 2 and 3.
This article gives you an example of how to do this.
It's not simple, so limiting the size of the report that users can generate might be the preferred option.

Check file size before adding background transfer request

I'm kind of newbie and i'm working on a background transfer feature to download files. It's for windows phone 7. But the problem is files over 100 MB can't be downloaded with "Transfer Preference = Allow Battery" and if i use "Transfer Preference = None" the phone must be connected to a power source in order to transfer (any file size). So far this is what i have tried but it just doesn't work with files over 100MB. Any help, or suggestion would be great. Thanks!
private void downloadTrigger()
{
string transferFileName = urlTextBox.Text;
var transferUri = new Uri(Uri.EscapeUriString(transferFileName), UriKind.Absolute);
BackgroundTransferRequest transferRequest = new BackgroundTransferRequest(transferUri);
transferRequest.Method = "GET";
string downloadFile = transferFileName.Substring(transferFileName.LastIndexOf("/") + 1);
Uri downloadUri = new Uri("shared/transfers/" + downloadFile, UriKind.Relative);
transferRequest.DownloadLocation = downloadUri;
transferRequest.Tag = downloadFile;
if (transferRequest.TotalBytesToReceive >= 104857600)
{
try
{
transferRequest.TransferPreferences = TransferPreferences.None;
MessageBox.Show("For files over 100MB an external power is required to start copy.", "News box", MessageBoxButton.OK);
BackgroundTransferService.Add(transferRequest);
feedbackTextBlock.Text = "Queueing " + downloadFile;
return;
}
catch
{
}
}
try
{
transferRequest.TransferPreferences = TransferPreferences.AllowBattery;
BackgroundTransferService.Add(transferRequest);
feedbackTextBlock.Text = "Copying " + downloadFile;
}
catch
{
}
}

Categories

Resources