Is it possible to merge two (or more) Streams (or MemoryStreams) using CopyTo method?
For instance, I have two source streams s1 and s2. I'm creating the destination MemoryStream:
MemoryStream omDest = new MemoryStream();
If I copy one Stream everything is fine:
s1.CopyTo(omDest);
But if I copy both, the second one overwrites the first one.
I'd appreciate your help.
Thank you.
You can set the position of the target stream to the length of the first stream after CopyTo like this:
memoryStream1.CopyTo(target);
target.Position = memoryStream1.Length;
memoryStream2.CopyTo(target);
So the copying for the second stream starts at the specified position
Full Code:
using (MemoryStream target = new MemoryStream(30))
{
using(MemoryStream mem1 = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 }))
{
mem1.CopyTo(target);
target.Position = mem1.Length;
}
using (MemoryStream mem2 = new MemoryStream(new byte[] { 6, 7, 8, 9, 10 }))
{
mem2.CopyTo(target);
}
foreach(byte b in target.ToArray())
{
Console.Write(b+",");
}
}
Best Regards
Flo
EDIT:
To make it simpler you could also use the WriteTo-Method, so you wouldn't need the resetting of the position.
Related
Is it possible to concatenate a number of pdf/a (with possibly different conformance levels: some pdf/a-1b, some pdf/a-3b ecc) into a single pdfa ?
I was thinking that using the latest level (3-a or 3b) would be ok but I get errors when validating with VeraPDF:
Here is my code (where :
public static byte[] CreateConformantCopy(List<byte[]> sourcePdfs)
{
var version = PdfVersion.PDF_1_7;
var type = PdfAType.PDF_A_3B;
WriterProperties wp = new WriterProperties();
wp.UseSmartMode();
wp.SetPdfVersion(version.ToPdfVersion());
PdfOutputIntent oi = new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", Assembly.GetExecutingAssembly().GetManifestResourceStream("xxx.Resources.sRGB_CS_profile.icm"));
using (var mergedPdf = new MemoryStream())
{
var writer = new PdfWriter(mergedPdf, wp);
using (PdfADocument newDoc = new PdfADocument(writer, type.ToPdfAConformanceLevel(), oi, new DocumentProperties() { }))
{
Document document = new Document(newDoc, PageSize.A4.Rotate());
newDoc.SetTagged();
newDoc.GetCatalog().SetLang(new PdfString(Thread.CurrentThread.CurrentUICulture.Name));
newDoc.GetCatalog().SetViewerPreferences(
new PdfViewerPreferences()
.SetDisplayDocTitle(true)
.SetCenterWindow(true)
);
PdfMerger merger = new PdfMerger(newDoc);
for (int k = 0; k < sourcePdfs.Count; k++)
{
using (var inDoc = PdfHelper.GetDocument(sourcePdfs[k]))
{
var numberOfPages = inDoc.GetNumberOfPages();
merger.Merge(inDoc, 1, numberOfPages);
}
}
newDoc.Close();
}
return mergedPdf.ToArray();
}
}
PDF/A-1 and PDF/A-2 have several differences in the requirements. So, merging them together might not be possible. Looking on your validation errors, I think this is exactly the case. For example, the very first one is about XMP metadata. The PDF/A-2 is more strict here, and you get this error because your first file (which is probably a valid PDF/A-1) does not actually satisfy the PDF/A-2 rules.
What is possible however is to attach a PDF/A-1 document to PDF/A-2 one. This does not even require the use of PDF/A-3, which allows arbitrary attachments. The PDF/A-2 standard does allow attaching valid PDF/A-1 (as well as PDF/A-2 documents).
I'm using a PdfPTable (iText) to print a table that is populated with some list of values.
The problem is that, in the case where the PdfPTable takes more than one page to be displayed, its last line is printed at the end of the first page and ALSO at the beginning of the second one.
Please find an example below :
EDIT :
Please find the code below :
protected static PdfPTable addUserList(PdfWriter writer, Document document, List<MyObject> objects) throws Exception {
PdfPTable headerTable = new PdfPTable(4);
headerTable.setWidthPercentage(100);
headerTable.setWidths(new int[] { 4, 7, 5, 3 });
PdfPCell headerCell = PDFUtils.makeDefaultCell(1);
headerCell.setBorderColor(Color.WHITE);
headerCell.setBorder(PdfPCell.RIGHT);
headerCell.setBorderWidth(1f);
Phrase phrase = new Phrase("Column1", Style.OPIFICIO_12_BOLD_WHITE);
headerCell.setHorizontalAlignment(Element.ALIGN_CENTER);
headerCell.setPhrase(phrase);
headerTable.addCell(headerCell);
phrase = new Phrase("Column2", Style.OPIFICIO_12_BOLD_WHITE);
headerCell.setPhrase(phrase);
headerCell.setHorizontalAlignment(Element.ALIGN_CENTER);
headerTable.addCell(headerCell);
phrase = new Phrase("Column3", Style.OPIFICIO_12_BOLD_WHITE);
headerCell.setPhrase(phrase);
headerCell.setHorizontalAlignment(Element.ALIGN_CENTER);
headerTable.addCell(headerCell);
phrase = new Phrase("Column4", Style.OPIFICIO_12_BOLD_WHITE);
Chunk chunk = new Chunk("(1)", Style.OPIFICIO_6_BOLD_WHITE);
chunk.setTextRise(7f);
phrase.add(chunk);
chunk = new Chunk("(XX)", Style.OPIFICIO_8_BOLD_WHITE);
chunk.setTextRise(1f);
phrase.add(chunk);
headerCell.setPhrase(phrase);
headerCell.setHorizontalAlignment(Element.ALIGN_CENTER);
headerCell.setBorder(PdfPCell.NO_BORDER);
headerTable.addCell(headerCell);
PdfPTable userTable = new PdfPTable(4);
userTable.setWidthPercentage(100);
userTable.setWidths(new int[] { 4, 7, 5, 3 });
PdfPCell cell = PDFUtils.makeDefaultCell(1);
cell.setBackgroundColor(null);
cell.setPaddingTop(2f);
cell.setPaddingLeft(6f);
cell.setPaddingRight(6f);
for (MyObject object : objects) {
if (object != null) {
cell.setHorizontalAlignment(Element.ALIGN_LEFT);
if (object.getAttribute1() != null) {
phrase = new Phrase(object.getAttribute1(), Style.FUTURASTD_10_NORMAL_BLACK);
} else {
phrase = new Phrase("", Style.FUTURASTD_10_NORMAL_BLACK);
}
cell.setBorderWidth(1f);
cell.setBorderColor(Color.WHITE);
cell.setBorder(PdfPCell.RIGHT);
cell.setPhrase(phrase);
userTable.addCell(cell);
phrase = new Phrase(object.getAttribute2(), Style.FUTURASTD_10_NORMAL_BLACK);
cell.setBorderWidth(1f);
cell.setBorderColor(Color.WHITE);
cell.setBorder(PdfPCell.RIGHT);
cell.setPhrase(phrase);
userTable.addCell(cell);
phrase = new Phrase(object.getAttribute3(), Style.FUTURASTD_10_NORMAL_BLACK);
cell.setBorderWidth(1f);
cell.setBorderColor(Color.WHITE);
cell.setBorder(PdfPCell.RIGHT);
cell.setPhrase(phrase);
userTable.addCell(cell);
phrase = new Phrase(object.getAttribute4(), Style.FUTURASTD_10_NORMAL_BLACK);
cell.setBorder(PdfPCell.NO_BORDER);
cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
cell.setPhrase(phrase);
userTable.addCell(cell);
}
}
PdfPTable mainTable = new PdfPTable(1);
mainTable.setWidthPercentage(100);
mainTable.setSplitLate(false);
mainTable.setHeaderRows(1);
PdfPCell cellH = new PdfPCell();
cellH.addElement(headerTable);
cellH.setBorder(Rectangle.NO_BORDER);
cellH.setCellEvent(new PDFUtils.CellBackgroundRedRecap());
mainTable.addCell(cellH);
if (userTable.getRows().size() > 0) {
PdfPCell cellUser = PDFUtils.makeDefaultCell(1);
cellUser.setPaddingTop(7f);
cellUser.setCellEvent(new PDFUtils.CellBackgroundRecap());
cellUser.setBorder(PdfCell.NO_BORDER);
cellUser.addElement(userTable);
mainTable.addCell(cellUser);
}
return mainTable;
}
The problem actually was solved years ago (as #Bruno pointed out in a comment).
The solution, therefore, is to replace the older iText version used by a more current one in which the problem is fixed.
Indeed, the OP was having an old version in the pom.xml of another module of his project that was conflicting with the one he was modifying. He has deleted it and now it works.
Updating from versions 2.x (including the unofficial 4.2.0) to 5.x requires at least updating import statements as itext was moved from com.lowagie to com.itextpdf. Further changes might be necessary to adapt to actual API changes, e.g. the signing API was overhauled during the 5.3.x versions; the basic API structure, though, remained fairly stable during the 5.x versions.
Furthermore, updating from anything below 7 to 7.x requires greater changes as the whole iText API has been re-designed to get rid of sub-optimal aspects of the earlier API design.
I need to group output of my Enumerator in different ZipEntries, based on specific property (providerId), original chartPreparations stream is ordered by providerId, so I can just keep reference to provider, and add a new entry when provider chages
Enumerator.outputStream(os => {
val currentProvider = new AtomicReference[String]()
// Step 1. Creating zipped output file
val zipOs = new ZipOutputStream(os, Charset.forName("UTF8"))
// Step 2. Processing chart preparation Enumerator
val chartProcessingTask = (chartPreparations) run Iteratee.foreach(cp => {
// Step 2.1. Write new entry if needed
if(currentProvider.get() == null || cp.providerId != currentProvider.get()) {
if (currentProvider.get() != null) {
zipOs.write("</body></html>".getBytes(Charset.forName("UTF8")))
}
currentProvider.set(cp.providerId)
zipOs.putNextEntry(new ZipEntry(cp.providerName + ".html"))
zipOs.write(HTML_HEADER)
}
// Step 2.2 Write chart preparation in HTML format
zipOs.write(toHTML(cp).getBytes(Charset.forName("UTF8")))
})
// Step 3. On Complete close stream
chartProcessingTask.onComplete(_ => zipOs.close())
})
Since current provider reference, is changing, during the output, I made it AtomicReference, so that I could handle references from different threads.
Can currentProvider just be a var Option[String], and why?
Given two different revisions need to get the differences between them, I intend to use the method duvuelve Diff but I anything as a result, it could be? Thanks.
My code is as follows
using (SvnClient client = new SvnClient())
using (MemoryStream result = new MemoryStream())
{
client.Authentication.DefaultCredentials = new NetworkCredential("asdf", "asdf/*");
try
{
//SvnUriTarget is a wrapper class for SVN repository URIs
SvnUriTarget target = new SvnUriTarget(textBox1.Text);
if (client.Diff(target, rango, result))
MessageBox.Show("Successfully para" + rango.ToString() + ".");
StreamReader strReader = new StreamReader(result);
string str = strReader.ReadToEnd();
}
}
The stream that is returned from the Diff() function is positioned at the end of the stream, so before creating your stream reader, you need to reposition it at the beginning of the stream:
result.Position = 0;
StreamReader strReader = new StreamReader(result);
To load XML files with arbitrary encoding I have the following code:
Encoding encoding;
using (var reader = new XmlTextReader(filepath))
{
reader.MoveToContent();
encoding = reader.Encoding;
}
var settings = new XmlReaderSettings { NameTable = new NameTable() };
var xmlns = new XmlNamespaceManager(settings.NameTable);
var context = new XmlParserContext(null, xmlns, "", XmlSpace.Default,
encoding);
using (var reader = XmlReader.Create(filepath, settings, context))
{
return XElement.Load(reader);
}
This works, but it seems a bit inefficient to open the file twice. Is there a better way to detect the encoding such that I can do:
Open file
Detect encoding
Read XML into an XElement
Close file
Ok, I should have thought of this earlier. Both XmlTextReader (which gives us the Encoding) and XmlReader.Create (which allows us to specify encoding) accepts a Stream. So how about first opening a FileStream and then use this with both XmlTextReader and XmlReader, like this:
using (var txtreader = new FileStream(filepath, FileMode.Open))
{
using (var xmlreader = new XmlTextReader(txtreader))
{
// Read in the encoding info
xmlreader.MoveToContent();
var encoding = xmlreader.Encoding;
// Rewind to the beginning
txtreader.Seek(0, SeekOrigin.Begin);
var settings = new XmlReaderSettings { NameTable = new NameTable() };
var xmlns = new XmlNamespaceManager(settings.NameTable);
var context = new XmlParserContext(null, xmlns, "", XmlSpace.Default,
encoding);
using (var reader = XmlReader.Create(txtreader, settings, context))
{
return XElement.Load(reader);
}
}
}
This works like a charm. Reading XML files in an encoding independent way should have been more elegant but at least I'm getting away with only one file open.
Another option, quite simple, is to use Linq to XML. The Load method automatically reads the encoding from the xml file. You can then get the encoder value by using the XDeclaration.Encoding property.
An example from MSDN:
// Create the document
XDocument encodedDoc16 = new XDocument(
new XDeclaration("1.0", "utf-16", "yes"),
new XElement("Root", "Content")
);
encodedDoc16.Save("EncodedUtf16.xml");
Console.WriteLine("Encoding is:{0}", encodedDoc16.Declaration.Encoding);
Console.WriteLine();
// Read the document
XDocument newDoc16 = XDocument.Load("EncodedUtf16.xml");
Console.WriteLine("Encoded document:");
Console.WriteLine(File.ReadAllText("EncodedUtf16.xml"));
Console.WriteLine();
Console.WriteLine("Encoding of loaded document is:{0}", newDoc16.Declaration.Encoding);
While this may not server the original poster, as he would have to refactor a lot of code, it is useful for someone who has to write new code for their project, or if they think that refactoring is worth it.