簡體   English   中英

將 Java InputStream 作為文件參數發送到 Linux 命令

[英]Sending Java InputStream to Linux Commands as a File Parameter

最近參與了Storlet項目,它是OpenStack Swift項目的一個中間件。 我不打算談論 Storlet,但簡而言之,Storlet 在存儲到 swift object 存儲的對象(文件)上運行 java 代碼。 storlet 讀取文件並以 InputSream 的形式發送到 java 應用程序,這意味着我們不直接訪問文件。

這是一個 storlet 的示例代碼,它獲取圖像作為輸入流並制作它的縮略圖。

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.io.InputStream;
import java.io.OutputStream;

import org.openstack.storlet.common.IStorlet;
import org.openstack.storlet.common.StorletException;
import org.openstack.storlet.common.StorletInputStream;
import org.openstack.storlet.common.StorletLogger;
import org.openstack.storlet.common.StorletObjectOutputStream;
import org.openstack.storlet.common.StorletContainerHandle;
import org.openstack.storlet.common.StorletOutputStream;
import org.openstack.storlet.common.StorletUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

public class ThumbnailStorlet implements IStorlet {
   @Override
   public void invoke(ArrayList<StorletInputStream> inputStreams,
        ArrayList<StorletOutputStream> outputStreams,
        Map<String, String> parameters, StorletLogger log)
        throws StorletException {
    log.emitLog("ThumbnailStorlet Invoked");

    /*
     * Get input stuff
     */
    HashMap<String, String> object_md;
    StorletInputStream storletInputStream = inputStreams.get(0);
            InputStream thumbnailInputStream = storletInputStream.getStream();
    object_md = storletInputStream.getMetadata();
    /*
     * Get output stuff
     */

    StorletObjectOutputStream storletObjectOutputStream = (StorletObjectOutputStream)outputStreams.get(0);
            OutputStream thumbnailOutputStream = storletObjectOutputStream.getStream();

    /*
     * Set the output metadata
     */
    log.emitLog("Setting metadata");
    storletObjectOutputStream.setMetadata(object_md);

    /*
     * Read Input to BufferedImage
     */
    log.emitLog("Reading Input");
    BufferedImage img = null;
            try {
            img = ImageIO.read(thumbnailInputStream);
    } catch (Exception e) {
        log.emitLog("Failed to read input stream to buffered image");
        throw new StorletException("Failed to read input stream to buffered image " + e.getMessage());
    } finally {
        try {
            thumbnailInputStream.close();
        } catch (IOException e) {
            log.emitLog("Failed to close input stream");
        }
    }
    try {
        thumbnailInputStream.close();
    } catch (IOException e) {
        log.emitLog("Failed to close input stream");
    }

    /*
     * Convert
     */
    log.emitLog("Converting");
    int newH = img.getHeight()/8;
    int newW = img.getWidth()/8;
            int type = img.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
    BufferedImage thumbnailImage = new BufferedImage(newW, newH, type);
            Graphics2D g = thumbnailImage.createGraphics();
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(img, 0, 0, newW, newH, null);
            g.dispose();

    /*
     * Write
     */
    log.emitLog("Writing Output");
    try {
        ImageIO.write(thumbnailImage, "PNG" , thumbnailOutputStream);
    } catch (Exception e) {
        log.emitLog("Failed to write image to out stream");
        throw new StorletException("Failed to write image to out stream " + e.getMessage());
    } finally {
        try {
            thumbnailOutputStream.close();
        } catch (IOException e) {
        }
    }

    try {
            thumbnailOutputStream.close();
    } catch (IOException e) {
    }

    log.emitLog("Done");

}

}

現在.. 我想在我的 java 代碼中使用一些在圖像上運行的外部應用程序,例如GDAL ,假設代碼類似於上面的代碼(與上面的代碼不完全相同)。 GDLA 有一些 cli 命令。 例如這個命令

 gdal_translate -of JPEG -co QUALITY=50  input.tif output.jpg

input.tif 已經存儲到我的 object 存儲中,storlet 可以讀取它並將其作為輸入流提供給我,我也有一些練習如何使用 java ProcessBuilder在 java 中運行外部進程但是,想象一下我收到 input.tif 作為 InputStream 不是一份文件。

接下來,我不想將 InputStream 寫回到我的應用程序運行的本地存儲,因為存儲空間不足(可能 object 非常大,超過 2GB)並且還會降低性能。

java 中是否有任何方法可以將 InputStream 作為文件參數傳遞給外部進程而不將其存儲在磁盤上。

我在 Ubuntu Docker 上運行我的代碼

我不認為你能做到這一點,一個File需要存儲在一個File system (本地或遠程)中才能被讀取。 您可以嘗試將ByteArrayInputStream作為讀取過程的基礎,但 GDAL 過程應支持該類型的輸入:

https://gdal.org/programs/gdal_translate.html#cmdoption-gdal_translate-arg-src_dataset

根據 GDAL 文檔,這似乎是不可能的:

<src_dataset>
The source dataset name. It can be either file name, URL of data source or subdataset name for multi-dataset files.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM