I am running an ASP 4.5 application. One one of the pages the user must answer several questions and the push the button to finish the test. My application uses a text file to analyze the users answers. If the user does everything quickly the application works fine, but when it takes longer then 20 min for him to finish the test I get an exception
Cannot read from a closed TextReader
I do not understand what's wrong, because I open StreamReader only when the button is pressed. This is a part of my code:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GlobalVariables.surname = Request.QueryString["surname"];
GlobalVariables.name = Request.QueryString["name"];
GlobalVariables.gender = Request.QueryString["gender"];
GlobalVariables.age = int.Parse(Request.QueryString["age"]);
}
Label1.Width = 700;
Button1.Click += new EventHandler(this.Button1_Click);
}
void Button1_Click(Object sender, EventArgs e)
{
var f0= new FileStream(Server.MapPath("./key.txt"), FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(f0);
//.....
sr.Close();
sr.Dispose();
}
Could somebody help me please?
when it takes longer then 20 mis for him to finish the test I get an exception
That sounds a lot like their session expired. To fix this, I recommend adding some javascript to establish a heartbeat to the web server. The heartbeat will keep the session alive; it doesn't need to do anything other than simply make a request every minute or so, so the server knows you're still there.
In addition to the answer from Joel I would recommend to separate processing the file from reading the file.
List<string> lines = new List<string>();
using (var f0 = new FileStream(Server.MapPath("./key.txt"), FileMode.Open, FileAccess.Read))
{
string line;
using (StreamReader reader = new StreamReader(f0))
{
while ((line = reader.ReadLine()) != null)
{
lines.add(line);
}
}
}
// it would need to be a very big text file to be a memory issue
// do your processing here
f the page is not a post back, you would want to set up the page as it should be viewed the first time. I would also suggest moving the button click even within the if(!Page.IsPostBack) as well as anything that needs to be setup before a post-back. Move your Stream reader to the else... like so if(!Page.IsPostBack) else { stream reader stuff } and remove the button click even in general since the button causes postback.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GlobalVariables.surname = Request.QueryString["surname"];
GlobalVariables.name = Request.QueryString["name"];
GlobalVariables.gender = Request.QueryString["gender"];
GlobalVariables.age = int.Parse(Request.QueryString["age"]);
Label1.Width = 700;
}
else
{
DoPostBackStuff();
}
}
private void DoPostBackStuff()
{
var f0= new FileStream(Server.MapPath("./key.txt"), FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(f0);
//.....
sr.Close();
sr.Dispose();
}
Related
I have this very large text file (around 35 000+ lines of information) and I would like to extract certain lines from it and place them in another text file.
The text file goes like this:
Feature info
Feature name: 123456
Version: 1
Tokens total: 35
Tokens remaining: 10
And I'd like to extract Feature name and tokens total. What I had in mind was a form with two buttons: 1 for browsing the file and the other to do the whole reading and writing to file part, of course in the same line by line format.
Anyone have any clues on how to do it? I have searched and I haven't really found specific things, also quite new to file read/write...
EDIT
Ok here is what I have so far and it works:
private void button1_Click(object sender, EventArgs e)
{
int counter = 0;
string line;
string s1 = "Feature name";
string s2 = "Tokens total";
// Read the file and display it line by line.
System.IO.StreamReader file = new System.IO.StreamReader("d:\\license.txt");
using (System.IO.StreamWriter file2 = new System.IO.StreamWriter(#"D:\test.txt"))
while ((line = file.ReadLine()) != null)
{
if (line.Contains(s1) || line.Contains(s2))
{
file2.WriteLine(line);
counter++;
}
}
file.Close();
And this is done by a single button. What I want though is to be able to search for the file I want and then use another button in order to do all writing process
Answer for the EDIT:
You can store the read data in property or private field in the form class. Use String or StringBuilder preferably. When the second button is clicked check if there is stored data and write it to the output file.
private StringBuilder data = new StringBuilder();
private void button2_Click(object sender, EventArgs e)
{
if(data.Length > 0)
{
using(System.IO.StreamWriter file2 = new System.IO.StreamWriter(#"D:\test.txt"))
{
file2.Write(data.ToString());
}
}
}
private void button1_Click(object sender, EventArgs e)
{
// Clear the previous store data
data.Clear();
// ...
System.IO.StreamReader file = new System.IO.StreamReader("d:\\license.txt");
while ((line = file.ReadLine()) != null)
{
if (line.Contains(s1) || line.Contains(s2))
{
sb.AppendLine(line);
counter++;
}
}
file.Close();
}
Please add using for System.IO and surround your StreamReader and StreamWriter with using block so your code will be more readable and you won't forget to release the used resources.
You can use StreamReader and StreamWriter for read/write file
To extract specific part of text, you may use Regex.Matches, it will return Match, then you can retrieve the defined group in Match.Groups
// Search name
Match mu = Regex.Match(line, #"Feature name: (\d+)");
// Get name
if (mu.Groups.Count == 1) Console.Writeline(mu.Groups[0].Value);
I am having problems saving a PowerPoint file in an add-in I am writing.
Basically, I need to save the currently open presentation as a wmv and then FTP it to an external server... sounds easy eh?
I have worked out how to save the currently open presentation as a wmv.
I have also got code to check if a file is open so I can tell when the "save" process is complete.
But the code just goes into an infinite loop. The wmv starts for get written but never goes beyond 0kb.
If I remove the line
checkfile(exportPath, exportName);
it works just fine... otherwise it just stays in a loop.
This is the code I have so far...
using System;
using System.Windows.Forms;
using Office = Microsoft.Office.Core;
using PowerPoint = Microsoft.Office.Interop.PowerPoint;
using System.IO;
namespace PowerPointAddIn2
{
public partial class LoginPanel : UserControl
{
public LoginPanel()
{
InitializeComponent();
}
private void LoginPanel_Load(object sender, EventArgs e)
{
}
private void btnLogin_Click(object sender, EventArgs e)
{
string exportName = "video_of_presentation";
string exportPath = #"C:\{0}.wmv";
// Export the currently open presentation
PowerPoint.Application ppApplication = null;
ppApplication = new PowerPoint.Application();
ppApplication.Activate();
ppApplication.ActivePresentation.SaveAs(String.Format(exportPath, exportName), PowerPoint.PpSaveAsFileType.ppSaveAsWMV, Office.MsoTriState.msoTrue);
checkfile(exportPath, exportName);
MessageBox.Show("Finished");
}
protected void checkfile(string exportPath, string exportName)
{
FileInfo f = new FileInfo(String.Format(exportPath, exportName));
while (IsFileLocked(f) == true) { System.Threading.Thread.Sleep(5000); }
MessageBox.Show("Finished");
}
protected virtual bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch (IOException)
{
//the file is unavailable because it is:
//still being written to
//or being processed by another thread
//or does not exist (has already been processed)
return true;
}
finally
{
if (stream != null)
stream.Close();
}
//file is not locked
return false;
}
}
}
Based on a previous thread I posted I also tried Thread.Join() to see if I could simply wait for the save thread to finish before I continued but it didn't pause at all while the file was being saved so I ended up with the same result.
Any help/pointers would be very much appreciated.
Thanks
The PowerPoint Application object has a ppMediaTaskStatus property that should return the info you need for this. You can get the various values using the Object Browser in the PPT VBA IDE .
Here i am passing the session id on a button click from one asp.net application to another asp.net application.
Application 1:
protected void imgBTN_Click(object sender, EventArgs e)
{
string sessionKey = HttpContext.Current.Session.SessionID;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(#"http://localhost:43392/PartnerHome.aspx");
string svcCredentials = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(sessionKey));
req.Headers.Add("Authorization", "Basic " + svcCredentials);
try
{
using (WebResponse svcResponse = (HttpWebResponse)req.GetResponse())
{
using (StreamReader sr = new StreamReader(svcResponse.GetResponseStream()))
{
string jsonTxt = sr.ReadToEnd();
}
}
}
catch (Exception c)
{
}
}
and my problem here is how to retrieve this session id there in my second asp.net application pageload
Application 2:
protected void Page_Load(object sender, EventArgs e)
{
}
Any Suggestion?
Another solution:
What I would do is to add an invisible image (some transparant pixel) on the page of application 1:
<img src="http://site2.domain.com/transpimage.aspx">
The invisible image would actually be a asp.net page hosted by site 2.
In the page load event of transpimage.aspx. I would output some image:
public void Page_Load(...)
{
using(Bitmap image = new Bitmap(1,1))
using(MemoryStream stream = new MemoryStream())
{
image.Save(stream);
Response.ContentType = "image/png";
stream.WriteTo(Response.OutputStream);
Response.End();
}
}
Since the image from application 2 is served by an aspx page (not a static image in a file) it will keep the session of application2 alive. I've done this before and it tends to be fairly robust.
If you are familiar with HttpHandlers you can write the "image page" as a handler, but don't forget that if you do it as a handler you need to inherit from the IRequiresSessionState interface to actually acccess the session.
Hope this helps!
I'm still on my first step on C# and this is my first post/question.
How do I implement Streamreader to Display(output)
Like after clicking the Dataretrieve button I want to retrieve the data located on "D:\Savedata.txt" and display it on the lblDisplay
This is my code, am I missing something?
void DataretrieveClick(object sender, EventArgs e)
{
StreamReader read = File.OpenText("D:\\Savedata.txt");
lblDisplay.Text = "Last Name: " +textBox1.Text.Trim();
read.Close();
}
Something like this should be what you're looking for.
void DataretrieveClick(object sender, EventArgs e)
{
using (StreamReader reader = File.OpenText("D:\\Savedata.txt"))
{
lblDisplay.Text = reader.ReadToEnd();
}
}
When you create an instance of a class that implements interface IDisposable, you should wrap it in a using() statement to make sure the resources for it are freed when you leave the using() scope. Also, you can look over the documentation for StreamReader here which should help you see what's available.
There is very handy static method ReadAllText in File class, which will open a text file, read all lines of the file, and then close the file:
lblDisplay.Text = File.ReadAllText("D:\\Savedata.txt");
Internally this method does exactly what you are trying to implement (creates StreamReader and reads all characters from the current position to the end of the stream):
using (var reader = new StreamReader(path, Encoding.UTF8, true, 0x400, true))
{
return reader.ReadToEnd();
}
You're looking for read.ReadToEnd().
I have a textbox where a user can input their email, what I want to do is make it so that when they click a submit button. That email will be saved into a text file ( on my server ) called emails.txt
I managed to get this working using System.IO and then using the File.WriteAll method. However I want to make it so that it will add the email to the list ( on a new line ) rather then just overwriting whats already in there.
I've seen people mention using Append, but I can't quite grasp how to get it working.
This is my current code (that overwrites instead of appending).
public partial class _Default : Page
{
private string path = null;
protected void Page_Load(object sender, EventArgs e)
{
path = Server.MapPath("~/emails.txt");
}
protected void emailButton_Click(object sender, EventArgs e)
{
File.WriteAllText(path, emailTextBox.Text.Trim());
confirmEmailLabel.Text = "Thank you for subscribing";
}
}
You can use StreamWriter to get working with text file. The WriteLine method in true mode append your email in new line each time....
using (StreamWriter writer = new StreamWriter("email.txt", true)) //// true to append data to the file
{
writer.WriteLine("your_data");
}
From the official MSDN documentation:
using (StreamWriter w = File.AppendText("log.txt"))
{
MyWriteFunction("Test1", w);
MyWriteFunction("Test2", w);
}
Use StreamWriter in Append mode. Write your data with WriteLine(data).
using (StreamWriter writer = new StreamWriter("emails.txt", true))
{
writer.WriteLine(email);
}
Seems like a very easy question with a very easy answer: Open existing file, append a single line
If you post the current code, we can modify that to append instead of overwrite.