欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實現(xiàn)Excel圖片URL篩選與大小檢測的全過程

 更新時間:2025年08月07日 10:07:02   作者:Nicky.Ma  
在數(shù)據(jù)處理場景中,我們常需篩選Excel中的圖片URL,本文分享一個完整的Java方案,涵蓋從讀取圖片URL到檢測有效性、篩選大小,再到生成新Excel文件的全過程,同時講解開發(fā)與優(yōu)化過程,需要的朋友可以參考下

引言

在數(shù)據(jù)處理場景中,我們常需篩選Excel中的圖片URL。本文分享一個完整的Java方案,涵蓋從讀取圖片URL到檢測有效性、篩選大小,再到生成新Excel文件的全過程,同時講解開發(fā)與優(yōu)化過程,幫助你解決實際業(yè)務(wù)中的數(shù)據(jù)篩選和清洗需求。

一、問題背景

客戶現(xiàn)場圖片數(shù)據(jù),要求如下:

  1. 讀取Excel的圖片URL。
  2. 檢測URL有效性并獲取圖片大小。
  3. 篩選大于1MB或無法訪問(404)的圖片記錄。
  4. 保留原始數(shù)據(jù)格式,尤其是日期類型數(shù)據(jù)。
  5. 生成篩選后的新Excel文件。

二、核心實現(xiàn)方案

(一)技術(shù)選型

為實現(xiàn)上述目標(biāo),我們主要采用以下技術(shù):

  1. Apache POI :用于讀取和寫入Excel文件,支持對單元格數(shù)據(jù)的操作及格式處理,能方便地處理XLSX文件。
  2. HttpURLConnection :用于檢測圖片URL的有效性并獲取圖片大小,通過發(fā)送HEAD請求獲取資源信息,避免下載整個圖片浪費帶寬。

(二)關(guān)鍵代碼實現(xiàn)

1. Excel文件讀取與寫入

package cn.api.server;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ImageSizeFilter {
    private static final Logger LOGGER = Logger.getLogger(ImageSizeFilter.class.getName());
    private static final int CONNECT_TIMEOUT = 5000;
    private static final int READ_TIMEOUT = 5000;
    private static final double BYTES_TO_MEGABYTES = 1024.0 * 1024.0;
    private static final double SIZE_THRESHOLD = 1.0;
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

    public static void main(String[] args) {
        String inputFilePath = "C:/Users/admin/Desktop/圖片數(shù)據(jù).xlsx";
        String outputFilePath = "C:/Users/admin/Desktop/圖片數(shù)據(jù)_篩選后.xlsx";

        System.out.println("開始處理Excel文件...");
        System.out.println("輸入文件: " + inputFilePath);

        long startTime = System.currentTimeMillis();
        int processedCount = 0;
        int filteredCount = 0;

        try (FileInputStream inputStream = new FileInputStream(new File(inputFilePath));
             Workbook workbook = new XSSFWorkbook(inputStream)) {

            Sheet sheet = workbook.getSheetAt(0);
            int totalRows = sheet.getLastRowNum();
            System.out.println("發(fā)現(xiàn) " + totalRows + " 條數(shù)據(jù)記錄");

            try (Workbook newWorkbook = new XSSFWorkbook()) {
                Sheet newSheet = newWorkbook.createSheet();
                Row headerRow = sheet.getRow(0);
                Row newHeaderRow = newSheet.createRow(0);
                
                // 復(fù)制表頭并添加新列
                copyRow(headerRow, newHeaderRow);
                createHeaderCell(newHeaderRow, "圖片大?。∕)");
                createHeaderCell(newHeaderRow, "狀態(tài)");

                int newRowIndex = 1;
                for (int i = 1; i <= totalRows; i++) {
                    if (i % 100 == 0) {
                        System.out.println("已處理 " + i + "/" + totalRows + " 行");
                    }

                    Row row = sheet.getRow(i);
                    if (row != null) {
                        Cell urlCell = row.getCell(7);
                        if (urlCell != null) {
                            String imageUrl = getCellValue(urlCell);
                            if (isValidUrl(imageUrl)) {
                                processedCount++;
                                long sizeInBytes = getImageSize(imageUrl);
                                double sizeInMegabytes = sizeInBytes / BYTES_TO_MEGABYTES;
                                boolean is404 = sizeInBytes == 0 && isUrl404(imageUrl);
                                
                                if (sizeInMegabytes > SIZE_THRESHOLD || is404) {
                                    filteredCount++;
                                    Row newRow = newSheet.createRow(newRowIndex++);
                                    copyRowWithDateHandling(row, newRow, workbook, newWorkbook);
                                    newRow.createCell(headerRow.getLastCellNum()).setCellValue(sizeInMegabytes);
                                    newRow.createCell(headerRow.getLastCellNum() + 1).setCellValue(is404 ? "404" : "圖片過大");
                                }
                            }
                        }
                    }
                }

                try (FileOutputStream outputStream = new FileOutputStream(new File(outputFilePath))) {
                    newWorkbook.write(outputStream);
                }

                long endTime = System.currentTimeMillis();
                System.out.println("篩選完成!耗時:" + (endTime - startTime) / 1000 + " 秒");
                System.out.println("處理記錄數(shù):" + processedCount);
                System.out.println("篩選出的記錄數(shù):" + filteredCount);
                System.out.println("結(jié)果保存至:" + outputFilePath);
            }
        } catch (IOException e) {
            LOGGER.log(Level.SEVERE, "處理文件時出錯", e);
        }
    }
}

在上述代碼中,我們通過FileInputStream讀取原始Excel文件,利用XSSFWorkbook將其加載為Workbook對象。然后獲取第一個工作表(Sheet),并遍歷其行數(shù)據(jù)。對于篩選出的符合條件的行,我們創(chuàng)建新的Workbook對象(newWorkbook),并在其中創(chuàng)建新的工作表(newSheet),將原始表頭復(fù)制過來并添加新列 “圖片大小(M)” 和 “狀態(tài)”,用于存儲圖片大小信息和篩選狀態(tài)。

2. URL檢測與圖片大小獲取

// 獲取圖片大?。ㄗ止?jié))
private static long getImageSize(String imageUrl) {
    HttpURLConnection connection = null;
    try {
        URL url = new URL(imageUrl);
        connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("HEAD");
        connection.setConnectTimeout(CONNECT_TIMEOUT);
        connection.setReadTimeout(READ_TIMEOUT);
        connection.connect();
        return connection.getResponseCode() == HttpURLConnection.HTTP_OK 
               ? connection.getContentLength() : 0;
    } catch (IOException e) {
        LOGGER.log(Level.SEVERE, "獲取圖片大小異常", e);
        return 0;
    } finally {
        if (connection != null) {
            connection.disconnect();
        }
    }
}

// 判斷URL是否404
private static boolean isUrl404(String imageUrl) {
    HttpURLConnection connection = null;
    try {
        URL url = new URL(imageUrl);
        connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("HEAD");
        connection.setConnectTimeout(CONNECT_TIMEOUT);
        connection.setReadTimeout(READ_TIMEOUT);
        connection.connect();
        return connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND;
    } catch (IOException e) {
        LOGGER.log(Level.SEVERE, "檢測404異常", e);
        return false;
    } finally {
        if (connection != null) {
            connection.disconnect();
        }
    }
}

這里,我們使用HttpURLConnection發(fā)送HEAD請求到指定的圖片URL。HEAD請求不會下載資源實體內(nèi)容,只請求資源的頭部信息,這樣可以快速獲取圖片的相關(guān)信息,如大小等。通過調(diào)用connection.getContentLength()方法可獲取圖片大?。ㄒ宰止?jié)為單位)。同時,我們還定義了isUrl404()方法來判斷URL是否返回404狀態(tài)碼,以便識別無法訪問的圖片。

3. 單元格數(shù)據(jù)讀取與處理

// 獲取單元格值(處理日期格式)
private static String getCellValue(Cell cell) {
    if (cell == null) {
        return "";
    }
    int cellType = cell.getCellType();
    switch (cellType) {
        case Cell.CELL_TYPE_STRING:
            return cell.getStringCellValue();
        case Cell.CELL_TYPE_NUMERIC:
            return DateUtil.isCellDateFormatted(cell) 
                   ? DATE_FORMAT.format(cell.getDateCellValue()) 
                   : String.valueOf(cell.getNumericCellValue());
        case Cell.CELL_TYPE_BOOLEAN:
            return String.valueOf(cell.getBooleanCellValue());
        case Cell.CELL_TYPE_FORMULA:
            return cell.getCellFormula();
        default:
            return "";
    }
}

在讀取Excel單元格數(shù)據(jù)時,需考慮不同類型的數(shù)據(jù)處理方式。對于字符串類型單元格,直接獲取其字符串值;對于數(shù)值型單元格,若其為日期格式(通過DateUtil.isCellDateFormatted(cell)判斷),則將其轉(zhuǎn)換為Date對象并按照指定格式(yyyy - MM - dd)格式化為字符串,否則以常規(guī)數(shù)值形式返回;對于布爾型單元格,返回對應(yīng)的布爾值字符串;對于公式型單元格,返回其公式內(nèi)容。

4. 行數(shù)據(jù)復(fù)制

// 復(fù)制行(表頭專用,不處理日期)
private static void copyRow(Row sourceRow, Row targetRow) {
    for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
        Cell sourceCell = sourceRow.getCell(i);
        Cell targetCell = targetRow.createCell(i);
        if (sourceCell != null) {
            int cellType = sourceCell.getCellType();
            switch (cellType) {
                case Cell.CELL_TYPE_STRING:
                    targetCell.setCellValue(sourceCell.getStringCellValue());
                    break;
                case Cell.CELL_TYPE_NUMERIC:
                    targetCell.setCellValue(sourceCell.getNumericCellValue());
                    break;
                case Cell.CELL_TYPE_BOOLEAN:
                    targetCell.setCellValue(sourceCell.getBooleanCellValue());
                    break;
                case Cell.CELL_TYPE_FORMULA:
                    targetCell.setCellFormula(sourceCell.getCellFormula());
                    break;
            }
        }
    }
}

// 復(fù)制行(數(shù)據(jù)行專用,處理日期格式)
private static void copyRowWithDateHandling(Row sourceRow, Row targetRow, 
                                           Workbook sourceWorkbook, Workbook targetWorkbook) {
    for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
        Cell sourceCell = sourceRow.getCell(i);
        Cell targetCell = targetRow.createCell(i);
        if (sourceCell != null) {
            int cellType = sourceCell.getCellType();
            switch (cellType) {
                case Cell.CELL_TYPE_STRING:
                    targetCell.setCellValue(sourceCell.getStringCellValue());
                    break;
                case Cell.CELL_TYPE_NUMERIC:
                    if (DateUtil.isCellDateFormatted(sourceCell)) {
                        targetCell.setCellValue(sourceCell.getDateCellValue());
                        CellStyle newCellStyle = targetWorkbook.createCellStyle();
                        newCellStyle.cloneStyleFrom(sourceCell.getCellStyle());
                        targetCell.setCellStyle(newCellStyle);
                    } else {
                        targetCell.setCellValue(sourceCell.getNumericCellValue());
                    }
                    break;
                case Cell.CELL_TYPE_BOOLEAN:
                    targetCell.setCellValue(sourceCell.getBooleanCellValue());
                    break;
                case Cell.CELL_TYPE_FORMULA:
                    targetCell.setCellFormula(sourceCell.getCellFormula());
                    break;
            }
        }
    }
}

為實現(xiàn)行數(shù)據(jù)的復(fù)制,我們定義了兩個方法。copyRow()方法用于復(fù)制表頭行數(shù)據(jù),直接根據(jù)單元格類型設(shè)置目標(biāo)單元格的值;copyRowWithDateHandling()方法用于復(fù)制數(shù)據(jù)行,在處理數(shù)值型單元格時,會判斷其是否為日期格式,若是,則將其作為日期處理并復(fù)制對應(yīng)的單元格樣式,以確保日期格式在新Excel文件中正確顯示。

三、優(yōu)化過程詳解

(一)初始實現(xiàn)問題

在最初的實現(xiàn)中,我們遇到了以下問題:

  1. 日期格式處理不當(dāng) :數(shù)值型日期被轉(zhuǎn)為普通數(shù)字,導(dǎo)致數(shù)據(jù)展示不符合預(yù)期,例如原本在Excel中顯示為 “2024 - 05 - 20” 的日期,在讀取后變?yōu)橐淮當(dāng)?shù)字。
  2. Java 8兼容性問題 :最初代碼使用了Java 12+的switch表達(dá)式,但在實際部署環(huán)境中需兼容Java 8,導(dǎo)致代碼無法正常運行。
  3. 缺少完整的行復(fù)制方法 :在復(fù)制行數(shù)據(jù)時,未能全面處理各種單元格類型及樣式,導(dǎo)致新生成的Excel文件數(shù)據(jù)格式混亂。

(二)日期格式處理優(yōu)化

通過引入DateUtil.isCellDateFormatted()方法檢測單元格是否為日期格式,并使用SimpleDateFormat將Date對象格式化為指定字符串形式,成功解決了日期格式處理問題。優(yōu)化后的代碼如下:

private static String getCellValue(Cell cell) {
    if (cell == null) {
        return "";
    }
    int cellType = cell.getCellType();
    switch (cellType) {
        case Cell.CELL_TYPE_STRING:
            return cell.getStringCellValue();
        case Cell.CELL_TYPE_NUMERIC:
            return DateUtil.isCellDateFormatted(cell) 
                   ? DATE_FORMAT.format(cell.getDateCellValue()) 
                   : String.valueOf(cell.getNumericCellValue());
        case Cell.CELL_TYPE_BOOLEAN:
            return String.valueOf(cell.getBooleanCellValue());
        case Cell.CELL_TYPE_FORMULA:
            return cell.getCellFormula();
        default:
            return "";
    }
}

(三)Java 8兼容性改造

將枚舉和switch表達(dá)式改為傳統(tǒng)寫法,使用Cell.CELL_TYPE_* 常量,并重構(gòu)行復(fù)制方法,使其在Java 8環(huán)境下穩(wěn)定運行。改造后的行復(fù)制方法如下:

private static void copyRowWithDateHandling(Row sourceRow, Row targetRow, 
                                           Workbook sourceWorkbook, Workbook targetWorkbook) {
    for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
        Cell sourceCell = sourceRow.getCell(i);
        Cell targetCell = targetRow.createCell(i);
        if (sourceCell != null) {
            int cellType = sourceCell.getCellType();
            switch (cellType) {
                case Cell.CELL_TYPE_STRING:
                    targetCell.setCellValue(sourceCell.getStringCellValue());
                    break;
                case Cell.CELL_TYPE_NUMERIC:
                    if (DateUtil.isCellDateFormatted(sourceCell)) {
                        targetCell.setCellValue(sourceCell.getDateCellValue());
                        CellStyle newCellStyle = targetWorkbook.createCellStyle();
                        newCellStyle.cloneStyleFrom(sourceCell.getCellStyle());
                        targetCell.setCellStyle(newCellStyle);
                    } else {
                        targetCell.setCellValue(sourceCell.getNumericCellValue());
                    }
                    break;
                case Cell.CELL_TYPE_BOOLEAN:
                    targetCell.setCellValue(sourceCell.getBooleanCellValue());
                    break;
                case Cell.CELL_TYPE_FORMULA:
                    targetCell.setCellFormula(sourceCell.getCellFormula());
                    break;
            }
        }
    }
}

(四)完整功能實現(xiàn)

經(jīng)過上述優(yōu)化后,我們的代碼實現(xiàn)了以下功能:

  1. 準(zhǔn)確讀取Excel文件中的數(shù)據(jù),包括各種類型單元格數(shù)據(jù),特別是正確處理了日期格式數(shù)據(jù),避免了數(shù)據(jù)變形問題。
  2. 通過HttpURLConnection有效檢測圖片URL的合法性及獲取圖片大小,能夠精準(zhǔn)篩選出大于1MB或無法訪問(404)的圖片記錄。
  3. 在生成新Excel文件時,完整保留了原始數(shù)據(jù)的格式,并新增列存儲圖片大小信息和篩選狀態(tài),方便用戶查看篩選結(jié)果。
  4. 兼容Java 8環(huán)境,確保代碼在不同版本的JDK下穩(wěn)定運行,適應(yīng)更多實際應(yīng)用場景。

四、使用說明

(一)環(huán)境準(zhǔn)備

  1. JDK版本 :需安裝JDK 8或以上版本。
  2. Maven依賴 :在項目中引入以下Apache POI相關(guān)依賴,用于操作Excel文件。
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.2</version>
</dependency>

(二)運行方式

  1. 根據(jù)實際需求修改main方法中的輸入文件路徑(inputFilePath)和輸出文件路徑(outputFilePath),指定待處理的Excel文件和生成結(jié)果的保存位置。
  2. 編譯項目,運行ImageSizeFilter類的main方法,程序?qū)⒆詣娱_始處理Excel文件,并在控制臺輸出處理進(jìn)度和結(jié)果信息。

(三)自定義配置

  1. 圖片大小閾值 :可通過修改SIZE_THRESHOLD常量的值來調(diào)整圖片大小篩選閾值,例如將其改為2.0,則篩選出大于2MB的圖片。
  2. 網(wǎng)絡(luò)連接超時時間 :根據(jù)網(wǎng)絡(luò)狀況調(diào)整CONNECT_TIMEOUT和READ_TIMEOUT常量的值,以優(yōu)化圖片URL檢測過程中的網(wǎng)絡(luò)連接性能。
  3. 日期顯示格式 :若需更改日期在新Excel文件中的顯示格式,可修改DATE_FORMAT常量對應(yīng)的SimpleDateFormat模式,如改為 “yyyy/MM/dd HH:mm:ss” 以包含時間信息。

五、技術(shù)總結(jié)與擴(kuò)展方向

(一)關(guān)鍵技術(shù)點總結(jié)

  1. POI操作Excel :熟練掌握POI對Excel文件的讀寫操作,包括工作簿、工作表、行、單元格的創(chuàng)建、獲取及數(shù)據(jù)讀寫,是實現(xiàn)本功能的核心基礎(chǔ)。通過合理使用CellStyle等類,可有效控制單元格數(shù)據(jù)的顯示格式。
  2. HttpURLConnection網(wǎng)絡(luò)請求 :利用HttpURLConnection發(fā)送HEAD請求檢測圖片URL的有效性及獲取圖片大小,是一種高效且節(jié)省帶寬的方法。正確設(shè)置請求方法、超時時間等參數(shù),可確保網(wǎng)絡(luò)請求的穩(wěn)定性和準(zhǔn)確性。
  3. Java 8兼容性編程 :在實際項目開發(fā)中,考慮到不同環(huán)境的兼容性需求,避免使用過高版本的Java特性,采用傳統(tǒng)語法結(jié)構(gòu)和常量,能提高代碼的通用性和可移植性。
  4. 數(shù)據(jù)格式處理 :對于Excel中的日期等特殊數(shù)據(jù)類型,需深入了解其存儲和展示原理,通過合理的判斷和轉(zhuǎn)換邏輯,確保數(shù)據(jù)在程序處理過程中及最終結(jié)果中的準(zhǔn)確性。

(二)可能的擴(kuò)展方向

  1. 多線程處理 :針對大規(guī)模數(shù)據(jù)處理場景,可考慮引入多線程技術(shù),將Excel文件的行數(shù)據(jù)分配到多個線程同時進(jìn)行圖片URL檢測和篩選操作,從而顯著提高處理效率,減少程序運行時間。
  2. 圖片預(yù)覽功能 :在篩選出不符合要求的圖片后,為進(jìn)一步方便用戶查看和分析,可增加圖片預(yù)覽功能。例如,利用圖像處理庫將圖片縮略圖嵌入到生成的新Excel文件中,或開發(fā)一個簡單的界面程序展示圖片預(yù)覽。
  3. 支持多種文件格式 :除了Excel文件(.xlsx),還可擴(kuò)展程序支持CSV等其他常見數(shù)據(jù)文件格式,以適應(yīng)更廣泛的數(shù)據(jù)處理需求。這需要根據(jù)不同文件格式的特點,調(diào)整數(shù)據(jù)讀取、寫入及格式處理等相關(guān)代碼邏輯。
  4. 數(shù)據(jù)庫存儲與查詢 :對于經(jīng)過篩選的圖片數(shù)據(jù)及相關(guān)信息,可考慮將其存儲到數(shù)據(jù)庫中,實現(xiàn)數(shù)據(jù)的持久化。同時,借助數(shù)據(jù)庫的查詢功能,能夠方便地對篩選結(jié)果進(jìn)行后續(xù)的統(tǒng)計分析、數(shù)據(jù)檢索等操作,為用戶提供了一種更靈活的數(shù)據(jù)管理方式。

六、結(jié)語

通過本案例,我們深刻體會到Java在數(shù)據(jù)處理領(lǐng)域的強(qiáng)大能力以及在實際業(yè)務(wù)開發(fā)中的廣泛應(yīng)用。借助Apache POI和HttpURLConnection等工具和技術(shù),能夠高效地實現(xiàn)Excel圖片URL的篩選與大小檢測功能,并解決實際業(yè)務(wù)中的數(shù)據(jù)清洗問題。在開發(fā)過程中,注重細(xì)節(jié)處理,如數(shù)據(jù)格式保留、跨版本兼容性等,是提升程序質(zhì)量和用戶體驗的關(guān)鍵。未來,隨著業(yè)務(wù)需求的不斷拓展和技術(shù)的持續(xù)發(fā)展,我們可以對現(xiàn)有程序進(jìn)行進(jìn)一步優(yōu)化和擴(kuò)展,以滿足更多樣化的數(shù)據(jù)處理場景。

希望本文對你有所幫助,如果你在實現(xiàn)過程中遇到任何問題或有任何改進(jìn)建議,歡迎在評論區(qū)留言交流。

附錄,所有代碼:

package cn.api.server;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ImageSizeFilter {
    private static final Logger LOGGER = Logger.getLogger(ImageSizeFilter.class.getName());
    // 設(shè)置連接超時時間(毫秒)
    private static final int CONNECT_TIMEOUT = 5000;
    // 設(shè)置讀取超時時間(毫秒)
    private static final int READ_TIMEOUT = 5000;
    // 定義字節(jié)到兆字節(jié)的轉(zhuǎn)換系數(shù)
    private static final double BYTES_TO_MEGABYTES = 1024.0 * 1024.0;
    // 圖片大小閾值(MB)
    private static final double SIZE_THRESHOLD = 1.0;
    // 日期格式
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

    public static void main(String[] args) {
        String inputFilePath = "C:/Users/admin/Desktop/圖片數(shù)據(jù).xlsx";
        String outputFilePath = "C:/Users/admin/Desktop/圖片數(shù)據(jù)_篩選后.xlsx";

        System.out.println("開始處理Excel文件...");
        System.out.println("輸入文件: " + inputFilePath);

        long startTime = System.currentTimeMillis();
        int processedCount = 0;
        int filteredCount = 0;

        try (FileInputStream inputStream = new FileInputStream(new File(inputFilePath));
             Workbook workbook = new XSSFWorkbook(inputStream)) {

            Sheet sheet = workbook.getSheetAt(0);
            int totalRows = sheet.getLastRowNum();
            System.out.println("發(fā)現(xiàn) " + totalRows + " 條數(shù)據(jù)記錄");

            try (Workbook newWorkbook = new XSSFWorkbook()) {
                Sheet newSheet = newWorkbook.createSheet();

                // 復(fù)制表頭,并新增圖片大小列和狀態(tài)列
                Row headerRow = sheet.getRow(0);
                Row newHeaderRow = newSheet.createRow(0);
                copyRow(headerRow, newHeaderRow);
                createHeaderCell(newHeaderRow, "圖片大?。∕)");
                createHeaderCell(newHeaderRow, "狀態(tài)");

                int newRowIndex = 1;
                for (int i = 1; i <= totalRows; i++) {
                    if (i % 100 == 0) {
                        System.out.println("已處理 " + i + "/" + totalRows + " 行");
                    }

                    Row row = sheet.getRow(i);
                    if (row != null) {
                        // 根據(jù)實踐的Excel表設(shè)置數(shù)字,這里是第8列
                        Cell urlCell = row.getCell(7);
                        if (urlCell != null) {
                            String imageUrl = getCellValue(urlCell);
                            if (isValidUrl(imageUrl)) {
                                processedCount++;
                                long sizeInBytes = getImageSize(imageUrl);
                                double sizeInMegabytes = sizeInBytes / BYTES_TO_MEGABYTES;
                                boolean is404 = false;
                                if (sizeInBytes == 0) {
                                    is404 = isUrl404(imageUrl);
                                }
                                if (sizeInMegabytes > SIZE_THRESHOLD || is404) {
                                    filteredCount++;
                                    Row newRow = newSheet.createRow(newRowIndex++);
                                    copyRowWithDateHandling(row, newRow, workbook, newWorkbook);
                                    // 在新行的倒數(shù)第二列寫入圖片大小(M)
                                    newRow.createCell(headerRow.getLastCellNum()).setCellValue(sizeInMegabytes);
                                    // 在新行的最后一列寫入狀態(tài)
                                    newRow.createCell(headerRow.getLastCellNum() + 1).setCellValue(is404 ? "404" : "圖片過大");
                                }
                            } else {
                                LOGGER.log(Level.WARNING, "發(fā)現(xiàn)不合法的URL (行 {0}): {1}", new Object[]{i, imageUrl});
                            }
                        }
                    }
                }

                try (FileOutputStream outputStream = new FileOutputStream(new File(outputFilePath))) {
                    newWorkbook.write(outputStream);
                }

                long endTime = System.currentTimeMillis();
                System.out.println("篩選完成!");
                System.out.println("處理時間: " + (endTime - startTime) / 1000 + " 秒");
                System.out.println("處理記錄數(shù): " + processedCount);
                System.out.println("篩選出的記錄數(shù): " + filteredCount);
                System.out.println("結(jié)果保存到: " + outputFilePath);

            } catch (IOException e) {
                LOGGER.log(Level.SEVERE, "寫入輸出文件時出錯", e);
                System.err.println("錯誤: 無法寫入輸出文件: " + outputFilePath);
            }

        } catch (IOException e) {
            LOGGER.log(Level.SEVERE, "讀取輸入文件時出錯", e);
            System.err.println("錯誤: 無法讀取輸入文件: " + inputFilePath);
        }
    }

    private static long getImageSize(String imageUrl) {
        HttpURLConnection connection = null;
        try {
            URL url = new URL(imageUrl);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("HEAD");
            connection.setConnectTimeout(CONNECT_TIMEOUT);
            connection.setReadTimeout(READ_TIMEOUT);
            connection.connect();
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                return connection.getContentLength();
            } else {
                LOGGER.log(Level.WARNING, "獲取圖片大小失敗,URL: {0},響應(yīng)碼: {1}", new Object[]{imageUrl, responseCode});
                return 0;
            }
        } catch (IOException e) {
            LOGGER.log(Level.SEVERE, "獲取圖片大小IO異常,URL: " + imageUrl, e);
            return 0;
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    private static boolean isUrl404(String imageUrl) {
        HttpURLConnection connection = null;
        try {
            URL url = new URL(imageUrl);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("HEAD");
            connection.setConnectTimeout(CONNECT_TIMEOUT);
            connection.setReadTimeout(READ_TIMEOUT);
            connection.connect();
            return connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND;
        } catch (IOException e) {
            LOGGER.log(Level.SEVERE, "判斷 URL 是否 404 時發(fā)生 IO 異常,URL: " + imageUrl, e);
            return false;
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    private static String getCellValue(Cell cell) {
        if (cell == null) {
            return "";
        }

        // 兼容Java 8的寫法
        int cellType = cell.getCellType();
        switch (cellType) {
            case Cell.CELL_TYPE_STRING:
                return cell.getStringCellValue();
            case Cell.CELL_TYPE_NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    Date date = cell.getDateCellValue();
                    return DATE_FORMAT.format(date);
                } else {
                    return String.valueOf(cell.getNumericCellValue());
                }
            case Cell.CELL_TYPE_BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case Cell.CELL_TYPE_FORMULA:
                return cell.getCellFormula();
            default:
                return "";
        }
    }

    private static boolean isValidUrl(String url) {
        if (url == null || url.trim().isEmpty()) {
            return false;
        }
        try {
            new URL(url);
            return true;
        } catch (MalformedURLException e) {
            return false;
        }
    }

    /**
     * 復(fù)制行(用于表頭復(fù)制,不處理日期格式)
     */
    private static void copyRow(Row sourceRow, Row targetRow) {
        for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
            Cell sourceCell = sourceRow.getCell(i);
            Cell targetCell = targetRow.createCell(i);
            if (sourceCell != null) {
                int cellType = sourceCell.getCellType();
                switch (cellType) {
                    case Cell.CELL_TYPE_STRING:
                        targetCell.setCellValue(sourceCell.getStringCellValue());
                        break;
                    case Cell.CELL_TYPE_NUMERIC:
                        targetCell.setCellValue(sourceCell.getNumericCellValue());
                        break;
                    case Cell.CELL_TYPE_BOOLEAN:
                        targetCell.setCellValue(sourceCell.getBooleanCellValue());
                        break;
                    case Cell.CELL_TYPE_FORMULA:
                        targetCell.setCellFormula(sourceCell.getCellFormula());
                        break;
                    default:
                        break;
                }
            }
        }
    }

    /**
     * 復(fù)制行并處理日期格式(用于數(shù)據(jù)行復(fù)制)
     */
    private static void copyRowWithDateHandling(Row sourceRow, Row targetRow, Workbook sourceWorkbook, Workbook targetWorkbook) {
        for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
            Cell sourceCell = sourceRow.getCell(i);
            Cell targetCell = targetRow.createCell(i);
            if (sourceCell != null) {
                int cellType = sourceCell.getCellType();
                switch (cellType) {
                    case Cell.CELL_TYPE_STRING:
                        targetCell.setCellValue(sourceCell.getStringCellValue());
                        break;
                    case Cell.CELL_TYPE_NUMERIC:
                        if (DateUtil.isCellDateFormatted(sourceCell)) {
                            targetCell.setCellValue(sourceCell.getDateCellValue());
                            CellStyle newCellStyle = targetWorkbook.createCellStyle();
                            newCellStyle.cloneStyleFrom(sourceCell.getCellStyle());
                            targetCell.setCellStyle(newCellStyle);
                        } else {
                            targetCell.setCellValue(sourceCell.getNumericCellValue());
                        }
                        break;
                    case Cell.CELL_TYPE_BOOLEAN:
                        targetCell.setCellValue(sourceCell.getBooleanCellValue());
                        break;
                    case Cell.CELL_TYPE_FORMULA:
                        targetCell.setCellFormula(sourceCell.getCellFormula());
                        break;
                    default:
                        break;
                }
            }
        }
    }

    private static void createHeaderCell(Row headerRow, String headerValue) {
        Cell headerCell = headerRow.createCell(headerRow.getLastCellNum());
        headerCell.setCellValue(headerValue);
        CellStyle style = headerCell.getSheet().getWorkbook().createCellStyle();
        Font font = headerCell.getSheet().getWorkbook().createFont();
        font.setBold(true);
        style.setFont(font);
        headerCell.setCellStyle(style);
    }
}

以上就是Java實現(xiàn)Excel圖片URL篩選與大小檢測的全過程的詳細(xì)內(nèi)容,更多關(guān)于Java Excel圖片URL篩選與檢測的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java字節(jié)流、字符流與轉(zhuǎn)換流過程

    java字節(jié)流、字符流與轉(zhuǎn)換流過程

    輸入輸出流(IO流)是數(shù)據(jù)傳輸?shù)某橄蟾拍?用于表示數(shù)據(jù)在設(shè)備間的傳輸過程,IO流按數(shù)據(jù)類型分為字符流和字節(jié)流,按數(shù)據(jù)流向分為輸入流和輸出流,字節(jié)流操作單個字節(jié),字符流操作字符,在實際應(yīng)用中,非文本文件多用字節(jié)流操作
    2024-10-10
  • 使用JavaMail發(fā)送郵件保證成功的方法

    使用JavaMail發(fā)送郵件保證成功的方法

    JavaMail是利用現(xiàn)有的郵件賬戶發(fā)送郵件的工具,使用過JavaMail的api發(fā)送郵件的人可能會有這樣一個疑惑:我如何知道我調(diào)用該api發(fā)送的郵件是否成功呢?那么通過下面這篇文章大家一起來看看使用JavaMail保證郵件發(fā)送成功的方法,有需要的朋友們可以參考借鑒。
    2016-11-11
  • Java 批量刪除html中注釋內(nèi)容的方法

    Java 批量刪除html中注釋內(nèi)容的方法

    最近項目中有一個功能需要讀取外部html文本文件。但是有的html文件里面有大量的注釋,需要刪除其中的注釋在存儲
    2014-04-04
  • 解決logback的日志文件路徑問題

    解決logback的日志文件路徑問題

    這篇文章主要介紹了解決logback的日志文件路徑問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • springboot實用配置詳細(xì)圖文教程

    springboot實用配置詳細(xì)圖文教程

    SpringBoot從本質(zhì)上來說就是Spring,它通過了一些自己的特性幫助我們簡化了Spring應(yīng)用程序的開發(fā),下面這篇文章主要給大家介紹了關(guān)于springboot實用配置的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • java中字符串替換常用的4種方法

    java中字符串替換常用的4種方法

    在Java中String類提供了許多方便的方法來處理字符串,下面這篇文章主要給大家介紹了關(guān)于java中字符串替換常用的4種方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-03-03
  • 解決IDEA的Terminal中文亂碼問題

    解決IDEA的Terminal中文亂碼問題

    這篇文章主要介紹了解決IDEA的Terminal中文亂碼問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-07-07
  • 關(guān)于Spring事務(wù)隔離、傳播屬性與@Transactional注解

    關(guān)于Spring事務(wù)隔離、傳播屬性與@Transactional注解

    這篇文章主要介紹了關(guān)于事務(wù)隔離、Spring傳播屬性與@Transactional注解,如果一組處理步驟或者全部發(fā)生或者一步也不執(zhí)行,我們稱該組處理步驟為一個事務(wù),需要的朋友可以參考下
    2023-05-05
  • java單鏈表逆序用法代碼示例

    java單鏈表逆序用法代碼示例

    這篇文章主要介紹了java單鏈表逆序用法代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • 項目打包成jar后包無法讀取src/main/resources下文件的解決

    項目打包成jar后包無法讀取src/main/resources下文件的解決

    本文主要介紹了項目打包成jar后包無法讀取src/main/resources下文件的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04

最新評論