I have been making a text editor in c#, and recently added the functionality to silently save the file (without SaveFileDialog). The file appears to save properly, however, when trying to open the file, i get the error System.ArgumentException - File format is not valid. It opens fine if the file has not been saved silently.
The code:
The save method:
public void save(RichTextBoxPrintCtrl.RichTextBoxPrintCtrl rtbIn, string fileNameIn)
{
string fileName = "";
if (getFileFromMap(fileNameIn) != "")
{
// The file already exists in the Map so save it
fileName = getFileFromMap(fileNameIn);
StreamWriter writer = new StreamWriter(fileName);
writer.Write(rtbIn.Text);
writer.Close();
}
else
{
// The file does not exist in the Map so
// Send it to SaveAs with the rtb and the initial fileName passed in
saveAs(rtbIn, fileNameIn);
}
}
SaveAs:
public string saveAs(RichTextBoxPrintCtrl.RichTextBoxPrintCtrl rtbIn, string fileName)
{
saveDialog.FileName = fileName;
saveDialog.Title = "Save As";
if (saveDialog.ShowDialog() == DialogResult.OK)
{
if (saveDialog.FileName.Length > 0)
{
if (saveDialog.FileName.EndsWith(".rtf"))
{
rtbIn.SaveFile(saveDialog.FileName, RichTextBoxStreamType.RichText);
}
else
{
rtbIn.SaveFile(saveDialog.FileName, RichTextBoxStreamType.PlainText);
}
addFileToMap(fileName, saveDialog.FileName);
return Path.GetFileName(saveDialog.FileName);
}
else { return ""; }
}
else { return ""; }
}
and Open:
public string open(RichTextBoxPrintCtrl.RichTextBoxPrintCtrl rtbIn)
{
if (openDialog.ShowDialog() == DialogResult.OK)
{
if (openDialog.FileName.Length > 0)
{
string fileName = Path.GetFileName(openDialog.FileName);
if (fileName.EndsWith(".rtf"))
{
rtbIn.LoadFile(openDialog.FileName, RichTextBoxStreamType.RichText);
}
else
{
rtbIn.LoadFile(openDialog.FileName, RichTextBoxStreamType.PlainText);
}
addFileToMap(openDialog.FileName, openDialog.FileName);
return fileName;
}
else { return ""; }
}
else { return ""; }
}
Other information:
The filenames are stored in a Dictionary because the editor has tabs.
RichTextBoxPrintCtrl is a custom RichTextBox that supports printing, it doesn't change anything relating to opening
The methods above are in a separate class which is why they require the richtextbox to be passed in.
If you need any other code, just let me know.
Any advice would be appreciated! Thanks in advance :)
EDIT:
Fixed, couldn't use StreamWriter.
Well, the issue seems to be that you are not saving the file in the same way.
When you perform a saveAs, you are calling rtb.SaveFile. In your silent save you are directly trying to save the rtb.Text to the file but that is probably not the correct format rtb.OpenFile is expecting.
I am no expert whatsoever in RichTextBox but spotting the difference when on method works and another similar one doesn't normally helps.
To expand a little more, Text returns only the plain text (no content formatting information). Your method save is saving as plain text any file, even if its a .rtf. Your Open method on the other hand will try to open an .rtf file as a formatted text, this can be causing the issues you are having.
Related
hey guys I am trying to send an attachment file but the attachment dialog is not opening
but instead it is rather telling me 'input string was not in a correct formart
private void proto_Type_AI_Blackhead_God(object sender, RoutedEventArgs e)
{
try
{
OpenFileDialog attachment = new OpenFileDialog();
attachment.InitialDirectory = Environment.SpecialFolder.MyDocuments.ToString();
attachment.Filter = "xml File (*.jpg;*.bmp;*.gif)|*.jpg;*.bmp;*.gif;|Pdf files|*.pdf;|Xml files|*.xml";
if (attachment.ShowDialog() == DialogResult.Value)
{
filename = attachment.FileName;
filename = attachment.SafeFileName;
}
else
{
MessageBox.Show("seriously bad");
}
attachment = null;
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I'm surprised that you got this code compiled.
First of all, OpenFileDialog.ShowDialog() returns bool?, so have it properly checked (for HasValue initally and then the value of Value).
Then, why do you overwrite filename variable? I assume filename is some global variable here.
Further, having that fixed I had no problems running the code, filter string is perfectly correct semantically. Logically, jpegs, bmps and gifs are not XML files.
Each time when the application can't serialize XML from specified URL it tries to send e-mail and write to XML file when the last Email was sent but after some count of invoking my XML file contains the wrong symbol-">"
P.S- Only this App using this file and we have only one instance of this app at the same time
// class constructor
public class XmlEmailService
{
private List<EmailSendingForXmlModel> emailList = new List<EmailSendingForXmlModel>();
XmlSerializer serializer = new XmlSerializer(typeof(List<EmailSendingForXmlModel>));
private bool IsDirty = false;
public XmlEmailService()
{
if (File.Exists(ConfigurationManager.AppSettings["XmlFilePath"]))
{
using (FileStream stream = File.OpenRead(ConfigurationManager.AppSettings["XmlFilePath"]))
{
emailList = (List<EmailSendingForXmlModel>)serializer.Deserialize(stream);
}
}
else
{
File.Create(ConfigurationManager.AppSettings["XmlFilePath"]).Dispose();
}
}
public void Save()
{
if (IsDirty)
{
using (FileStream stream = File.OpenWrite(ConfigurationManager.AppSettings["XmlFilePath"]))
{
serializer.Serialize(stream, this.emailList);
}
}
}
// Create/Update List of Emails from XML file
public void CreateOrUpdateList(string Email, bool IsSent)
{
if (this.emailList.Any(x => x.Email == Email))
{
var item = this.emailList.Where(x => x.Email == Email).FirstOrDefault();
if (item.SendDate <= DateTime.Now.AddMinutes((Int32.Parse(ConfigurationManager.AppSettings["Sending_interval"])) * -1))
{
if (IsSent)
item.SendDate = DateTime.Now;
this.IsDirty = true;
}
}
else
{
if (IsSent)
{
this.emailList.Add(new EmailSendingForXmlModel()
{
Email = Email,
SendDate = DateTime.Now
});
}
else
{
this.emailList.Add(new EmailSendingForXmlModel()
{
Email = Email,
SendDate = DateTime.MinValue
});
}
this.IsDirty = true;
}
}
}
<?xml version="1.0"?>
<ArrayOfEmailSendingForXmlModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<EmailSendingForXmlModel>
<Email>TestEmaili#gmail.com </Email>
<SendDate>2019-10-04T11:36:46.79885+03:00</SendDate>
</EmailSendingForXmlModel>
</ArrayOfEmailSendingForXmlModel>>
Last symbol ">" invoked the error. I don't know where this symbol comes from
My hypothesis is that you are not clearing the output file. So what happens is that if the length of the written text (including whitespace characters) is shorter than what is previously contained in file, the "tail" will remain in the file.
From documentation of File.OpenWrite
The OpenWrite method opens a file if one already exists for the file path, or creates a new file if one does not exist. For an existing file, it does not append the new text to the existing text. Instead, it overwrites the existing characters with the new characters. If you overwrite a longer string (such as "This is a test of the OpenWrite method") with a shorter string (such as "Second run"), the file will contain a mix of the strings ("Second runtest of the OpenWrite method").
To fix this, make sure you first clear the file before writing to it. The simplest way to do that is to just delete the file if it exists before creating new one to write into.
#Euphoric, you can also use System.IO.StreamWriter that will overwrite the entire file unless specified in the constructor.
I'm pretty new to C# and I'm experimenting a lot, I'm trying to make my program a little more user friendly and that is where the problem starts.
At first the location of the excelfile was in a public static string and I had no problems. I've changed it to this:
public string Excellocation()
{
string xlLocation;
if (but_Browse.Text == "Zoek Excel")
{
xlLocation = #"E:\Levi\Documents\Verjaardagen.xlsx";
}
else //Only if I get into this part of my code I get the error
{
xlLocation = but_Browse.Text;
}
return xlLocation;
}
And the button I use so the user can give me a location for the excel file is:
private void but_Browse_Click(object sender, EventArgs e)
{
var FD = new System.Windows.Forms.OpenFileDialog();
if (FD.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string fileToOpen = FD.FileName;
System.IO.FileInfo File = new System.IO.FileInfo(FD.FileName);
//OR
System.IO.StreamReader reader = new System.IO.StreamReader(fileToOpen);
//etc
but_Browse.Text = fileToOpen;
this.but_Browse.AutoSize = true;
But_Import.Visible = true;
}
}
Reading the Excel-file is no problem, my program finds it and processes it, if and only if the user changed the location by using the "Browse button" I get a message from Windows that there is already an excel file with that name and if I want to replace it, If I click away that message, my code gives an error on the line that tries to save the excel file
xlWorkbook.Save();
xlWorkbook.Close(true);
xlApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
xlWorkbook.Save() gives me this error:
System.Runtime.InteropServices.COMException occurred
HResult=0x800A03EC Message=Verjaardagen.xlsx can not be saved,
because it's read-only.
I have no idea why I don't get an error with the default location while I do get an error if use my button to give me that same location.
Does anyone know what i'm doing wrong?
Thanks in advance
So the problem is that the file is read only when you try to write to it after going through but_Browse_Click? Are you closing the StreamReader? Try using
reader.close();
in but_Browse_Click.
Perhaps a better way would be:
using (StreamReader reader = new StreamReader(fileToOpen))
{
//all code involving the reader in here
}
This automatically closes on completion.
Hi im very new to c# so apologies for this.
Im trying to create a text file to save customers details. But i want to name the text file by the surname. I.e myfile.txt.
Im sure im close, but missing something when it comes to changing the surname.text to a variable then making it the name of my created new file.
I have put 2 ** around the problem area.
private void button1_Click(object sender, EventArgs e)
{
try
{
if ((tb_firstname.Text == "") || (tb_surname.Text == "") || (tb_postcode.Text == ""))
{
MessageBox.Show("Missing values from textboxes!");
}
else if (
****string myfile.txt = (tb_surname.Text);
File.Exists("myfile.txt"));****
{
if (MessageBox.Show("Warning: file already exists. " +
"Contents will be replaced - " +
"do you want to continue?", "File Demo",
MessageBoxButtons.YesNo, MessageBoxIcon.Question,
MessageBoxDefaultButton.Button1,
MessageBoxOptions.DefaultDesktopOnly) ==
DialogResult.Yes)
{
//write lines of text to file
StreamWriter outputStream = File.CreateText(myfile.txt);
outputStream.WriteLine(tb_firstname.Text);
outputStream.WriteLine(tb_surname.Text);
outputStream.WriteLine(tb_surname.Text);
outputStream.Close();
MessageBox.Show("Text written to file successfully!");
this.Close();
}
else
{
MessageBox.Show("Action cancelled existing file contents not replaced!");
this.Close();
}
}
else
{
//write lines of text to file
StreamWriter outputStream = File.CreateText("myFile.txt");
outputStream.WriteLine(tb_firstname.Text);
outputStream.WriteLine(tb_surname.Text);
outputStream.WriteLine(tb_postcode.Text);
outputStream.Close();
MessageBox.Show("Text written to file successfully!");
this.Close();
}
}
catch (Exception problem)
{
MessageBox.Show("Program has caused an error - " + problem.ToString());
}
}
any help would be great!
You are creating a file called myfile.txt every time
StreamWriter outputStream = File.CreateText("myFile.txt");
That's a string literal you are using.
You have the line:
string myfile.txt = (tb_surname.Text)
which reads the contents of the text box into a variable called myfile.txt. You then need to use that in the file creation code:
StreamWriter outputStream = File.CreateText(myFile.txt);
Note that there are no quotes.
This will overwrite the file if it already exists - if you want to append you will need to use the following method:
StreamWriter outputStream = File.AppendText(myFile.txt);
I believe you are trying to save the surname as part of the file name. You can generate the filename and check if it exists with the code below:
First generate the filename:
string fileName = string.Format("{0}File.txt", tb_surname.Text);
And then check it using the variable:
File.Exists(fileName);
I want to clear the file path from the file upload. The file upload is inside the update panel and I am using a AsyncFileUpload. How can I clear the file and change the background color of the fileupload
btnAudUpload_Click Method
string filename =FileUpload.FileName;
string Fullpath = Path.Combine(#"D:\Media", filename);
if (FileUpload.HasFile)
{
if (filename.ToLower().EndsWith("mp4"))
{
//Saving the file
}
else
{
//I want to clear the FileUpload content here
}
}
Clear the Attributes worked for me... but that will remove styles and other stuff
string filename =FileUpload.FileName;
string Fullpath = Path.Combine(#"D:\Media", filename);
if (FileUpload.HasFile)
{
if (filename.ToLower().EndsWith("mp4"))
{
//Saving the file
}
else
{
//I want to clear the FileUpload content here
FileUpload.Attributes.Clear();
}
}
I know this thread is almost a year old, but this still seems to be a prevalent issue. The easiest fix I've found is to set the file upload control to a new instance of it.
FileUpload1 = new FileUpload();
If you want to have interactivity without relouding the page you'll have to use JavaScript. That's why I would check the file extension on the client side instead of the server side. Example:
function checkFile() {
var input = document.getElementById('fileUpload').value.toLowerCase();
var extension = '.mp4';
if (!input.indexOf(extension, input.length - extension.length) != -1) {
alert('Invalid file extension. Only .mp4 is allowed.');
document.getElementById('fileUpload').value = '';
}
}
The only thing you'll have to add is changing the fileUpload background color which is very easy to do.
Good luck!
I think when you do postback the file contnet property will removed by default, because a security reasons !