Entwickler-Ecke

Sonstiges (.NET) - Verschachtelte using-Anweisung oder selber disposen?


lapadula - Di 18.04.17 21:08
Titel: Verschachtelte using-Anweisung oder selber disposen?
Guten Abend,

ich versuche mich gerade an iTextSharp. Ich möchte eine PDF-Datei erstellen, diese mit einwenig Text füllen und dann den Text markieren.

Es klappt alles soweit nur beim markieren, da versuche ich die PDF-Datei zu öffnen, jedoch taucht eine Exception auf, die besagt, dass auf diese Datei bereits zugegriffen wird.

Den FileStream habe ich versucht selber zu schließen und nun mit der using-Anweisung. Ich benutze diese zum ersten Mal und wollte fragen ob folgender Code üblich ist:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
private void button2_Click(object sender, EventArgs e)
        {
            using (FileStream fs = new FileStream(@"C:\Users\pc\Desktop\forerunner.pdf", FileMode.Create, FileAccess.Write, FileShare.None))
            {
                using (Document doc = new Document())
                {
                    using (PdfWriter writer = PdfWriter.GetInstance(doc, fs))
                    {
                        doc.Open();
                        doc.Add(new Paragraph("Hello World"));
                    }
                }
                
            }
        }


Und meine zweite Frage wäre, warum die Datei trotzdem nicht geöffnet werden kann?

Hier der Komplette Code:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
using System;
using System.Windows.Forms;
using iTextSharp.text;
using iTextSharp.text.pdf;
using System.IO;
using iTextSharp.text.pdf.parser;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;

namespace TextSharp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                GetPageNumber();
            }
            catch (Exception Ex)
            {
                MessageBox.Show(Ex.ToString());
            }
           
        }

        public void GetPageNumber()
        {
            string searchWord = textBox1.Text;

            //Process p = new Process();
            //p.StartInfo.FileName = @"C:\Users\pc\Desktop\forerunner.pdf";
            //p.Start();


            string strFileNameTextBox = System.IO.Path.GetFileName(@"C:\Users\pc\Desktop\forerunner.pdf");

            List<int> PageNumbers = Helper.ReadPdfFile(@"C:\Users\pc\Desktop\forerunner.pdf", searchWord);

            comboBox1.Items.Clear();
            foreach (int i in PageNumbers)
            {
                comboBox1.Items.Add(i);
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            using (FileStream fs = new FileStream(@"C:\Users\pc\Desktop\forerunner.pdf", FileMode.Create, FileAccess.Write, FileShare.None))
            {
                using (Document doc = new Document())
                {
                    using (PdfWriter writer = PdfWriter.GetInstance(doc, fs))
                    {
                        doc.Open();
                        doc.Add(new Paragraph("Hello World"));
                    }
                }
                
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            PdfReader pdfReader = new PdfReader(@"C:\Users\pc\Desktop\forerunner.pdf");
            PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(@"C:\Users\pc\Desktop\forerunner.pdf", FileMode.Create, FileAccess.Write, FileShare.None));

            PdfContentByte canvas = pdfStamper.GetUnderContent(1);
            canvas.SetColorFill(BaseColor.YELLOW);
            canvas.Rectangle(367866616);
            canvas.Fill();
            canvas.RestoreState();
            pdfStamper.Close();
            pdfReader.Close();
        }
    }
}


Edit: Ok die using-Anweisung zu verschachteln war keine Gute Idee. Nun habe ich den FileStream mittelns .Close() wieder geschlossen, reicht das nicht?


Moderiert von user profile iconChristian S.: Topic aus Basistechnologien verschoben am Di 18.04.2017 um 21:26


Ralf Jansen - Di 18.04.17 21:32

Ohne ITextSharp jetzt genau zu kennen sieht das Handling mit dem using richtig aus. So sollte es funktioniren (wenn innerhalb von ITextSharp es halbwegs normal programmiert ist).

Was passiert in Helper.ReadPdfFile? Sieht auch nach einer Fileoperation auf dem File aus.


Delete - Di 18.04.17 22:03

- Nachträglich durch die Entwickler-Ecke gelöscht -


lapadula - Di 18.04.17 22:22

In der Klasse Helper befindet sich nur die statische Methode ReadPdfFiles:

Wirft dann eine List<int> mit den SeitenNr. zurück, wo das zu suchende Wort gefunden wurde.


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
public static List<int> ReadPdfFile(string fileName, String searthText)
        {
            List<int> pages = new List<int>();
            if (File.Exists(fileName))
            {
                PdfReader pdfReader = new PdfReader(fileName);
                for (int page = 1; page <= pdfReader.NumberOfPages; page++)
                {
                    ITextExtractionStrategy strategy = new SimpleTextExtractionStrategy();

                    string currentPageText = PdfTextExtractor.GetTextFromPage(pdfReader, page, strategy);
                    if (currentPageText.Contains(searthText))
                    {
                        pages.Add(page);
                    }
                }
                pdfReader.Close();
            }
            return pages;
        }


Wenn ich meine using-Verschachtelung so lasse, tritt eine ObjectDisposedException auf.("Auf eine geschlossene Datei kann nicht zugegriffen werden").

Ohne using: Ich klicke zuerst auf button2, da wird die PDF erstellt und mit Inhalt gefüllt und auf button3 soll dann der Text markiert werden, in der 77. Zeile tritt dann die besagte Exception auf.

An iTextSharp sollte es eig. nicht liegen.


Ralf Jansen - Di 18.04.17 22:41

Ich vermute der PDFWriter schließt den Stream schon selber und ein folgendes schließen des Streams knallt dann(soviel zu sauber programmiert ;) ). Ruf mal writer.CloseStream = false; vor doc.Open(); auf.
Nach Codeanalyse auf github (heißt ich habe es nicht ausprobiert) sollte das helfen.


Delete - Mi 19.04.17 03:16

- Nachträglich durch die Entwickler-Ecke gelöscht -


lapadula - Mi 19.04.17 18:10

Ahso daran lag das also, danke!

Man kann also die PDFs nicht wirklich "bearbeiten", sondern man müsste die alte PDF im Anschluss löschen, verstehe ich das richtig?


Delete - Mi 19.04.17 22:53

- Nachträglich durch die Entwickler-Ecke gelöscht -


lapadula - Do 20.04.17 20:10

Ok das ist soweit klar aber ich kann nicht die Datei lesen und gleichzeitig etwas reinschreiben. Bei Office scheint es genauso zu sein, dort wird ja auch eine temp Datei erstellt.

Es gäbe noch die Möglichkeit die Datei in ein byte Array zu lesen aber da besteht das Risiko bei einer Exception die temp-Datei und die Originale Datei zu verlieren.


Delete - Do 20.04.17 21:39

- Nachträglich durch die Entwickler-Ecke gelöscht -


lapadula - Do 20.04.17 23:37

Okay das funktioniert tatsächlich :D

Hab mich darüber auf stackoverflow informiert und dort hieß es, es sei ohne eine temp-Datei oder byte array nicht möglich.

Vielen Dank für die Infos


Delete - Fr 21.04.17 00:56

- Nachträglich durch die Entwickler-Ecke gelöscht -