[JAVA] Doc.close werkt niet naar behoren

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • WillemJanJansen
  • Registratie: Augustus 2005
  • Laatst online: 19:35
Tweakende vrienden;

Ik ben in Java aan het rommelen met een stukje code dat de invoer van textField naar placeholders in een Word template schrijft. Hiervoor opent het een .docx template en vervangt tekst placeholders voor wat ik invoer in het textField met fx:id"naamPlaceholder". Dit werkt allemaal prima maar mijn stukje code houdt het nieuw gegenereerde document "in gebruik" waardoor je alleen een "alleen-lezen" document of een nieuwe kopie kan openen.

Ik heb hiervoor het volgende stuk code van het internet gevist:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
try{
XWPFDocument doc = new XWPFDocument(OPCPackage.open("C:'\\users\\template.docx"));

for (XWPFParagraph p : doc.getParagraphs()) {
                List<XWPFRun> runs = p.getRuns();
                if (runs != null) {
                    for (XWPFRun r : runs) {
                        String text = r.getText(0);
                        if (text != null && text.contains("naamPlaceHolder")) {
                            text = text.replace("naamPlaceHolder", naamPlaceHolder.getText());
                            r.setText(text, 0);
                        }
                    }
                }doc.write(new FileOutputStream("C:'\\user\\bestand.docx"));
            }
}
catch(Exception e){
e.getStackTrace();
e.printStackTrace();
System.out.println("Bericht voor als het misgaat.")


Als ik na regel 14 "doc.Write(new FileOutPutStream(-pad-))" de method "doc.Close()" toevoeg dan maakt de code wijzigingen in mijn template terwijl hij het moet opslaan in het nieuw te genereren document.

Zonder doc.close() werkt de code prima en worden al mijn placeholders vervangen maar blijft het document in gebruik bij Java.

Ik heb al het nodige geprobeerd maar ik krijg het niet voor elkaar. Heeft iemand een oplossing?
Ik heb zelf hieraan gedacht:
- Staat mijn FileOutputStream in de juiste scope?
- Moet ik de For loop op een bepaalde manier verbreken voor ik de FileOutputStream activeer?

Een hoop knappe koppen hier - hopelijk prikt iemand hier makkelijk doorheen.

Bedankt voor de moeite

Alle reacties


Acties:
  • +2 Henk 'm!

  • Sandor_Clegane
  • Registratie: Januari 2012
  • Niet online

Sandor_Clegane

Fancy plans and pants to match

@WillemJanJansen Je leest het originele bestand in en je maakt wijzigen in de representatie van het originele bestand. Als je een doc.close doet, gok ik dat dat een methode van XWPFDocument is om het bestand met wijzigingen "goed" op te slaan. Helaas is dit het originele bestand.

Wat je wilt is een kopietje van het bestand opslaan en het originele ongemoeid laten. Ik ken Java verder niet en XWPFDocument ook niet, maar een ideetje zou kunnen zijn eerst een kopie van de template te maken op de juiste plek met de juiste naam, deze te openen, wijzigingen te doen en dan opslaan.

Misschien dat iemand anders een elegantere manier heeft.

PS: Ik gok dat Doc.Close naar behoren werkt. :) Misschien dat je een dispose kunt aanroepen op het XWPF object om het te forceren, maar dat lijkt me niet wenselijk.

[ Voor 11% gewijzigd door Sandor_Clegane op 02-08-2022 19:59 ]

Less alienation, more cooperation.


Acties:
  • +1 Henk 'm!

  • Webgnome
  • Registratie: Maart 2001
  • Laatst online: 15:43
van de docs:
Poixmldocument::write
Write out this document to an Outputstream. Note - if the Document was opened from a File rather than an InputStream, you must write out to a different file, overwriting via an OutputStream isn't possible. If stream is a FileOutputStream on a networked drive or has a high cost/latency associated with each written byte, consider wrapping the OutputStream in a BufferedOutputStream to improve write performance.
POIXMLDocument::close
public void close()
throws java.io.IOException
Closes the underlying OPCPackage from which this document was read, if there is one
Once this has been called, no further operations, updates or reads should be performed on the document.

Specified by:
close in interface java.io.Closeable
Specified by:
close in interface java.lang.AutoCloseable
Throws:
java.io.IOException - for writable packages, if an IO exception occur during the saving process.
Dus ik denk dat je hier het originele bestand moet sluiten voordat je het naar een nieuw document weg schrijft. Of zoals de voorganger al aangaf kun je beter via de Files (nio) van Java een kopie van de file maken en aanpassingen doen op die versie.

Strava | AP | IP | AW


Acties:
  • 0 Henk 'm!

  • WillemJanJansen
  • Registratie: Augustus 2005
  • Laatst online: 19:35
Bedankt voor jullie antwoorden. Het klinkt allebei logisch. Ik ga proberen om een combinatie van jullie antwoorden door te voeren en de data in een kopie weg te schrijven. Goeie inspiratie!

Acties:
  • +2 Henk 'm!

  • SPee
  • Registratie: Oktober 2001
  • Laatst online: 13-05 12:56
In regel 14 maak je een outputstream aan naar je nieuwe bestand.
Tenzij dat in de doc staat, zul je die stream ook zelf moeten sluiten. Anders blijft die open totdat je programma sluit.
Dus je hebt niet 1, maar 2 streams open. 1 voor het lezen (regel 2) en 1 voor het wegschrijven (regel 14). Beide moet je sluiten.
Zoek op "try-with-resources" hoe je dat het makkelijkste kunt doen.

let the past be the past.


Acties:
  • 0 Henk 'm!

  • WillemJanJansen
  • Registratie: Augustus 2005
  • Laatst online: 19:35
Bedankt voor de tip Spee. Ik ga jullie tips toepassen op mijn volgende werkdag en zal dan laten weten of het gewerkt heeft.

Acties:
  • +1 Henk 'm!

  • CodeCaster
  • Registratie: Juni 2003
  • Niet online

CodeCaster

Can I get uhm...

Je wijzigingen in het originele bestand worden via XWPFDocument, getParagraphs(), getRuns(), getText(), setText() bijgehouden in het document-object.

Zodra je daarop close() aanroept, worden die wijzigingen weggeschreven.

Dus inderdaad, of eerst het bestand kopiëren en daarop je wijzigingen doen, of uitzoeken hoe je het XWPFDocument na het handmatig opslaan naar een nieuw bestand kunt resetten.

[ Voor 3% gewijzigd door CodeCaster op 03-08-2022 07:56 ]

https://oneerlijkewoz.nl
Het ergste moet nog komen / Het leven is een straf / Een uitgestrekte kwelling van de wieg tot aan het graf


Acties:
  • 0 Henk 'm!

  • WillemJanJansen
  • Registratie: Augustus 2005
  • Laatst online: 19:35
Ik zou nog even terugkoppelen hoe het is afgelopen. Ik kopieer nu met nio het templatebestand en sla het daarna alsnog op in een ander .docx bestand. De kopieeractie hoeft niet helemaal maar heeft er wel voor gezorgd dat mijn template intact blijft bij falende code. Ik krijg het niet voor elkaar om het document te sluiten na het generen van het document. Dit heeft er denk ik mee te maken dat het genereren enkele seconden duurt om op te slaan en daardoor de doc.close() nog niet werkt. Intellij geeft aan dat ik het document sluit voordat de doc.write() gebeurt namelijk.

Ik heb het nu opgelost door het document niet te sluiten maar een System.exit() uit te voeren. Het is niet de mooiste oplossing maar het werkt. Ik ga ervoor zorgen dat het docx schrijf gedeelte een eigen thread krijgt waardoor ik alleen die thread kan sluiten en mijn UI actief blijft maar ben nu allang blij dat het redelijk werkt.

Erg bedankt voor jullie antwoorden. Ik kan geen antwoord selecteren als "het beste antwoord" want jullie hebben allemaal wat nuttigs toegevoegd. Dit wordt erg gewaardeerd!

Acties:
  • +2 Henk 'm!

  • Sandor_Clegane
  • Registratie: Januari 2012
  • Niet online

Sandor_Clegane

Fancy plans and pants to match

WillemJanJansen schreef op donderdag 4 augustus 2022 @ 16:02:
Ik zou nog even terugkoppelen hoe het is afgelopen. Ik kopieer nu met nio het templatebestand en sla het daarna alsnog op in een ander .docx bestand. De kopieeractie hoeft niet helemaal maar heeft er wel voor gezorgd dat mijn template intact blijft bij falende code. Ik krijg het niet voor elkaar om het document te sluiten na het generen van het document. Dit heeft er denk ik mee te maken dat het genereren enkele seconden duurt om op te slaan en daardoor de doc.close() nog niet werkt. Intellij geeft aan dat ik het document sluit voordat de doc.write() gebeurt namelijk.

Ik heb het nu opgelost door het document niet te sluiten maar een System.exit() uit te voeren. Het is niet de mooiste oplossing maar het werkt. Ik ga ervoor zorgen dat het docx schrijf gedeelte een eigen thread krijgt waardoor ik alleen die thread kan sluiten en mijn UI actief blijft maar ben nu allang blij dat het redelijk werkt.

Erg bedankt voor jullie antwoorden. Ik kan geen antwoord selecteren als "het beste antwoord" want jullie hebben allemaal wat nuttigs toegevoegd. Dit wordt erg gewaardeerd!
Kun je de write niet flushen oid? Dan forceer je schrijf actie lijkt me.

Zelfde probleem lijkt: https://stackoverflow.com...-word-doc-from-apache-poi

Of in ieder geval dezelfde observatie. :)

Less alienation, more cooperation.


Acties:
  • +1 Henk 'm!

  • WillemJanJansen
  • Registratie: Augustus 2005
  • Laatst online: 19:35
Dat lijkt inderdaad erg op mijn probleem. Ik ga het maandag eens proberen. Ik zal flush eens proberen. Hopelijk lost dat het wat eleganter op. Wederom Thanks voor het meedenken.

Acties:
  • +1 Henk 'm!

  • Rowwan
  • Registratie: November 2000
  • Laatst online: 21:29
Kun je je volledige (relevante) code nog eens posten? Wat is nu 'doc' in de nieuwe situatie?

Volgens mij maak je het jezelf onnodig moeilijk met je threads en systeem exit. Een flush zou niet nodig moeten zijn. Verder zou ik de link van @Sandor_Clegane eens doorlezen.

[ Voor 36% gewijzigd door Rowwan op 08-08-2022 09:02 ]


Acties:
  • +1 Henk 'm!

  • WillemJanJansen
  • Registratie: Augustus 2005
  • Laatst online: 19:35
Het werkt nu volledig. Het kwam er inderdaad op neer dat ik meerdere streams moest sluiten. Een system.exit is dus niet meer nodig.

Ik heb:
code:
1
doc.write(new FileOutputStream("C:'\\user\\bestand.docx"));


Veranderd naar:
code:
1
2
3
4
FileOutputStream fos = new FileOutputStream(document.docx");
            doc.write(fos);
            fos.close();
            doc.close();


Daarmee is mijn probleem dus ook geheel opgelost. Achteraf is de oplossing erg simpel. Allemaal erg bedankt voor de hulp!

Acties:
  • +1 Henk 'm!

  • mr_derk
  • Registratie: September 2005
  • Laatst online: 23:04
Handig om jezelf aan te leren: https://www.baeldung.com/java-try-with-resources

Dan hoef je je daar minder/geen zorgen over te maken
Pagina: 1