Почему батик не может сохранить файл .svg с помощью OutputStream?

Я хочу манипулировать существующим файлом .svg из файловой системы, используя библиотеку Batik от Apache. Моя цель - загрузить файл .svg, нарисовать на нем несколько фигур, а затем сохранить окончательный результат в файловой системе.

Сейчас у меня два класса. Первый класс может загрузить файл .svg и нарисовать на нем форму, но не может сохранить результат. Второй класс умеет рисовать фигуры на новом холсте и сохранять результат в файловой системе.

Это первый класс. Я пытаюсь сохранить окончательный результат с помощью OutputStream, но это не сработало.


import org.apache.batik.svggen.SVGGraphics2D;
import org.apache.batik.svggen.SVGGraphics2DIOException;
import org.apache.batik.swing.JSVGCanvas;
import org.apache.batik.swing.svg.GVTTreeBuilderAdapter;
import org.apache.batik.swing.svg.GVTTreeBuilderEvent;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.MalformedURLException;
import java.util.concurrent.atomic.AtomicBoolean;

public class RedrawingSVG extends JFrame {

    protected AtomicBoolean shown = new AtomicBoolean(false);

    public static void main(String[] args) throws MalformedURLException, InterruptedException, FileNotFoundException, UnsupportedEncodingException, SVGGraphics2DIOException {
        RedrawingSVG redrawingSVG = new RedrawingSVG();
        redrawingSVG.drawSvg();
    }

    public void drawSvg() throws MalformedURLException, InterruptedException, FileNotFoundException, UnsupportedEncodingException, SVGGraphics2DIOException {
        final JSVGCanvas canvas = new JSVGCanvas();
        canvas.setDocumentState(JSVGCanvas.ALWAYS_DYNAMIC); // to update it
        canvas.setURI(new File("/home/ekuntsevich/Downloads/img.svg").toURI().toURL().toString());

        canvas.addGVTTreeBuilderListener(new GVTTreeBuilderAdapter() {
            public void gvtBuildCompleted(GVTTreeBuilderEvent e) {
                synchronized (shown) {
                    shown.set(true); // No modifications be fore!!
                    shown.notifyAll();
                }
            }
        });
        getContentPane().add(canvas);

        setSize(800, 400);
        setVisible(true);

        synchronized (shown) { // Strictly required to wait
            while (shown.get() == false) {
                try {
                    shown.wait(0);
                } catch (Exception e) {
                }
            }
        }
        Document doc = canvas.getSVGDocument();

        SVGGraphics2D svgGenerator = new SVGGraphics2D(doc);
        svgGenerator.setPaint(Color.red);
        svgGenerator.fill(new Rectangle(100, 100, 1000, 1000));

        Element root = doc.getDocumentElement();
        svgGenerator.getRoot(root);

        Writer out;
        try {
            OutputStream outputStream = new FileOutputStream(new File("img2.svg"));
            out = new OutputStreamWriter(outputStream, "UTF-8");
            svgGenerator.stream(out, true);
            outputStream.flush();
            outputStream.close();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (SVGGraphics2DIOException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Это второй класс.


import java.awt.Rectangle;
import java.awt.Graphics2D;
import java.awt.Color;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.IOException;

import org.apache.batik.svggen.SVGGraphics2D;
import org.apache.batik.dom.GenericDOMImplementation;

import org.apache.batik.svggen.SVGGraphics2DIOException;
import org.w3c.dom.Document;
import org.w3c.dom.DOMImplementation;

public class TestSVGGen {

    public void paint(Graphics2D g2d) {
        g2d.setPaint(Color.red);
        g2d.fill(new Rectangle(10, 10, 100, 100));
    }

    public static void main(String[] args) throws IOException {

        // Get a DOMImplementation.
        DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();

        // Create an instance of org.w3c.dom.Document.
        String svgNS = "http://www.w3.org/2000/svg";
        Document document = domImpl.createDocument(svgNS, "svg", null);

        // Create an instance of the SVG Generator.
        SVGGraphics2D svgGenerator = new SVGGraphics2D(document);

        // Ask the test to render into the SVG Graphics2D implementation.
        TestSVGGen test = new TestSVGGen();
        test.paint(svgGenerator);

        // Finally, stream out SVG to the standard output using
        // UTF-8 encoding.
        boolean useCSS = true; // we want to use CSS style attributes
        Writer out;
        try {
            OutputStream outputStream = new FileOutputStream(new File("img3.svg"));
            out = new OutputStreamWriter(outputStream, "UTF-8");
            svgGenerator.stream(out, useCSS);
            outputStream.flush();
            outputStream.close();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (SVGGraphics2DIOException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Наконец я хочу объединить возможности этих двух классов. Я хочу иметь код для: загрузки изображения .svg -> рисования чего-либо поверх этого изображения -> сохранить результат как изображение .svg в файловой системе.

Что именно означает «не сработало»? Что происходит вместо того, чтобы он работал?

Robert Longson 10.04.2019 20:12
Создание фильтров для вашего сайта
Создание фильтров для вашего сайта
Фильтры - удобный инструмент в арсенале веб-дизайнера. Они позволяют изменять элементы на странице с помощью всего нескольких строк кода. Эти...
Анимация SVG-узоров без единой строки CSS
Анимация SVG-узоров без единой строки CSS
Недавно я работал над веб-проектом, который позволил мне поэкспериментировать с шаблонами SVG. С SVG очень приятно работать, как только вы получите...
Как использовать d3.js для рисования 2D SVG-элементов в приложении Angular?
Как использовать d3.js для рисования 2D SVG-элементов в приложении Angular?
D3.js - это обширная библиотека, используемая для привязки произвольных данных к объектной модели документа (DOM). Мы разберем основные варианты...
1
1
681
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я решил свою проблему. Я просмотрел разные сигнатуры для метода stream из класса SVGGraphics2D и обнаружил, что есть метод с параметрами, подходящими для моего случая. Я использовал следующий метод stream(Element svgRoot, Writer writer) для сохранения изображения .svg. Наконец, вместо svgGenerator.stream(out, true); я использовал svgGenerator.stream(root, out);. Меня устраивает.

Самый быстрый способ сохранить SVGDOcument в файл [для будущих поколений :)]

public static void saveSvgDocumentToFile(SVGDocument document, File file)
        throws FileNotFoundException, IOException {
    SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
    try (Writer out = new OutputStreamWriter(new FileOutputStream(file), "UTF-8")) {
        svgGenerator.stream(document.getDocumentElement(), out);
    }
}

Другие вопросы по теме