关于poi读取中的一些坑

最近使用poi解析excel遇到了很多问题,由于是第一次使用,遇到了很多坑。

上传的时候:

poi对于excel时候,对于office2003和office2007的解析不太一样,使用不同的方式解析,因此需要在页面做版本校验或者后台设置不同版本的处理方式,poi中HSSFWorkbookXSSFWorkbook都实现了Workbook接口,HSSFWorkbook针对的2003的版本,XSSFWorkbook针对的是2007的版本,在解析excel的时候要注意,不然会抛异常。

解析excel的时候:

关于格式的问题:

我们经常会读一些数,比如手机号,如果按照数字读取需要注意指定格式(DecimalFormat df = new DecimalFormat("#.#########"))来处理读取数据含有小数位的问题

另外在读取单元格的时候最好判断单元格类型,这里列出部分格式判断:

public static String getCellValue(XSSFCell cell) {  
            String cellValue = "";  
            DecimalFormat df = new DecimalFormat("#.#########");
                switch (cell.getCellType()) {  
                case XSSFCell.CELL_TYPE_STRING: 
                    cellValue = cell.getRichStringCellValue().getString().trim();  
                    break;  
                case XSSFCell.CELL_TYPE_NUMERIC:
                    cellValue = df.format(cell.getNumericCellValue()).toString();  
                    break; 
                default:  
                    cellValue = "";  
            }
            return cellValue;  
        }

关于excel原来有数据,但是删除数据后格式仍旧保留导致的读取时候仍然读到该行导致报空指针异常问题:

因为我读取的excel只有一列,所以我直接先判断row是否为空,为空则认为该行没有数据,不读取单元格内容

关于导出问题:

excel一般导出这里不做介绍,一般按照正常格式就可以,这里想说一下如果导出的数据了比较大的时候,建议使用poi3.8以上版本中的SXSSFWorkbook

之前导出10W数据后台报内存溢出,改用SXSSFWorkbook后没有出现该情况。具体不做分析,刚入行不久,还在研究阶段。会继续研究和更新。这里只是将自己遇到的问题总结一下。

<think>首先,用户要求我使用POI库来解析Word文档(可能是.doc或.docx格式),并将内容(文字和图片等)存储到数据库中。我需要参考提供的引用内容,这些引用涉及到POI的使用、依赖项以及数据处理。关键引用摘要:-引用[1]:提到使用ApachePOI的hwpf模块来处理.doc文件。-引用[2]:提到POI解析Word比HTML复杂,因为没有标签,需要遍历文本。-引用[3]:详细描述了使用POI处理Word表格数据和图片,支持DOCX和DOC,提供了对象定义和依赖。-引用[4]:提到处理Excel文件,涉及数字类型问题,但针对Word也需要注意数据类型。-引用[5]:提供了SpringBoot整合POI的依赖项。用户的具体查询是:“如何用POI解析Word文件并将包含文字和图片的内容存入数据库”。所以,我的回答需要覆盖:1.设置依赖。2.解析Word文件(包括文字、图片)。3.处理内容并将数据存储到数据库。由于引用[3]提到了一个完整的解决方案,我会基于它来构建我的回答。用户提供的引用[3]描述了一个方法:通过POI处理Word文档,支持DOCX和DOC,定义了对象如FieldInfo和ImportEntity,这些可以用于存储数据。结构化我的回答:-**介绍**:简要解释POI库和解析过程。-**步骤**:-1.**添加依赖**:参考引用[3]和[5],提供POI依赖项。-2.**读取Word文件**:解释如何使用POI读取.doc和.docx文件。-3.**提取内容**:-对于文字:遍历文档部分。-对于图片:提取图片并处理。-4.**处理数据**:定义一个模型类来存储提取的数据(如引用[3]的FieldInfo)。-5.**存储到数据库**:描述如何将处理后的数据保存到数据库,可能使用SpringBoot或类似框架。-**代码示例**:提供一个简化的代码片段,展示关键部分。-**注意事项**:如处理文件格式差异、错误处理等。-**生成相关问题**:根据系统指令,在结尾添加相关问题。系统指令:-使用中文回答。-行内数学表达式用$...$(可能不适用于此)。-独立公式用$$...$$(这里可能用不到)。-在引用的段落末尾添加引用标识,如[^1]。-生成相关问题。参考用户提供的示例格式(关于快速排序的示例),结构清晰,有代码块和相关问题。确保回答真实可靠:基于引用内容构建我的响应。最终回答大纲:1.**介绍**:解释POI读取Word并将内容存入数据库的可行性。2.**关键步骤**:-添加依赖。-读取Word文件。-遍历和提取文字内容。-提取图片内容。-定义数据模型(类似引用[3]的对象)。-保存到数据库(使用JDBC、SpringData等)。3.**代码示例**:展示一个简化版的解析代码。4.**注意事项**:讨论常见,如文件格式处理(.docvs.docx)、数字处理等。5.**相关问题**:生成3-5个相关问题。生成相关问题:-针对解析Word时可能遇到的问题。-例如:如何优化解析性能?如何处理特殊元素如表格?如何确保数据一致性?</think> ### 使用Apache POI解析Word文档并将文字和图片内容存入数据库 解析Word文档(包括.doc和.docx格式)并将内容(如文字和图片)存储到数据库是Java开发中的常见需求,尤其是在处理客户数据录入时。Apache POI是一个强大的库,提供了hwpf模块处理.doc文件,以及ooxml模块处理.docx文件[^1]。通过POI,您可以遍历文档元素来提取结构化数据,然后通过JDBC、Spring Boot或其他框架将数据持久化到数据库中。以下是详细的实现步骤和代码示例,基于引用内容构建一个完整的解决方案。 #### 1. **添加POI依赖** 首先,在您的Java项目(如Maven)中添加必要的依赖,包括poi-ooxml用于.docx文件、poi-scratchpad用于.doc文件,以及相关工具包。引用[5]中提供的依赖很全面: ```xml <!-- 在pom.xml中添加 --> <dependencies> <!-- POI核心 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.17</version> <!-- 最新稳定版本,推荐3.15+ --> </dependency> <!-- DOCX文件处理 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </dependency> <!-- DOC文件处理 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-scratchpad</artifactId> <version>3.17</version> </dependency> <!-- Spring Boot集成(可选) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> <version>2.7.0</version> <!-- 根据项目调整 --> </dependency> </dependencies> ``` 如果使用Spring Boot,参考[^5]引入Spring Data JPA来简化数据库操作。 #### 2. **读取Word文件并提取内容** 解析Word文件的关键是使用POI的`XWPFDocument`(.docx)或`HWPFDocument`(.doc)类来遍历文档元素。Word没有HTML那样的标签结构,因此需要逐段、逐表处理,并特别注意图片提取[^2]。 ##### 步骤分解: - **读取文件**:根据文件后缀选择正确的POI类。 - **提取文字内容**:遍历文档中的段落(runs)、表格(tables)等。 - **提取图片**:使用POI的`XWPFPictureData`(.docx)或`PicRecord`(.doc)读取图片为字节数组,然后保存到文件系统或数据库的Blob字段。 - **数据处理**:定义一个数据模型(如引用[3]的`FieldInfo`)来存储提取的元素。 参考[^3]的对象定义,我们简化一个数据模型(Entity)类来映射Word内容: ```java import lombok.Data; import javax.persistence.*; // 使用JPA注解 import java.util.List; @Data @Entity public class WordContent { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String contentText; // 存储文字内容 @Lob // 用于存储二进制数据(图片) private byte[] contentImage; // 其他字段,如图片路径、表格索引等,参考[^3] } ``` ##### 示例代码:解析Word并提取数据 以下是一个核心方法,演示如何用POI读取Word文件(支持.doc和.docx),提取文字和图片,然后保存到数据库中。假设我们使用Spring Boot和JPA。 ```java import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.usermodel.Picture; import org.apache.poi.xwpf.usermodel.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.persistence.EntityManager; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.List; @Service public class WordParserService { @Autowired private EntityManager entityManager; // 或使用Spring Data JPA的Repository public void parseAndSaveWord(String filePath) throws IOException { File file = new File(filePath); if (filePath.endsWith(".docx")) { try (FileInputStream fis = new FileInputStream(file); XWPFDocument doc = new XWPFDocument(fis)) { // 提取文字:遍历段落 StringBuilder textContent = new StringBuilder(); for (XWPFParagraph para : doc.getParagraphs()) { textContent.append(para.getText()).append("\n"); } // 提取图片:遍历所有图片数据 List<XWPFPictureData> pictures = doc.getAllPictures(); for (int i = 0; i < pictures.size(); i++) { XWPFPictureData pic = pictures.get(i); byte[] imageBytes = pic.getData(); // 图片字节数组 // 创建并保存实体到数据库 WordContent entity = new WordContent(); entity.setContentText(textContent.toString()); entity.setContentImage(imageBytes); // 存储为Blob entityManager.persist(entity); } } } else if (filePath.endsWith(".doc")) { try (FileInputStream fis = new FileInputStream(file); HWPFDocument doc = new HWPFDocument(fis)) { // 提取文字 String text = doc.getDocumentText(); StringBuilder textContent = new StringBuilder(text); // 提取图片 for (Picture pic : doc.getPicturesTable().getAllPictures()) { byte[] imageBytes = pic.getContent(); // 图片字节数组 // 保存到数据库 WordContent entity = new WordContent(); entity.setContentText(textContent.toString()); entity.setContentImage(imageBytes); entityManager.persist(entity); } } } } } ``` **注意事项**: - **文件格式处理**:确保根据后缀(.docx vs .doc)选择正确的POI类,否则会抛出异常[^1]。 - **图片处理**:图片以字节数组形式存储为Blob类型在数据库(如MySQL的LONGBLOB或PostgreSQL的BYTEA)中。如果文档没有图片,代码需要处理空场景。 - **数据模型扩展**:引用[3]提到的`FieldInfo`模型支持表格索引等,您可以根据需求扩展,例如添加字段处理表格数据。 - **性能优化**:对于大文件,分块提取避免OOM错误[^2]。 - **数据类型处理**:类似Excel,注意数字类型(如科学记数法)的转换,引用[^4]中提到的方法可应用于字符串或数值字段[^4]。 #### 3. **存储到数据库** 使用Spring Boot的数据访问层(如JPA Repository)简化数据库操作。定义一个Repository来保存实体: ```java import org.springframework.data.jpa.repository.JpaRepository; public interface WordContentRepository extends JpaRepository<WordContent, Long> {} ``` 在服务类中注入并调用保存: ```java @Autowired private WordContentRepository repository; public void saveContent(WordContent entity) { repository.save(entity); } ``` 运行服务时,传入Word文件路径即可完成解析和入库。 #### 4. **常见问题和建议** - **错误处理**:添加异常处理(如文件不存在、格式不支持),确保健壮性。 - **图片优化**:如果图片过大,先压缩再存储,或保存为文件路径而非Blob。 - **测试**:使用JUnit测试各种Word格式的场景。 - **工具辅助**:对于复杂结构(如表格),结合poi-ooxml的`XWPFTable`类遍历单元格[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值