使用java从100个图像URL的文本文件中提取图像

时间:2015-06-21 05:19:44

标签: java file url file-io

我有一个包含大量图片网址的文字文件。我需要获取一个Java代码来自动提取这些图像并将这些图像保存到文件中。我知道如何从单个URL保存图像,但是如何修改代码以进行多线程处理?我想将所有图像放在一个具有原始文件名的文件夹下。我试图谷歌出许多代码,但一切都失败了。请帮我找一个解决方案。答案将受到高度赞赏。

我用来保存单个图像的代码是:

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;

public class SaveImageFromUrl {
    public static void main(String[] args) throws Exception {
        String imageUrl = "http://http://img.emol.com/2015/04/25/nepalterremoto02ok_2260.jpg";
        String destinationFile = "/home/abc/image.jpg";
        saveImage(imageUrl, destinationFile);
    }

    public static void saveImage(String imageUrl, String destinationFile) throws IOException {
        URL url = new URL(imageUrl);
        InputStream is = url.openStream();
        OutputStream os = new FileOutputStream(destinationFile);

        byte[] b = new byte[2048];
        int length;

        while ((length = is.read(b)) != -1) {
            os.write(b, 0, length);
        }
        is.close();
        os.close();
    }
}

3 个答案:

答案 0 :(得分:2)

您可以利用预先存在的API ...

  • 使用Files.readAllLines阅读文件
  • ImageIO.readImageIO.write下载文件
  • 运行并发任务的Executor API,以帮助提高速度

所以,基本上,从每个URL下载图像都是相同的过程,可以封装成一个简单的任务。

public class DownloadImageFromURLTask implements Callable<File> {

    private URL url;
    private String path;

    public DownloadImageFromURLTask(URL url, String path) {
        this.url = url;
        this.path = path;
    }

    @Override
    public File call() throws Exception {

        BufferedImage img = ImageIO.read(url);
        String name = url.getPath();
        name = name.substring(name.lastIndexOf("/"));
        File output = new File(path, name);
        ImageIO.write(img, "jpg", output);

        return output;
    }

}

我在这里使用了Callable,因为它会插入Executor API并允许我获取返回结果,即下载图像的File。< / p>

接下来,我们需要从文本文件中读取URL并构建要执行的任务列表......

        List<String> listOfURLs = Files.readAllLines(new File("ListOfURLs.txt").toPath());
        List<DownloadImageFromURLTask> listOfTasks = new ArrayList<>(listOfURLs.size());
        String path = "/home/abc";
        for (String url : listOfURLs) {
            listOfTasks.add(new DownloadImageFromURLTask(new URL(url), path));
        }

为简单起见,我刚刚使用了Files.readAllLines

接下来,我们需要执行所有任务......

        ExecutorService exector = Executors.newFixedThreadPool(4);
        List<Future<File>> listOfFutures = exector.invokeAll(listOfTasks);

这是使用固定大小的线程池,这允许我们调整一些性能,因为每个任务将被合并,直到线程可用于运行它。

这里使用invokeAll是一个阻塞调用,这意味着在所有任务完成或失败之前,它不会返回。方便。

您可以选择处理生成的List FutureCallable,其中包含 for (int index = 0; index < listOfFutures.size(); index++) { Future<File> future = listOfFutures.get(index); try { File file = future.get(); } catch (ExecutionException ex) { String url = listOfURLs.get(index); System.out.println("Failed to download image from " + url); ex.printStackTrace(); } } 的返回结果

@Scripts.Render("~/Scripts/Owner.js")

在此示例中,它正在处理列表以查找失败的任务。

有关详细信息,请查看Reading/Loading an ImageWriting/Saving an ImageExecutorsReading, Writing, and Creating Files

答案 1 :(得分:0)

您可以在命令行上使用curl来获取多个文件。但是,我假设您正在尝试学习Java并发,因此我使用并发性重新编写程序:

更新:现在处理文件并下载每个网址并保留原始文件名

cn

答案 2 :(得分:0)

要从网址文字中获取图片,您可以使用以下代码:

public class SaveImageFromUrl {
    BufferedImage img = null;

    public static void main(String[] args)  {
        String path = "https://upload.wikimedia.org/wikipedia/commons/1/1e/Stonehenge.jpg";
        String destinationFile = "C:\\Users\\user\\Desktop";

        try {
            BufferedImage tmp = ImageIO.read(new URL(path));
            ImageIO.write(tmp, "jpg", new File(destinationFile + "\\" + "image" + ".jpg"));
        } catch (Exception ex) {
            System.out.println("Exception ex  ///" + ex);
        }
    }
}