I am trying to separate the MIME gui from the code i need. I am almost there just one more gui element i dont know how to replace. This element is the openfiledialog. Here a code snippet.
Program.cs
var sfd = new OpenFileDialog();
sfd.FileName = "C:\\eml\\" + validOutputFilename;
try
{
var writer = new MimeMessageWriter();
using (var fs = sfd.OpenFile()) writer.Write(message, fs);
}
catch (Exception ex)
{
//ignore
// need to log
}
message is an IMessage. A class created to store the information about an eml file. The open file dialog is allowing you to put in the file name with an eml extension and that is all. write.Write expects an IMessage and a stream. Inside writer.Write the file is being written The only part of the file that uses this code is when the file itself is writen at the end and write out any attachments. Here are those code snippets.
*MimeMessageWriter
-the attachment uses it here
var embeddedMessage = attachment.OpenAsMessage();
var messageWriter = new MimeMessageWriter();
var msgStream = new MemoryStream();
messageWriter.Write(embeddedMessage, msgStream);
var messageAttachment = ew DotNetOpenMail.FileAttachment(msgStream.ToArray());
messageAttachment.ContentType = "message/rfc822";
messageAttachment.FileName = filename + ".eml";
outMessage.AddMixedAttachment(messageAttachment);
-write out the file part of the file
using (var sw = new StreamWriter(stream))
sw.Write(outMessage.ToDataString());
I want to replace openFileDialog with something that will allow me to pass the filename to write out file in the MimeMessageWriter
Replace
using (var fs = sfd.OpenFile()) writer.Write(message, fs);
with
string fileName = #"c:\eml\myAttachment.eml";
using ( FileStream fs = new FileStream( fileName, FileMode.CreateNew ) )
{
writer.Write( message, fs )
}
See also: http://msdn.microsoft.com/de-de/library/47ek66wy.aspx
Related
In my C# application, I am trying to make it able to pull a pdf and save it, so that end users can press a button and pull up that pdf while they are in the application. But when I copy the content to the filestream it makes the pdf but it is just blank with nothing from the original pdf. What am I doing wrong?
The pdf's could also have pictures on them, and I don't think the way I'm doing it would allow those to be brought over.
Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog();
bool? response = openFileDialog.ShowDialog();
var fileContent = string.Empty;
var filestream = openFileDialog.OpenFile();
using (StreamReader reader = new StreamReader(filestream))
{
fileContent = reader.ReadToEnd();
}
// make folder path
string FolderPath = "ProjectPDFs\\";
string RootPath = "X:\\Vents-US Inventory";
DirectoryInfo FolderDir = new DirectoryInfo(Path.Combine(RootPath, FolderPath));
Directory.CreateDirectory(FolderDir.ToString());
string filePath = "";
string FileName = openFileDialog.SafeFileName;
if (fileContent.Length > 0)
{
filePath = Path.Combine(FolderDir.ToString(), FileName);
using (Stream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
byte[] bytestream = Encoding.UTF8.GetBytes(fileContent);
Stream stream = new MemoryStream(bytestream);
stream.CopyTo(fileStream);
}
}
I am trying to replace text in a docx document based on this sample, with some modifications: https://learn.microsoft.com/en-us/office/open-xml/how-to-search-and-replace-text-in-a-document-part#sample-code
However, the saved document is not valid anymore. Word is able to correct the file, but there is a Number of entries expected in End Of Central Directory does not correspond to number of entries in Central Directory. exception is thrown at System.IO.Compression.ZipArchive.ReadCentralDirectory() when trying to open the created file again with WordprocessingDocument.
My code looks like this:
using (var fs = new FileStream(fn, FileMode.Open, FileAccess.Read, FileShare.Read))
using (var ms = new MemoryStream())
{
await fs.CopyToAsync(ms);
using (var wordDoc = WordprocessingDocument.Open(ms, true))
{
string docText;
using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
{
docText = sr.ReadToEnd();
}
/*Regex regexText = new Regex("text to replace");
docText = regexText.Replace(docText, "new text");*/
using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
{
sw.Write(docText);
}
}
await File.WriteAllBytesAsync(target, ms.GetBuffer());
}
using (var wordDoc = WordprocessingDocument.Open(target, true))
{
}
The issue is not repated to the replace itself. Even reading the MainDocumentPart in any way causes this exception to be thrown.
Why the streams? I want to create and modify a document from template and save it afterwards to a stream. But I haven't found any CreateFromTemplate overload neither a Save/SaveAs overload that accepts a stream.
I upload a csv file to AppData folder in project solution and read the content with the code below:
using (var fs = new FileStream(Path.Combine(uploadPath, name), chunk == 0 ? FileMode.Create : FileMode.Append))
{
var buffer = new byte[fileUpload.InputStream.Length];
fileUpload.InputStream.Read(buffer, 0, buffer.Length);
fs.Write(buffer, 0, buffer.Length);
var reader = new StreamReader(System.IO.File.OpenRead(fs.Name));// I check path and file itself in AppData folder. its ok
List<string> listA = new List<string>();
List<string> listB = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(';');
}
But it throws IOException with message:
The process cannot access the file 'c:\path\App_Data\o_1amtdiagc18991ndq1c1k1c2v1bama.csv'
because it is being used by another process.
I couldnt get it how and why it's being used I created this file from original uploaded file with unique name..
I couldnt get it how and why its being used
Because you've not closed the stream that's writing to it:
using (var fs = new FileStream(Path.Combine(uploadPath, name), ...)
I would suggest you write the file, close the using statement so the handle can be released, then read it:
string fullName = Path.Combine(uploadPath, name);
using (var fs = ...)
{
// Code as before, but ideally taking note of the return value
// of Stream.Read, that you're currently ignoring. Consider
// using Stream.CopyTo
}
// Now the file will be closed
using (var reader = File.OpenText(fullName))
{
// Read here
}
My class which holds the constructor method of writing to a file
class Writer
{
public Writer(string filename, List<string> data)
{
FileStream ostrm;
StreamWriter writer;
TextWriter oldOut = Console.Out;
try
{
ostrm = new FileStream("C:/Users/kyle/Desktop/ConferenceSoftware/" + filename + ".txt", FileMode.OpenOrCreate, FileAccess.Write);
writer = new StreamWriter( ostrm );
}
catch (Exception e)
{
Console.WriteLine("Cannot open " + filename + ".txt for writing");
Console.WriteLine(e.Message);
return;
}
Console.SetOut(writer);
foreach (var _data in data)
{
Console.WriteLine( _data );
}
Console.SetOut(oldOut);
writer.Close();
ostrm.Close();
}
}
Inside my main method:
List<string> dataToAdd = new List<string>();
dataToAdd.Add("Example");
new Writer(Settings.ConferenceRoomName, dataToAdd);
However, if I already have text inside the file, instead appending to the file from the last line, it does it from the first line, ie:
Example // new added through method
Line that already exists // already in file
Line that already exists // already in file
// this is where I wanted it but it goes to the top
Any help would be appreciated, I don't see where I could target what line to start writing at.
Thanks in advance.
You need to use FileMode.Append instead of OpenOrCreate:
ostrm = new FileStream("C:/Users/kyle/Desktop/ConferenceSoftware/" +
filename + ".txt", FileMode.Append, FileAccess.Write);
See documentation (about FileMode.Append):
Opens the file if it exists and seeks to the end of the file, or creates a new file. This requires FileIOPermissionAccess.Append permission. FileMode.Append can be used only in conjunction with FileAccess.Write...
So it will also create the file if it does not exist.
If you don't want to create a non-existing file, you can check if it exists using File.Exists() before opening the stream.
When you create a new FileStream with FileMode.OpenOrCreate, it writes over the existing file. If you would like to append to the file, use FileMode.Append instead:
FileMode.Append: Opens the file if it exists and seeks to the end of the file, or creates a new file. This requires FileIOPermissionAccess.Append permission.
ostrm = new FileStream("C:/Users/kyle/Desktop/ConferenceSoftware/" + filename + ".txt", FileMode.Append, FileAccess.Write);
You want file mode Append instead of OpenOrCreate:
ostrm = new FileStream("C:/Users/kyle/Desktop/ConferenceSoftware/" + filename + ".txt", FileMode.Append, FileAccess.Write);
Both will create a new file if it doesn't exist, the difference is that OpenOrCreate starts writing at the beginning of the file and Append starts writing at the end of the file.
Reference: FileMode Enumeration
Have a slight issue that I need a second pair of eyes because I am at the point where the code is just being hacked apart instead of taking time needed to break it down.
The end goal of the program is to read in X number of files depending on users choices, take those files put them into memory all together, and then append them all to one Word file.
It is only writing out the first file. If I change to a WriteFile method it only writes out the last file. I would like it to write out all files
Any tips in the right direction would be appreciated.
private void cmdSubmit_Click(object sender, EventArgs e)
{
SaveFileDialog saveFile = new SaveFileDialog();
saveFile.Filter = "Word Files (*.doc)|*.doc";
saveFile.FilterIndex = 1;
saveFile.RestoreDirectory = true;
string dirPath = "";
FileStream destStream = (dynamic)null;
MemoryStream outStream = new MemoryStream();
if (saveFile.ShowDialog() == DialogResult.OK)
{
dirPath = saveFile.FileName;
destStream = new FileStream(dirPath, FileMode.Create, FileAccess.Write);
destStream.Close();
}
DirectoryInfo di = new DirectoryInfo(#"FilePath");
FileInfo[] args = di.GetFiles("*.doc");
foreach (object itemChecked in chkLB.CheckedItems)
{
//loop through checked items and add to file
string fileStream = di.ToString() + itemChecked.ToString() + ".doc";//READ IN FILES
FileStream inFile = File.OpenRead(fileStream); //Read the files one by one
outStream.SetLength(inFile.Length);
inFile.Read(outStream.GetBuffer(), 0, (int)inFile.Length);
outStream.Flush();
inFile.Close();
fileSave(outStream, dirPath);
//MessageBox.Show("Item with title: \"" + itemChecked.ToString()); Nice trick to add "" around a value
}
//Open File
//Microsoft.Office.Interop.Word.Application word = new Microsoft.Office.Interop.Word.Application();
//Document openDoc = word.Documents.Open(dirPath);
MessageBox.Show("DONE");
}
public static void fileSave(MemoryStream memStream, string saveFile)
{
//FileStream fileOut = File.Open(saveFile, FileMode.Append);
if (!File.Exists(saveFile))
{
FileStream fileOut = new FileStream(saveFile, FileMode.OpenOrCreate, FileAccess.Write);
//stream writter?
memStream.WriteTo(fileOut);
fileOut.Flush();
fileOut.Close();
}
else
{
FileStream fileOut = new FileStream(saveFile, FileMode.Append, FileAccess.Write);
memStream.WriteTo(fileOut);
fileOut.Flush();
fileOut.Close();
}
}
Use open XMl to merge two word files into one.
AltChunk is the answer for your question.
http://msdn.microsoft.com/en-us/library/documentformat.openxml.wordprocessing.altchunk.aspx
There is two answer for this question.
Answer 1.
If all you're doing is reading files and marge them together to a new file, you might not need to write code. You can use command:
C:\> copy x.doc+y.doc+z.doc output.doc
Now call this via Process.Start when you want.
Answer 2:
string[] files = { #"E:\x.txt", #"E:\y.txt", #"E:\z.txt" };
FileStream outputFile = new FileStream(#"E:\output.txt", FileMode.Create);
using (BinaryWriter ws = new BinaryWriter(outputFile))
{
foreach (string file in files)
{
ws.Write(System.IO.File.ReadAllBytes(file));
}
}
Well...the simple way wouldn't be much more difficult than this:
public static void Concatenate( IEnumerable<FileInfo> files , FileInfo destination , bool overWriteDestination = true )
{
FileMode mode = overWriteDestination ? FileMode.Create : FileMode.Append ;
using ( FileStream tgt = destination.Open( mode , FileAccess.Write , FileShare.Read ) )
{
foreach( FileInfo file in files )
{
using ( FileStream src = file.Open( FileMode.Open , FileAccess.Read , FileShare.Read ) )
{
const int bufferSize = 64*1024; // 64k buffer OK?
src.CopyTo( tgt , bufferSize ) ;
}
}
tgt.Flush() ;
}
return;
}
...
DirectoryInfo dir = new DirectoryInfo( #"C:\foo") ;
FileInfo target = new FileInfo( #"C:\foo.glob") ;
Concatenate( dir.EnumerateFiles( "*.*" ) , target , true ) ;
Which will do what you ask (concatenate the files). But at the end of the day, all you've got is all the various octets concatenated together. If you're expecting a single MS Word document to result that is the functional concatenation of the pages in each file, it's not going to happen.
Easily.
That's a rather more complicated process. These might be of use:
Append multiple DOCX files together
http://blogs.msdn.com/b/brian_jones/archive/2008/12/08/the-easy-way-to-assemble-multiple-word-documents.aspx
All of these techniques make the assumption that you're working with *.docx files (which are XML) rather than the binary *.doc files. If you've got to deal with *.doc files, Good luck. You're probably better off converting them to RTF and parsing that, or converting them to *.docx.