日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

apache poi 修改docx表格_一个excel(20M)就能干趴你的poi,你信吗(附源码)?

發(fā)布時間:2024/10/14 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 apache poi 修改docx表格_一个excel(20M)就能干趴你的poi,你信吗(附源码)? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

點擊上方“阿拉奇學(xué)Java”,選擇“置頂或者星標(biāo)

優(yōu)質(zhì)文章第一時間送達(dá)!

鏈接:?www.cnblogs.com/rongdi/p/11872810.html

推薦閱讀 |?Java 的 JSP 已經(jīng)被淘汰了嗎?

推薦閱讀 |?知乎高贊:本科生如何才能進(jìn)入騰訊、阿里等一流互聯(lián)網(wǎng)大廠?

這篇文章主要是因為使用POI導(dǎo)入一個20M的excel發(fā)生了OOM(OutOfMemoryError)異常。說來也慚愧,工作了這么多年,還真沒導(dǎo)入過這種大小的文件,并且還發(fā)生了內(nèi)存溢出。如果你百度下基本上清一色的告訴你:POI導(dǎo)入excel文件有兩種方式,第一種是用戶模式,這種模式用起來很簡單直觀,可以類比xml的dom方式解析(這里只針對excel2007,因為2003本身就有最大條數(shù)限制并且目前基本用的很少,這里直接忽略),第二種是event模式,這種通常是網(wǎng)上說的解決POI導(dǎo)入大excel的”萬金油“方法,可以類比為xml的sax解析方式。呵呵,我這篇文章首先就是要干趴這種方法(JVM使用-Xms512m -Xmx512m)。不信你隨便寫一個導(dǎo)入接口,導(dǎo)入如下20M大小的execl看看:鏈接: https://pan.baidu.com/s/1DUrS8ctLPp7Z6imOc1aIUQ 提取碼: hd79 。首先,既然要導(dǎo)入大點的excel2007,那么我們應(yīng)該稍微了解一下這種文件如何存儲數(shù)據(jù),我們百度上可以發(fā)現(xiàn),2007其實就是一個壓縮包,可以直接修改后綴成zip然后解壓打開文件看看,如下

?

上圖可以看到最大的兩個文件就兩個:sharedStrings.xml和sheet1.xml。其中sheet2.xml這個可以不關(guān)注,直接從excel刪掉都沒事,這里沒刪除主要是沒多大關(guān)系,這個excel文件也是測試直接提供給我的。由于sheet2比較小,與這個文章說到的內(nèi)存溢出并無關(guān)系,請不要胡思亂想,被分散了注意。直接用大文本編輯工具打開上圖兩個大文件,可以發(fā)現(xiàn)sharedString.xml里內(nèi)容其實就是excel中每個單元格里的字符串內(nèi)容(數(shù)字類型除外),sheet.xml就是每個sheet里的結(jié)構(gòu)xml,了解到這里基本上就了解了本文章說到問題的基本知識,然后下面進(jìn)入正題。先使用百度中查到的提供的event方式導(dǎo)入excel,代碼如下:
package?com.example.utils;

import?org.apache.poi.openxml4j.opc.OPCPackage;
import?org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
import?org.apache.poi.xssf.eventusermodel.XSSFReader;
import?org.apache.poi.xssf.usermodel.XSSFRichTextString;
import?org.xml.sax.Attributes;
import?org.xml.sax.InputSource;
import?org.xml.sax.SAXException;
import?org.xml.sax.XMLReader;
import?org.xml.sax.helpers.DefaultHandler;
import?org.xml.sax.helpers.XMLReaderFactory;

import?java.io.File;
import?java.io.InputStream;
import?java.sql.SQLException;
import?java.util.ArrayList;
import?java.util.Iterator;
import?java.util.List;

/**
?* 百度上直接copy過來的
?* XSSF and SAX (Event API)
?*/
public?abstract?class?BigDataParseExcelUtil?extends?DefaultHandler?{
????private?ReadOnlySharedStringsTable sst;
????private?String lastContents;
????private?boolean?nextIsString;
????private?int?sheetIndex = -1;
????private?List rowlist =?new?ArrayList();private?int?curRow =?0;?// 當(dāng)前行private?int?curCol =?0;?// 當(dāng)前列索引private?int?preCol =?0;?// 上一列列索引private?int?titleRow =?0;?// 標(biāo)題行,一般情況下為0private?int?rowsize =?0;?// 列數(shù)private?List excelList =?new?ArrayList();?//excel全部轉(zhuǎn)換為list// excel記錄行操作方法,以sheet索引,行索引和行元素列表為參數(shù),對sheet的一行元素進(jìn)行操作,元素為String類型public?abstract?void?optRows(int?sheetIndex,?int?curRow,
?????????????????????????????????List rowlist, List excelList)?throws?SQLException, Exception;// 只遍歷一個sheet,其中sheetId為要遍歷的sheet索引,從1開始,1-3/**
?????*?@param?filename
?????*?@param?sheetId sheetId為要遍歷的sheet索引,從1開始,1-3
?????*?@throws?Exception
?????*/public?void?processOneSheet(String filename,?int?sheetId)?throws?Exception?{
????????OPCPackage pkg = OPCPackage.open(filename);
????????XSSFReader r =?new?XSSFReader(pkg);
????????ReadOnlySharedStringsTable strings =?new?ReadOnlySharedStringsTable(pkg);
????????XMLReader parser = fetchSheetParser(strings);// rId2 found by processing the Workbook// 根據(jù) rId# 或 rSheet# 查找sheet
????????InputStream sheet2 = r.getSheet("rId"?+ sheetId);
????????sheetIndex++;
????????InputSource sheetSource =?new?InputSource(sheet2);
????????parser.parse(sheetSource);
????????sheet2.close();
????}@Overridepublic?void?characters(char[] ch,?int?start,?int?length)throws?SAXException?{// 得到單元格內(nèi)容的值
????????lastContents +=?new?String(ch, start, length);
????}public?void?process(InputStream inputStream)?throws?Exception?{
????????OPCPackage pkg = OPCPackage.open(inputStream);
????????XSSFReader r =?new?XSSFReader(pkg);
????????ReadOnlySharedStringsTable strings =?new?ReadOnlySharedStringsTable(pkg);
????????XMLReader parser = fetchSheetParser(strings);
????????Iterator sheets = r.getSheetsData();while?(sheets.hasNext()) {
????????????curRow =?0;
????????????sheetIndex++;
????????????InputStream sheet = sheets.next();
????????????InputSource sheetSource =?new?InputSource(sheet);
????????????parser.parse(sheetSource);
????????????sheet.close();
????????}
????}/**
?????* 遍歷 excel 文件
?????*/public?void?process(File file)?throws?Exception?{
????????OPCPackage pkg = OPCPackage.open(file);
????????XSSFReader r =?new?XSSFReader(pkg);
????????ReadOnlySharedStringsTable strings =?new?ReadOnlySharedStringsTable(pkg);
????????XMLReader parser = fetchSheetParser(strings);
????????Iterator sheets = r.getSheetsData();while?(sheets.hasNext()) {
????????????curRow =?0;
????????????sheetIndex++;
????????????InputStream sheet = sheets.next();
????????????InputSource sheetSource =?new?InputSource(sheet);
????????????parser.parse(sheetSource);
????????????sheet.close();
????????}
????}public?XMLReader?fetchSheetParser(ReadOnlySharedStringsTable sst)throws?SAXException?{
????????XMLReader parser = XMLReaderFactory.createXMLReader();// .createXMLReader("org.apache.xerces.parsers.SAXParser");this.sst = sst;
????????parser.setContentHandler(this);return?parser;
????}@Overridepublic?void?startElement(String uri, String localName, String name,
?????????????????????????????Attributes attributes)?throws?SAXException?{// c => 單元格if?(name.equals("c")) {// 如果下一個元素是 SST 的索引,則將nextIsString標(biāo)記為true
????????????String cellType = attributes.getValue("t");
????????????String rowStr = attributes.getValue("r");
????????????curCol =?this.getRowIndex(rowStr);if?(cellType !=?null?&& cellType.equals("s")) {
????????????????nextIsString =?true;
????????????}?else?{
????????????????nextIsString =?false;
????????????}
????????}// 置空
????????lastContents =?"";
????}@Overridepublic?void?endElement(String uri, String localName, String name)throws?SAXException?{// 根據(jù)SST的索引值的到單元格的真正要存儲的字符串// 這時characters()方法可能會被調(diào)用多次if?(nextIsString) {try?{int?idx = Integer.parseInt(lastContents);
????????????????lastContents =?new?XSSFRichTextString(sst.getEntryAt(idx))
????????????????????.toString();
????????????}?catch?(Exception e) {
????????????}
????????}// v => 單元格的值,如果單元格是字符串則v標(biāo)簽的值為該字符串在SST中的索引// 將單元格內(nèi)容加入rowlist中,在這之前先去掉字符串前后的空白符if?(name.equals("v")) {
????????????String value = lastContents.trim();
????????????value = value.equals("") ??" "?: value;int?cols = curCol - preCol;if?(cols >?1) {for?(int?i =?0; i < cols -?1; i++) {
????????????????????rowlist.add(preCol,?"");
????????????????}
????????????}
????????????preCol = curCol;
????????????rowlist.add(curCol -?1, value);
????????}?else?{// 如果標(biāo)簽名稱為 row ,這說明已到行尾,調(diào)用 optRows() 方法if?(name.equals("row")) {int?tmpCols = rowlist.size();if?(curRow >?this.titleRow && tmpCols this.rowsize) {for?(int?i =?0; i this.rowsize - tmpCols; i++) {
????????????????????????rowlist.add(rowlist.size(),?"");
????????????????????}
????????????????}try?{
????????????????????optRows(sheetIndex, curRow, rowlist, excelList);
????????????????}?catch?(SQLException e) {
????????????????????e.printStackTrace();
????????????????}?catch?(Exception e) {// TODO Auto-generated catch block
????????????????????e.printStackTrace();
????????????????}if?(curRow ==?this.titleRow) {this.rowsize = rowlist.size();
????????????????}
????????????????rowlist.clear();
????????????????curRow++;
????????????????curCol =?0;
????????????????preCol =?0;
????????????}
????????}
????}// 得到列索引,每一列c元素的r屬性構(gòu)成為字母加數(shù)字的形式,字母組合為列索引,數(shù)字組合為行索引,// 如AB45,表示為第(A-A+1)*26+(B-A+1)*26列,45行public?int?getRowIndex(String rowStr)?{
????????rowStr = rowStr.replaceAll("[^A-Z]",?"");byte[] rowAbc = rowStr.getBytes();int?len = rowAbc.length;float?num =?0;for?(int?i =?0; i < len; i++) {
????????????num += (rowAbc[i] -?'A'?+?1) * Math.pow(26, len - i -?1);
????????}return?(int) num;
????}
}
package?com.example.service;

import?com.example.utils.BigDataParseExcelUtil;
import?org.springframework.stereotype.Service;

import?java.io.InputStream;
import?java.sql.SQLException;
import?java.util.List;

/**
?*?@author: rongdi
?*?@date:
?*/
@Service
public?class?ExcelService?{

????public?void?import1(InputStream inputStream)?throws?Exception?{

????????BigDataParseExcelUtil xlx =?new?BigDataParseExcelUtil() {
????????????@Override
????????????public?void?optRows(int?sheetIndex,?int?curRow, List rowlist, List excelList)throws?SQLException?{
????????????????System.out.println(rowlist);
????????????}
????????};
????????xlx.process(inputStream);
????}


}


package?com.example.controller;

import?com.example.service.ExcelService;
import?org.springframework.beans.factory.annotation.Autowired;
import?org.springframework.stereotype.Controller;
import?org.springframework.web.bind.annotation.RequestMapping;
import?org.springframework.web.bind.annotation.RequestParam;
import?org.springframework.web.bind.annotation.ResponseBody;
import?org.springframework.web.multipart.MultipartFile;

/**
?* @author: rongdi
?* @date:
?*/
@Controller
public class ExcelController {

????@Autowired
????private ExcelService excelService;

????@RequestMapping("/excel/import1")
????@ResponseBody
????public String import1(@RequestParam("file") MultipartFile multipartFile) throws Exception {
????????excelService.import1(multipartFile.getInputStream());
????????return?"ok";
????}

}

使用postman等工具,導(dǎo)入上面說的20M的文件22.xlsx,報錯如下:

那我們優(yōu)化一下不使用inputStream,直接使用一個File傳入看看


????public?void?import2(File file)?throws?Exception?{
????????BigDataParseExcelUtil xlx =?new?BigDataParseExcelUtil() {
????????????@Override
????????????public?void?optRows(int?sheetIndex,?int?curRow, List rowlist, List excelList)throws?SQLException?{
????????????????System.out.println(rowlist);
????????????}
????????};
????????xlx.process(file);
????}

????@RequestMapping("/excel/import2")
????@ResponseBody
????public?String?import2(@RequestParam("file")?MultipartFile multipartFile)?throws?Exception?{
????????// 延遲解析比率
????????ZipSecureFile.setMinInflateRatio(-1.0d);
????????File tmp = Files.createTempFile("tmp-",?".xlsx").toFile();
????????Files.copy(multipartFile.getInputStream(), Paths.get(tmp.getPath()), StandardCopyOption.REPLACE_EXISTING);
????????excelService.import2(tmp);
????????return?"ok";
????}

使用postman上傳文件運行效果如下:

?

? 這時候就發(fā)現(xiàn)很尷尬了,難道是POI自己代碼里就有bug,我們可以使用斷點調(diào)試確認(rèn)一下這個strings里到底是不是全部放了sharedStrings.xml里的內(nèi)容。

? 由上證明就是這個strings裝多了導(dǎo)致內(nèi)存溢出了,從這里可以看出網(wǎng)上說使用event事件解析excel的方案基本都是行不通的,哎,我也不懂為啥百度上都是這種答案,難道他們壓根都沒遇到過大數(shù)據(jù)導(dǎo)入嗎?當(dāng)然也有可能我冤枉了他們,因為sharedStrings.xml中存放的是每個單元格的字符串內(nèi)容,這個存放是排重過的,如果雖然excel里單元格很多,但是大多都是整型或者大多都是重復(fù)的,那確實可以跳過這一步一路之后會一路暢通了,因為畢竟sax解析xml確實可以節(jié)省很多內(nèi)存。從上分析可以看到POI就兩種方式導(dǎo)入:一種是用戶方式寫代碼簡單,基本按順序數(shù)格子就好,但是類比dom方式解析xml,很耗內(nèi)存。第二種事件方式,類比sax方式解析xml確實很省內(nèi)存,但是POI提供的類里把解析出的大量字符串放入了集合中,還是會導(dǎo)致內(nèi)存溢出。那么我們怎么解決這個問題,這里很常規(guī)的想法是到底這個strings是用來干啥的,怎么用的,如果可以保持strings相同邏輯功能的前提下,修改了ReadOnlySharedStringsTable這個類的邏輯,就可以解決這里的內(nèi)存溢出了。那么我們可以直接搜索ReadOnlySharedStringsTable類里所有用到strings的方法上打上斷點,特別是從strings里取值的方法上,然后調(diào)大jvm內(nèi)存避免內(nèi)存溢出的情況下斷點調(diào)試如下

?  我們是不是可以直接往strings里添加字符串和獲取字符串的方法那里替換掉,不要使用strings這個集合存儲所有字符串。但是既然excel里設(shè)計成使用一個sharedStrings.xml存放公共的字符串,而不是像csv格式那樣,每次讀一行取一行數(shù)據(jù)就好了。那么這個sharedStrings.xml中的數(shù)據(jù)總要解析出來,總要有個地方存儲里面的數(shù)據(jù),不然怎么結(jié)合sheet.xml的格式獲取到每一行的數(shù)據(jù)呢?所以這里就很尷尬了,不能每次解析sharedStrings.xml時不保存每次需要獲取strings的時候,再去解析一下這個xm吧,如果從本文章的xml上來看,要重復(fù)解析25W次,效率極其低。現(xiàn)在問題可以簡化成我們需要把sharedStrings.xml解析出的所有字符串放在一個地方,還能方便解析,由于怕內(nèi)存溢出,肯定不能放在內(nèi)存中了。那么這里就有一些選擇,比如解析出的字符串按加入strings集合的順序放入數(shù)據(jù)庫,文件,外部存儲或者緩存(限制內(nèi)存大小,多余寫入文件)存儲中。然后使用的時候按照索引位置idx去一一取出。本文章先使用臨時文件來放這些數(shù)據(jù),因為不想搞那么復(fù)雜,導(dǎo)入任務(wù)不管再多復(fù)雜的系統(tǒng)中,最終執(zhí)行的都會是一個單節(jié)點,在單節(jié)點中先使用本機(jī)資源這種就近資源是最方便的。如下直接先復(fù)制源碼,然后修改上述說的兩個地方。


package?com.example.utils;

import?org.apache.poi.ooxml.util.SAXHelper;
import?org.apache.poi.openxml4j.opc.OPCPackage;
import?org.apache.poi.openxml4j.opc.PackagePart;
import?org.apache.poi.ss.usermodel.RichTextString;
import?org.apache.poi.util.Removal;
import?org.apache.poi.xssf.model.SharedStrings;
import?org.apache.poi.xssf.usermodel.XSSFRelation;
import?org.apache.poi.xssf.usermodel.XSSFRichTextString;
import?org.xml.sax.Attributes;
import?org.xml.sax.InputSource;
import?org.xml.sax.SAXException;
import?org.xml.sax.XMLReader;
import?org.xml.sax.helpers.DefaultHandler;

import?javax.xml.parsers.ParserConfigurationException;
import?java.io.File;
import?java.io.FileNotFoundException;
import?java.io.FileOutputStream;
import?java.io.FileReader;
import?java.io.IOException;
import?java.io.InputStream;
import?java.io.LineNumberReader;
import?java.io.PushbackInputStream;
import?java.nio.file.Files;
import?java.util.ArrayList;
import?java.util.LinkedHashMap;
import?java.util.List;
import?java.util.Map;

import?static?org.apache.poi.xssf.usermodel.XSSFRelation.NS_SPREADSHEETML;

public?class?ReadOnlySharedStringsTable?extends?DefaultHandler?implements?SharedStrings?{

????protected?final?boolean?includePhoneticRuns;

????/**
?????* An integer representing the total count of strings in the workbook. This count does not
?????* include any numbers, it counts only the total of text strings in the workbook.
?????*/
????protected?int?count;

????/**
?????* An integer representing the total count of unique strings in the Shared String Table.
?????* A string is unique even if it is a copy of another string, but has different formatting applied
?????* at the character level.
?????*/
????protected?int?uniqueCount;

????/**
?????* The shared strings table.
?????*/
????private?List strings;private?File tmp =?null;
????FileOutputStream fos =?null;private?int?counts;private?Map map =?new?LinkedHashMap();public?ReadOnlySharedStringsTable(OPCPackage pkg)throws?IOException, SAXException?{this(pkg,?true);
????}public?ReadOnlySharedStringsTable(OPCPackage pkg,?boolean?includePhoneticRuns)throws?IOException, SAXException?{this.includePhoneticRuns = includePhoneticRuns;
????????ArrayList parts =
????????????????pkg.getPartsByContentType(XSSFRelation.SHARED_STRINGS.getContentType());// Some workbooks have no shared strings table.if?(parts.size() >?0) {
????????????PackagePart sstPart = parts.get(0);
????????????readFrom(sstPart.getInputStream());
????????}
????}/**
?????* Like POIXMLDocumentPart constructor
?????*
?????* Calls {@link?#ReadOnlySharedStringsTable(PackagePart, boolean)}, with a
?????* value of true to include phonetic runs.
?????*
?????*?@since?POI 3.14-Beta1
?????*/public?ReadOnlySharedStringsTable(PackagePart part)?throws?IOException, SAXException?{this(part,?true);
????}/**
?????* Like POIXMLDocumentPart constructor
?????*
?????*?@since?POI 3.14-Beta3
?????*/public?ReadOnlySharedStringsTable(PackagePart part,?boolean?includePhoneticRuns)throws?IOException, SAXException?{this.includePhoneticRuns = includePhoneticRuns;
????????readFrom(part.getInputStream());
????}/**
?????* Read this shared strings table from an XML file.
?????*
?????*?@param?is The input stream containing the XML document.
?????*?@throws?IOException if an error occurs while reading.
?????*?@throws?SAXException if parsing the XML data fails.
?????*/public?void?readFrom(InputStream is)?throws?IOException, SAXException?{// test if the file is empty, otherwise parse it
????????PushbackInputStream pis =?new?PushbackInputStream(is,?1);int?emptyTest = pis.read();if?(emptyTest > -1) {
????????????pis.unread(emptyTest);
????????????InputSource sheetSource =?new?InputSource(pis);try?{
????????????????XMLReader sheetParser = SAXHelper.newXMLReader();
????????????????sheetParser.setContentHandler(this);
????????????????sheetParser.parse(sheetSource);
????????????}?catch(ParserConfigurationException e) {throw?new?RuntimeException("SAX parser appears to be broken - "?+ e.getMessage());
????????????}
????????}
????}/**
?????* Return an integer representing the total count of strings in the workbook. This count does not
?????* include any numbers, it counts only the total of text strings in the workbook.
?????*
?????*?@return?the total count of strings in the workbook
?????*/@Overridepublic?int?getCount()?{return?this.count;
????}/**
?????* Returns an integer representing the total count of unique strings in the Shared String Table.
?????* A string is unique even if it is a copy of another string, but has different formatting applied
?????* at the character level.
?????*
?????*?@return?the total count of unique strings in the workbook
?????*/@Overridepublic?int?getUniqueCount()?{return?this.uniqueCount;
????}/**
?????* Return the string at a given index.
?????* Formatting is ignored.
?????*
?????*?@param?idx index of item to return.
?????*?@return?the item at the specified position in this Shared String table.
?????*?@deprecated?use getItemAt instead
?????*/@Removal(version =?"4.2")@Deprecatedpublic?String?getEntryAt(int?idx)?{/**
?????????* 這里就是修改部分了,直接從按行存儲的臨時文件讀取需要的字符串
?????????*/
????????String value = map.get(idx +?1);if(value ==?null) {return?readString(idx,1000,this.uniqueCount);
????????}?else?{return?value;
????????}
????}/**
?????* 從指定位置讀取size個字符串,這里是使用局部性原理,每次讀取size個字符串,
?????* 以免每次需要讀取文件,性能極低
?????*?@return
?????*/private?String?readString(int?idx,int?size,int?numbers)?{
????????map.clear();int?currNumber = idx +?1;if?(currNumber 0?|| currNumber > numbers) {return?null;
????????}try?{
????????????FileReader in =?new?FileReader(tmp);
????????????LineNumberReader reader =?new?LineNumberReader(in);try?{
????????????????String line =?"";for(int?i =?1;i <= numbers;i ++) {
????????????????????line = reader.readLine();if(i >= currNumber && i < currNumber + size) {
????????????????????????map.put(i, line);
????????????????????}
????????????????}
????????????}?finally?{
????????????????reader.close();
????????????????in.close();
????????????}
????????}?catch?(Exception e) {
????????????System.out.println(e.getMessage());
????????}return?map.get(idx +?1);
????}/**
?????* Returns all the strings.
?????* Formatting is ignored.
?????*
?????*?@return?a list with all the strings
?????*?@deprecated?use getItemAt instead
?????*/@Removal(version =?"4.2")@Deprecatedpublic?List?getItems()?{return?strings;
????}@Overridepublic?RichTextString?getItemAt(int?idx)?{return?new?XSSFRichTextString(getEntryAt(idx));
????} ContentHandler methods private?StringBuilder characters;private?boolean?tIsOpen;private?boolean?inRPh;@Overridepublic?void?startElement(String uri, String localName, String name,
?????????????????????????????Attributes attributes)?throws?SAXException?{if?(uri !=?null?&& ! uri.equals(NS_SPREADSHEETML)) {return;
????????}if?("sst".equals(localName)) {
????????????String count = attributes.getValue("count");if(count !=?null)?this.count = Integer.parseInt(count);
????????????String uniqueCount = attributes.getValue("uniqueCount");if(uniqueCount !=?null)?this.uniqueCount = Integer.parseInt(uniqueCount);try?{
????????????????tmp = Files.createTempFile("tmp-",?".xlsx").toFile();
????????????}?catch?(IOException e) {
????????????????e.printStackTrace();
????????????}// this.strings = new ArrayList<>(this.uniqueCount);
????????????characters =?new?StringBuilder(64);try?{
????????????????fos =?new?FileOutputStream(tmp,true);
????????????}?catch?(FileNotFoundException e) {
????????????????e.printStackTrace();
????????????}
????????}?else?if?("si".equals(localName)) {
????????????characters.setLength(0);
????????}?else?if?("t".equals(localName)) {
????????????tIsOpen =?true;
????????}?else?if?("rPh".equals(localName)) {
????????????inRPh =?true;//append space...this assumes that rPh always comes after regular if?(includePhoneticRuns && characters.length() >?0) {
????????????????characters.append(" ");
????????????}
????????}
????}@Overridepublic?void?endElement(String uri, String localName, String name)?throws?SAXException?{if?(uri !=?null?&& ! uri.equals(NS_SPREADSHEETML)) {return;
????????}if?("si".equals(localName)) {// strings.add(characters.toString().intern());try?{/**
?????????????????* 這里就是修改的一部分,這里直接把字符串按行存入臨時文件
?????????????????*/
????????????????counts ++;
????????????????fos.write((characters.toString() +?"\n").getBytes());if(counts ==?this.uniqueCount) {
????????????????????fos.close();
????????????????}
????????????}?catch?(IOException e) {
????????????????e.printStackTrace();
????????????}
????????}?else?if?("t".equals(localName)) {
????????????tIsOpen =?false;
????????}?else?if?("rPh".equals(localName)) {
????????????inRPh =?false;
????????}
????}/**
?????* Captures characters only if a t(ext) element is open.
?????*/@Overridepublic?void?characters(char[] ch,?int?start,?int?length)?throws?SAXException?{if?(tIsOpen) {if?(inRPh && includePhoneticRuns) {
????????????????characters.append(ch, start, length);
????????????}?else?if?(! inRPh){
????????????????characters.append(ch, start, length);
????????????}
????????}
????}
}然后在自己代碼里把包換成自己的包,替換POI里該類的包,運行JVM堆情況如下毫無壓力

 自此內(nèi)存溢出問題大功告成!針對使用POI導(dǎo)入大Excel遇到的問題總結(jié)如下:1)網(wǎng)上給出的方案不管是用戶模式還是事件模式,往往都不能支持大excel的導(dǎo)入2)excel本質(zhì)上是一堆excel的壓縮包(這里只考慮2007忽略2003)改了個后綴名成xlsx3)使用事件導(dǎo)入時應(yīng)先將上傳文件存入文件,再使用文件OPCPackage.open(file),如果直接傳入輸入流,由于里面邏輯會將輸入流的所有內(nèi)容先存入ByteArrayOutputStream 中,這個輸出流實際上是一個內(nèi)存中的字節(jié)流,所以也會導(dǎo)致內(nèi)存溢出。4)用戶模式不用考慮,事件模式會先將sharedString.xml這個大xml解析出來放入一個List中,不管通過什么方式都繞不開需要解析這個類,因為每個單元格的字符串都放在這個xml中,而要解析這個xml最常規(guī)的方法就是保存在內(nèi)存使用list和map之內(nèi)的容器存放我相信不會有人會想剛解析出一個xml還要存回文件中把,這里基本就繞不開ReadOnlySharedStringsTable或者SharedStringsTable,就算你僥幸繞開了,想自己解析,或許還是重復(fù)這兩個類的悲劇,這就是另外一種內(nèi)存溢出的根源。回顧一下上述實現(xiàn)直接把sharedStrings.xml中的內(nèi)容粗略的保存到文件中,然后再從文件中獲取是屬于很低劣的實現(xiàn),只能說能滿足不內(nèi)存溢出,性能方面堪憂!下面直接借鑒easyexcel源碼中用到的ReadCache來實現(xiàn)保存sharedStrings.xml中的內(nèi)容
package?com.example.advanceevent;

import?com.example.utils.FileUtils;
import?org.ehcache.Cache;
import?org.ehcache.CacheManager;
import?org.ehcache.config.CacheConfiguration;
import?org.ehcache.config.builders.CacheConfigurationBuilder;
import?org.ehcache.config.builders.CacheManagerBuilder;
import?org.ehcache.config.builders.ResourcePoolsBuilder;
import?org.ehcache.config.units.MemoryUnit;
import?org.ehcache.core.Ehcache;
import?org.slf4j.Logger;
import?org.slf4j.LoggerFactory;

import?java.io.File;
import?java.util.HashMap;
import?java.util.UUID;

/**
?*?@author: rongdi
?*?@date:
?*/
public?class?ReadCache?{

????private?static?final?Logger LOGGER = LoggerFactory.getLogger(Ehcache.class);
????private?int?index =?0;
????private?HashMap dataMap =?new?HashMap(1334);private?static?CacheManager fileCacheManager;private?static?CacheConfiguration fileCacheConfiguration;private?static?CacheManager activeCacheManager;private?CacheConfiguration activeCacheConfiguration;private?Cache fileCache;private?Cache activeCache;private?String cacheAlias;private?int?cacheMiss =?0;public?ReadCache(int?maxCacheActivateSize)?{this.activeCacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Integer.class, HashMap.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap((long)maxCacheActivateSize, MemoryUnit.MB)).withSizeOfMaxObjectGraph(1000000L).withSizeOfMaxObjectSize((long)maxCacheActivateSize, MemoryUnit.MB).build();
????????init();
????}private?void?init()?{this.cacheAlias = UUID.randomUUID().toString();this.fileCache = fileCacheManager.createCache(this.cacheAlias, fileCacheConfiguration);this.activeCache = activeCacheManager.createCache(this.cacheAlias,?this.activeCacheConfiguration);
????}public?void?put(String value)?{this.dataMap.put(this.index, value);if?((this.index +?1) %?1000?==?0) {this.fileCache.put(this.index /?1000,?this.dataMap);this.dataMap =?new?HashMap(1334);
????????}
????????++this.index;if?(LOGGER.isDebugEnabled() &&?this.index %?1000000?==?0) {
????????????LOGGER.debug("Already put :{}",?this.index);
????????}
????}public?String?get(Integer key)?{if?(key !=?null?&& key >=?0) {int?route = key /?1000;
????????????HashMap dataMap = (HashMap)this.activeCache.get(route);if?(dataMap ==?null) {
????????????????dataMap = (HashMap)this.fileCache.get(route);this.activeCache.put(route, dataMap);if?(LOGGER.isDebugEnabled() &&?this.cacheMiss++ %?1000?==?0) {
????????????????????LOGGER.debug("Cache misses count:{}",?this.cacheMiss);
????????????????}
????????????}return?(String)dataMap.get(key);
????????}?else?{return?null;
????????}
????}public?void?putFinished()?{if?(this.dataMap !=?null) {this.fileCache.put(this.index /?1000,?this.dataMap);
????????}
????}public?void?destroy()?{
????????fileCacheManager.removeCache(this.cacheAlias);
????????activeCacheManager.removeCache(this.cacheAlias);
????}static?{
????????File cacheFile = FileUtils.createCacheTmpFile();
????????fileCacheManager = CacheManagerBuilder.newCacheManagerBuilder().with(CacheManagerBuilder.persistence(cacheFile)).build(true);
????????activeCacheManager = CacheManagerBuilder.newCacheManagerBuilder().build(true);
????????fileCacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Integer.class, HashMap.class, ResourcePoolsBuilder.newResourcePoolsBuilder().disk(10L, MemoryUnit.GB)).withSizeOfMaxObjectGraph(1000000L).withSizeOfMaxObjectSize(10L, MemoryUnit.GB).build();
????}
}package?com.example.advanceevent;

import?org.apache.poi.ooxml.util.SAXHelper;
import?org.apache.poi.openxml4j.opc.OPCPackage;
import?org.apache.poi.openxml4j.opc.PackagePart;
import?org.apache.poi.ss.usermodel.RichTextString;
import?org.apache.poi.util.Removal;
import?org.apache.poi.xssf.model.SharedStrings;
import?org.apache.poi.xssf.usermodel.XSSFRelation;
import?org.apache.poi.xssf.usermodel.XSSFRichTextString;
import?org.xml.sax.Attributes;
import?org.xml.sax.InputSource;
import?org.xml.sax.SAXException;
import?org.xml.sax.XMLReader;
import?org.xml.sax.helpers.DefaultHandler;

import?javax.xml.parsers.ParserConfigurationException;
import?java.io.IOException;
import?java.io.InputStream;
import?java.io.PushbackInputStream;
import?java.util.ArrayList;
import?java.util.List;

import?static?org.apache.poi.xssf.usermodel.XSSFRelation.NS_SPREADSHEETML;

public?class?ReadOnlySharedStringsTable?extends?DefaultHandler?implements?SharedStrings?{

????protected?final?boolean?includePhoneticRuns;

????/**
?????* An integer representing the total count of strings in the workbook. This count does not
?????* include any numbers, it counts only the total of text strings in the workbook.
?????*/
????protected?int?count;

????/**
?????* An integer representing the total count of unique strings in the Shared String Table.
?????* A string is unique even if it is a copy of another string, but has different formatting applied
?????* at the character level.
?????*/
????protected?int?uniqueCount;

????/**
?????* 緩存
?????*/
????ReadCache readCache =?new?ReadCache(100);

????private?int?counts;


????public?ReadOnlySharedStringsTable(OPCPackage pkg)throws?IOException, SAXException?{
????????this(pkg,?true);
????}

????public?ReadOnlySharedStringsTable(OPCPackage pkg,?boolean?includePhoneticRuns)throws?IOException, SAXException?{
????????this.includePhoneticRuns = includePhoneticRuns;
????????ArrayList parts =
????????????????pkg.getPartsByContentType(XSSFRelation.SHARED_STRINGS.getContentType());// Some workbooks have no shared strings table.if?(parts.size() >?0) {
????????????PackagePart sstPart = parts.get(0);
????????????readFrom(sstPart.getInputStream());
????????}
????}/**
?????* Like POIXMLDocumentPart constructor
?????*
?????* Calls {@link?#ReadOnlySharedStringsTable(PackagePart, boolean)}, with a
?????* value of true to include phonetic runs.
?????*
?????*?@since?POI 3.14-Beta1
?????*/public?ReadOnlySharedStringsTable(PackagePart part)?throws?IOException, SAXException?{this(part,?true);
????}/**
?????* Like POIXMLDocumentPart constructor
?????*
?????*?@since?POI 3.14-Beta3
?????*/public?ReadOnlySharedStringsTable(PackagePart part,?boolean?includePhoneticRuns)throws?IOException, SAXException?{this.includePhoneticRuns = includePhoneticRuns;
????????readFrom(part.getInputStream());
????}/**
?????* Read this shared strings table from an XML file.
?????*
?????*?@param?is The input stream containing the XML document.
?????*?@throws?IOException if an error occurs while reading.
?????*?@throws?SAXException if parsing the XML data fails.
?????*/public?void?readFrom(InputStream is)?throws?IOException, SAXException?{// test if the file is empty, otherwise parse it
????????PushbackInputStream pis =?new?PushbackInputStream(is,?1);int?emptyTest = pis.read();if?(emptyTest > -1) {
????????????pis.unread(emptyTest);
????????????InputSource sheetSource =?new?InputSource(pis);try?{
????????????????XMLReader sheetParser = SAXHelper.newXMLReader();
????????????????sheetParser.setContentHandler(this);
????????????????sheetParser.parse(sheetSource);
????????????}?catch(ParserConfigurationException e) {throw?new?RuntimeException("SAX parser appears to be broken - "?+ e.getMessage());
????????????}
????????}
????}/**
?????* Return an integer representing the total count of strings in the workbook. This count does not
?????* include any numbers, it counts only the total of text strings in the workbook.
?????*
?????*?@return?the total count of strings in the workbook
?????*/@Overridepublic?int?getCount()?{return?this.count;
????}/**
?????* Returns an integer representing the total count of unique strings in the Shared String Table.
?????* A string is unique even if it is a copy of another string, but has different formatting applied
?????* at the character level.
?????*
?????*?@return?the total count of unique strings in the workbook
?????*/@Overridepublic?int?getUniqueCount()?{return?this.uniqueCount;
????}/**
?????* Return the string at a given index.
?????* Formatting is ignored.
?????*
?????*?@param?idx index of item to return.
?????*?@return?the item at the specified position in this Shared String table.
?????*?@deprecated?use getItemAt instead
?????*/@Removal(version =?"4.2")@Deprecatedpublic?String?getEntryAt(int?idx)?{/**
?????????* 這里就是修改部分了,直接從按行存儲的臨時文件讀取需要的字符串
?????????*/return?readCache.get(idx);
????}/**
?????* Returns all the strings.
?????* Formatting is ignored.
?????*
?????*?@return?a list with all the strings
?????*?@deprecated?use getItemAt instead
?????*/@Removal(version =?"4.2")@Deprecatedpublic?List?getItems()?{return?null;
????}@Overridepublic?RichTextString?getItemAt(int?idx)?{return?new?XSSFRichTextString(getEntryAt(idx));
????} ContentHandler methods private?StringBuilder characters;private?boolean?tIsOpen;private?boolean?inRPh;@Overridepublic?void?startElement(String uri, String localName, String name,
?????????????????????????????Attributes attributes)?throws?SAXException?{if?(uri !=?null?&& ! uri.equals(NS_SPREADSHEETML)) {return;
????????}if?("sst".equals(localName)) {
????????????String count = attributes.getValue("count");if(count !=?null)?this.count = Integer.parseInt(count);
????????????String uniqueCount = attributes.getValue("uniqueCount");if(uniqueCount !=?null)?this.uniqueCount = Integer.parseInt(uniqueCount);// this.strings = new ArrayList<>(this.uniqueCount);
????????????characters =?new?StringBuilder(64);
????????}?else?if?("si".equals(localName)) {
????????????characters.setLength(0);
????????}?else?if?("t".equals(localName)) {
????????????tIsOpen =?true;
????????}?else?if?("rPh".equals(localName)) {
????????????inRPh =?true;//append space...this assumes that rPh always comes after regular if?(includePhoneticRuns && characters.length() >?0) {
????????????????characters.append(" ");
????????????}
????????}
????}@Overridepublic?void?endElement(String uri, String localName, String name)?throws?SAXException?{if?(uri !=?null?&& ! uri.equals(NS_SPREADSHEETML)) {return;
????????}if?("si".equals(localName)) {// strings.add(characters.toString().intern());
????????????readCache.put(characters.toString());/**
?????????????* 這里就是修改的一部分,這里直接把字符串按行存入臨時文件
?????????????*/
????????????counts ++;if(counts ==?this.uniqueCount) {
????????????????readCache.putFinished();
????????????}
????????}?else?if?("t".equals(localName)) {
????????????tIsOpen =?false;
????????}?else?if?("rPh".equals(localName)) {
????????????inRPh =?false;
????????}
????}/**
?????* Captures characters only if a t(ext) element is open.
?????*/@Overridepublic?void?characters(char[] ch,?int?start,?int?length)?throws?SAXException?{if?(tIsOpen) {if?(inRPh && includePhoneticRuns) {
????????????????characters.append(ch, start, length);
????????????}?else?if?(! inRPh){
????????????????characters.append(ch, start, length);
????????????}
????????}
????}
}

至此代碼效率有了相當(dāng)大的提高,而且內(nèi)存溢出問題也得到解決。詳細(xì)測試代碼:https://github.com/rongdi/poi-example.git

看到這里啦,說明你對這篇文章感興趣,幫忙轉(zhuǎn)發(fā)一下或者點擊文章右下角在。感謝啦!關(guān)注公眾號,回復(fù)「進(jìn)群」即可進(jìn)入無廣告技術(shù)交流群。同時送上250本電子書+學(xué)習(xí)視頻作為見面禮!有你想看的精彩?Java 的 JSP 已經(jīng)被淘汰了嗎?知乎高贊:本科生如何才能進(jìn)入騰訊、阿里等一流互聯(lián)網(wǎng)大廠?ArrayList集合為什么不能使用foreach增加、刪除、修改元素有一種幸福,叫娶個女項目經(jīng)理做老婆互聯(lián)網(wǎng)公司忽悠員工的黑話面試字節(jié)跳動,被懟的體無完膚!別在 Java 代碼里亂打日志了,這才是正確的打日志姿勢有了這套模板,女朋友再也不用擔(dān)心我刷不動 LeetCode 了支付寶架構(gòu)師眼中的高并發(fā)架構(gòu)20M文件從30秒壓縮到1秒,我是如何做到的(附源碼)?39 個奇葩代碼注釋,看完笑哭了。

總結(jié)

以上是生活随笔為你收集整理的apache poi 修改docx表格_一个excel(20M)就能干趴你的poi,你信吗(附源码)?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

一区二区三区高清不卡 | 日本成人中文字幕在线观看 | 亚洲人在线7777777精品 | 在线 高清 中文字幕 | 97av在线 | 久久伊人热 | 色综合a| 在线免费看黄色 | 欧美色精品天天在线观看视频 | 欧美成人91| 国产精品久久久久久999 | 色多视频在线观看 | 午夜色场| 日韩视频中文字幕 | av综合网址 | 成年人网站免费在线观看 | 一区二区三区电影大全 | 狠狠狠的干 | 国产色女人 | 国产视频在线观看一区二区 | 久久艹在线观看 | 欧美日韩精品二区第二页 | 天天操天天添天天吹 | 色综合久久久久综合体桃花网 | 国产精品电影一区 | 国产又粗又硬又爽视频 | 日本九九视频 | 国精产品999国精产 久久久久 | 久久 一区 | 国产精品久久久久久久久久ktv | 日本69hd | 日韩精品视频在线免费观看 | 99热国产在线| 国产精品丝袜久久久久久久不卡 | 欧美一区二区精美视频 | 97精品国产一二三产区 | 久久成人午夜 | 月丁香婷婷| 欧产日产国产69 | www婷婷| 亚洲精品动漫成人3d无尽在线 | 日韩理论影院 | 久久伦理电影网 | 日韩精品久久久久久 | 久久精品com | 久久精品久久久久 | 精品一区二区三区久久久 | 美女免费av| 黄色三级免费网址 | 久久夜色精品国产欧美乱 | 日本精品久久久久影院 | 日韩精品中文字幕av | 国产免费久久精品 | 激情电影在线观看 | 中文在线免费一区三区 | 久久激情综合网 | 91精品国产高清自在线观看 | 日韩在线一区二区免费 | 91亚洲国产成人久久精品网站 | 一区二区三区电影 | av在线免费网站 | 99色99| 精品一区二区亚洲 | 中文字幕av一区二区三区四区 | 精品国产乱子伦一区二区 | 日韩精品免费在线观看视频 | 精品美女视频 | 国产丝袜高跟 | 香蕉手机在线 | 国产亚洲精品久久久久久 | 韩国av在线播放 | 91片黄在线观 | 999精品视频 | 九色91在线视频 | 中文字幕乱码亚洲精品一区 | 日本少妇久久久 | 天天超碰| 青青久草在线视频 | 欧美精品中文在线免费观看 | 午夜视频在线网站 | 91av资源网| 日韩精品在线观看视频 | 午夜av剧场| 中文字幕av免费在线观看 | av三级在线播放 | 国产精品久久一区二区三区不卡 | 日本精品在线 | 自拍超碰在线 | 久久精品艹 | 久草在线视频首页 | 日韩另类在线 | 久久久99精品免费观看 | 青青河边草免费视频 | 九九热在线免费观看 | 狠狠网站 | 超碰在线98 | 麻豆传媒一区二区 | 国产精品久久久久免费a∨ 欧美一级性生活片 | 久久亚洲欧美日韩精品专区 | 国产高清视频免费 | 四虎影视8848dvd | 久草在线视频新 | 欧美精品久久久久久久久久 | 99热播精品 | 亚洲综合在线观看视频 | 欧美日韩亚洲在线 | 国产又粗又猛又黄 | 亚洲天堂在线观看完整版 | 久久免费的精品国产v∧ | 国产精品久久久久久久久久久杏吧 | 日韩在线观看视频中文字幕 | 欧美日韩xx| 96国产在线| 久久久电影网站 | 成人免费亚洲 | 国产精品久久av | 正在播放五月婷婷狠狠干 | 欧美激情片在线观看 | 国产精品手机在线 | 香蕉视频国产在线 | 91精品办公室少妇高潮对白 | 国产美女免费 | 午夜精品久久久久久久99水蜜桃 | 国产精品99精品 | 日韩天天操| 伊人官网| 免费a级毛片在线看 | 又湿又紧又大又爽a视频国产 | 欧美视频国产视频 | 91精品在线观看视频 | 欧美 日韩 国产 成人 在线 | 国产免费黄视频在线观看 | 国产成人精品久久二区二区 | 国产97免费 | 亚洲美女视频网 | 久久久久免费视频 | 亚洲欧美日韩精品一区二区 | 婷婷网址 | 黄色一级影院 | 国产精品福利av | 狠狠激情中文字幕 | 天天色天天骑天天射 | 热久久免费视频精品 | 成人在线观看网址 | 在线观看的a站 | 天天操天天透 | 人人搞人人干 | 天天综合日日夜夜 | 国产一级大片免费看 | 色婷婷狠狠五月综合天色拍 | 国产精品免费成人 | 搡bbbb搡bbb视频 | 日韩精品一区在线观看 | 不卡的av在线 | 国产精品久久久亚洲 | av在线等| 日韩av综合网站 | www.天天干 | 天天草网站 | 337p日本欧洲亚洲大胆裸体艺术 | 午夜狠狠干 | 国产成人精品在线 | 中文字幕在线观看av | 国产亚洲婷婷免费 | 亚洲九九九在线观看 | 国产69精品久久久久99尤 | www.色婷婷| 国产成人三级一区二区在线观看一 | 综合网天天 | 日韩美av在线 | 香蕉网在线播放 | 欧美一级免费黄色片 | 天堂在线视频中文网 | 国产 色| 日韩在线观看网站 | 久久99这里只有精品 | 91精品在线免费 | 久久人人爽人人爽 | 国产视频综合在线 | 日韩欧美国产视频 | 天天天天天天天操 | av官网在线 | 精品国产一二三四区 | 亚洲一区二区三区在线看 | 欧美性爽爽 | 成年人免费在线观看 | 色午夜影院| 超碰在线日本 | 人人狠狠综合久久亚洲婷 | 天天色棕合合合合合合 | 国产黄色片免费在线观看 | 久久九九久久精品 | 西西人体www444 | 一本一道久久a久久综合蜜桃 | 香蕉影视| 久草线 | 免费无遮挡动漫网站 | 园产精品久久久久久久7电影 | 中文字幕一区二区三区在线播放 | 中文字幕在线一二 | 一本一本久久aa综合精品 | 精品国产视频在线 | 欧美午夜精品久久久久久浪潮 | 免费av网站在线看 | 91久久丝袜国产露脸动漫 | 五月婷香蕉久色在线看 | 99精品免费网 | 国产精品毛片一区视频播 | 国产免码va在线观看免费 | 精品欧美在线视频 | 精品爱爱 | 婷婷资源站 | 亚洲女在线| 91视频在线 | 国产精品视频线看 | 亚洲最大成人网4388xx | 少妇搡bbbb搡bbb搡忠贞 | 顶级欧美色妇4khd | 国产精品一区二区三区在线免费观看 | 二区三区毛片 | 久久久久久欧美二区电影网 | 亚洲精品女人久久久 | 亚洲激色 | h文在线观看免费 | 超碰个人在线 | 婷婷亚洲五月 | 久久综合视频网 | 最新在线你懂的 | 国产精品中文久久久久久久 | 美女网站色在线观看 | 91精品一区二区三区蜜臀 | 亚洲黄色一级大片 | 国产成人精品一区二区三区网站观看 | 中文字幕丰满人伦在线 | 天天爱天天操天天爽 | 国产免费xvideos视频入口 | 国产精品久久久久久久久久三级 | 亚州精品国产 | 亚洲精品视频第一页 | 久久国产精品99久久久久久进口 | 中文字幕91视频 | 亚洲污视频 | 亚洲精品午夜国产va久久成人 | 天天操天天操天天操天天操天天操天天操 | 日韩一三区 | 日本高清久久久 | 日韩理论片中文字幕 | 色视频在线观看 | 97理论电影 | 久久精品一级片 | 操高跟美女 | 91av国产视频 | 天天玩天天干天天操 | 天天搞天天干天天色 | 狠狠狠色丁香婷婷综合久久五月 | 国产一级电影网 | 久久99国产精品久久99 | 国产高清成人av | 国产在线观看你懂的 | 97精品国产97久久久久久久久久久久 | 久久中文视频 | 激情 亚洲 | 国产成人精品一区二区三区福利 | 久久久久久麻豆 | 日韩精品aaa| 天天操天天干天天综合网 | 2024国产精品视频 | 色999精品| 日韩在线免费看 | 婷婷色 亚洲 | 伊人婷婷综合 | 国产精品日韩 | 在线观看福利网站 | www好男人 | 成人午夜电影免费在线观看 | 亚州黄色一级 | 91香蕉国产在线观看软件 | 日韩一区精品 | www.五月婷婷 | 在线看不卡av | 丁香婷婷久久久综合精品国产 | 欧洲亚洲激情 | 国产精品资源在线 | 99热精品在线 | 免费一级特黄毛大片 | 91av美女| 夜夜骑天天操 | 91av影视| 在线免费性生活片 | 狠狠色狠狠色终合网 | 天天激情 | 国产美女精品视频 | 久久久久这里只有精品 | 国产精品24小时在线观看 | 久久在线视频精品 | 久久99久国产精品黄毛片入口 | 久久国产精品久久精品国产演员表 | 亚洲精品国内 | 国产高清在线a视频大全 | 日本免费一二三区 | 亚洲国产片色 | 日韩高清黄色 | 久久不卡电影 | 久久中文字幕视频 | 人人狠狠综合久久亚洲婷 | 人人爽人人香蕉 | 欧美日韩国产一区二区三区在线观看 | 亚洲欧美日韩在线看 | 久久精品看 | 2023av| 国产精品18久久久 | wwwwww国产 | 丁香一区二区 | 五月综合色婷婷 | 在线视频欧美亚洲 | 久久精品国产99 | 婷婷新五月 | 久久精品爱爱视频 | 国产又粗又猛又爽又黄的视频免费 | 国产精品丝袜久久久久久久不卡 | 日日干天天插 | 在线看成人 | 激情开心站| 亚洲视频免费 | 午夜视频免费在线观看 | 亚洲精品色 | 17videosex性欧美 | 国产免费人成xvideos视频 | 日韩在线理论 | 久久久久国产免费免费 | 97成人免费 | 欧美在线久久 | 91一区啪爱嗯打偷拍欧美 | 亚洲尺码电影av久久 | 亚洲精品国产精品99久久 | 超碰在线94 | 丁香5月婷婷 | 国产成人精品一区二区三区网站观看 | 中文字幕 婷婷 | 色综合天天视频在线观看 | 日韩欧美国产激情在线播放 | 久久不射电影院 | 色婷av | 18+视频网站链接 | 天天射天天 | 亚洲精品99久久久久中文字幕 | 亚洲一二三在线 | 97视频网站| 日韩精品中文字幕在线 | 懂色av一区二区在线播放 | 国产美女精品久久久 | 99视频在线免费 | 成 人 黄 色 视频免费播放 | 最新日韩精品 | 人人讲下载 | 日韩一级片网址 | 国产一区私人高清影院 | 色欧美成人精品a∨在线观看 | 丁香久久五月 | 97电影在线 | 在线视频1卡二卡三卡 | 中文字幕电影高清在线观看 | 欧美一二三区播放 | 97超碰中文字幕 | 日本中文字幕高清 | 久久久 精品 | 欧美视频99 | 国产精品久久久久久久久久了 | 少妇bbb| 成人毛片在线观看 | 中文字幕 成人 | 97精品国产91久久久久久久 | 91精品久久久久久综合五月天 | 欧美一级性 | 免费视频91 | 免费看一及片 | 午夜影视av | 亚洲自拍自偷 | 中文字幕在线观看完整版电影 | 国产精品久久久久久影院 | 狠狠婷婷 | 97精品国产91久久久久久久 | 97福利在线观看 | 国产精品欧美一区二区三区不卡 | 欧美久久影院 | 久久久久久97三级 | 婷婷久久丁香 | 97超碰国产精品女人人人爽 | 午夜视频在线观看一区 | 激情网第四色 | 色综合久久久久综合99 | 黄色毛片大全 | 正在播放 久久 | 久久精品免视看 | 久久久免费看片 | 色综合久久久久综合体桃花网 | 国产精品美女久久久久久网站 | 日本黄色免费网站 | 久久网页| 精品视频123区在线观看 | 欧美日韩另类在线观看 | 激情图片区 | 欧美午夜性 | 亚洲 欧美日韩 国产 中文 | 日本三级在线观看中文字 | 久草视频免费在线观看 | 中文字幕 婷婷 | 97超碰站 | 美女网站视频色 | 欧美性脚交 | 福利二区视频 | 欧美亚洲另类在线视频 | 毛片网免费 | 色天天中文 | 亚洲一区 av| av一级片 | 亚洲人人网 | 91香蕉视频在线下载 | 国产成人av电影在线 | 波多野结衣亚洲一区二区 | av综合站 | 中文日韩在线视频 | 中文字幕有码在线观看 | 亚洲狠狠丁香婷婷综合久久久 | 久久久久久麻豆 | 超碰在线人人97 | 国产精品一区二区久久精品爱微奶 | 久草精品视频在线播放 | 99视频在线观看一区三区 | 中文av日韩| www.国产高清 | 免费在线看v| 99热免费在线 | 国产精品18久久久久白浆 | 免费在线激情视频 | 日韩在线视频网 | 天天操天天干天天 | 99在线精品观看 | 成人在线黄色 | 9999在线视频 | 中文字幕精品久久 | 日韩欧美视频在线 | 国产色 在线| 欧美不卡在线 | 中文字幕日韩一区二区三区不卡 | 国产精品第54页 | 国产一级大片免费看 | 亚洲一区网站 | 97电影院在线观看 | av中文天堂 | 国产原厂视频在线观看 | 激情电影影院 | 夜夜操天天 | 亚洲一区精品二人人爽久久 | ,午夜性刺激免费看视频 | 免费视频在线观看网站 | 99亚洲国产 | 亚洲精品在线看 | 免费av网站在线 | 99中文字幕视频 | 中文字幕第一页在线 | 欧美黑人猛交 | 五月天激情开心 | 18av在线视频 | 久草在线免费资源站 | 不卡视频在线看 | 三级小视频在线观看 | 国产成人久久精品77777综合 | 欧美激情精品久久久久 | 国产伦精品一区二区三区免费 | 久草电影在线观看 | 久久久国产在线视频 | 天天射天天操天天色 | 国产亚洲成人网 | 国外av在线 | 久久精品欧美一 | 久久玖| 色偷偷中文字幕 | 国产九九九九九 | 草久中文字幕 | a黄色大片 | 女人高潮特级毛片 | 日韩三级视频在线观看 | 精品久久久久久亚洲 | 色香蕉视频 | 成人黄色小说网 | 黄色软件在线观看 | 国产专区精品 | 欧美日韩免费一区二区 | 在线免费观看黄色大片 | 久久人人爽人人爽人人片 | 91在线免费公开视频 | 99精品视频在线观看播放 | 中文十次啦 | 婷婷激情综合网 | www久久com| 在线观看免费视频你懂的 | 国内一区二区视频 | 国产又粗又猛又色 | 99精品视频在线免费观看 | 国产精品久久久久久久久久久久午夜片 | 一区二区三区高清在线观看 | 波多野结衣一区三区 | 国产xx在线 | 中午字幕在线 | 一本到视频在线观看 | 日韩在线视频观看 | 国产综合精品久久 | 97在线免费| 久久久久国产一区二区三区 | avove黑丝| 91人人射 | 97超碰国产在线 | 亚洲成人资源网 | 欧美地下肉体性派对 | 亚洲精品乱码久久久久久写真 | 亚洲精品tv久久久久久久久久 | 激情丁香综合 | 人人爱天天操 | 日韩欧美一区二区在线播放 | 一区二区三区高清在线 | 久99久中文字幕在线 | 日本中文字幕在线播放 | 久草免费在线视频观看 | 日韩精品免费一区二区 | 中文字幕亚洲在线观看 | 亚洲精区二区三区四区麻豆 | 国产欧美中文字幕 | 亚洲永久精品国产 | 亚洲 欧美 变态 国产 另类 | 精品美女久久久久 | 久久综合精品国产一区二区三区 | 亚洲人天堂 | 久久久精品日本 | 蜜臀精品久久久久久蜜臀 | 日韩高清一区 | 国产精品久久人 | 97综合网 | 免费观看v片在线观看 | 国产精品不卡在线播放 | 五月婷婷综合在线视频 | 国产在线视频一区二区 | 欧美最新另类人妖 | 808电影| 日韩av视屏 | 天天操天天操天天操天天操天天操 | 国产精品男女视频 | 性色大片在线观看 | 黄在线免费看 | 亚洲九九影院 | 少妇性色午夜淫片aaaze | 亚洲好视频| 人人爽人人爽人人片av免 | 欧美日韩在线观看不卡 | 久久精品国产一区二区三区 | 中文字幕有码在线观看 | 一区二区视 | 97超视频免费观看 | 欧美日韩另类在线 | 18做爰免费视频网站 | 中文字幕亚洲不卡 | 日韩系列 | 伊人亚洲综合 | 成人一区二区在线 | 天天插天天干天天操 | 久草在线官网 | 久久免费视频6 | 精品久久一区 | 国产精品久久久久久久毛片 | 99久久99视频只有精品 | 国内精品久久久久久久影视麻豆 | av片在线看| 亚洲黄色在线播放 | 亚洲精品美女久久久 | 性色av香蕉一区二区 | 国产精品理论片在线播放 | www.亚洲黄 | 最近能播放的中文字幕 | 亚洲免费在线观看视频 | 国内视频 | 波多野结衣精品视频 | 久久免费视频6 | 久久久午夜剧场 | 久久黄色成人 | 国产高清在线一区 | 岛国av在线免费 | 日韩中文字幕91 | 香蕉久草在线 | 亚洲永久精品国产 | 狠狠的干| www.伊人网 | www黄免费 | 欧美日韩电影在线播放 | 久久精品国产一区二区电影 | 中文字幕在线高清 | 欧美一级高清片 | 国产视频精品免费 | 中文字幕第一页在线播放 | 久久精品综合 | 久久综合影视 | 国产精品一区二区三区在线播放 | 国产成人三级在线观看 | 青春草免费在线视频 | 一区 二区电影免费在线观看 | 美女视频永久黄网站免费观看国产 | 天天综合网~永久入口 | 伊人中文在线 | 手机看片 | 伊人中文网 | 日韩免费视频线观看 | 日韩精品久久久久 | 国产精品白浆视频 | 九九视频一区 | 日韩免费看片 | 蜜臀久久99精品久久久无需会员 | 午夜.dj高清免费观看视频 | 日韩美女一级片 | 亚洲国产精品电影 | 精品国产免费观看 | 久草视频在线资源站 | 欧美一级乱黄 | 亚洲精品小视频在线观看 | 欧洲av在线 | 成人免费观看电影 | 日韩欧美不卡 | 久操久| 狠狠地日| 免费能看的黄色片 | 九九国产视频 | 午夜视频在线观看一区 | 亚洲国产最新 | 亚洲欧美偷拍另类 | 国产精品久久久久久爽爽爽 | 亚洲人久久 | 四虎影视精品成人 | 毛片黄色一级 | 在线看福利av | 91成人蝌蚪 | 亚洲日本在线视频观看 | 日韩一区二区三区不卡 | 97福利在线| 91精品一区二区三区久久久久久 | www国产亚洲精品 | 久久五月精品 | 欧美激情视频一区二区三区 | 久草在线观看视频免费 | 久久9999久久免费精品国产 | 精品国产一区二区三区av性色 | 亚洲精品国产精品乱码在线观看 | 国产91精品久久久久 | 天天干一干 | 色综合久久99 | 在线观看亚洲专区 | 亚洲国产精品久久 | 天天色天天操天天爽 | 欧美激情精品久久久久久免费印度 | 欧美日韩视频一区二区三区 | 五月天婷婷在线视频 | 国内99视频| 美女免费视频一区 | 国产露脸91国语对白 | 亚洲年轻女教师毛茸茸 | 最近更新中文字幕 | 99视频在线精品国自产拍免费观看 | 久久精品视 | 久久久久看片 | 午夜精品久久久久久久99 | 免费看三片 | 国产日本高清 | 人人爽人人爽av | 四虎国产精品成人免费影视 | 亚洲va欧美 | 五月婷香蕉久色在线看 | 最新日韩在线观看视频 | 国产午夜精品久久久久久久久久 | 黄视频网站大全 | 美女免费网视频 | 麻豆免费视频网站 | 国产美女被啪进深处喷白浆视频 | 欧美日韩免费观看一区=区三区 | 色wwwww| 在线影视 一区 二区 三区 | 日本中文字幕网站 | 韩日电影在线 | 深爱激情站 | 久久草网站 | 亚洲日本欧美 | 999成人免费视频 | 天天摸天天干天天操天天射 | 欧美成人在线网站 | 久久精品1区2区 | 国产精品久久久久久影院 | 热久精品 | 99r在线精品 | 国产精品久久久久久久7电影 | 91精品国产综合久久久久久久 | aaa毛片视频 | 成人免费观看完整版电影 | 天天干天天射天天爽 | 天天干天天操天天拍 | 91精品入口 | 夜夜干夜夜| 久久久久久久久久久久电影 | 免费污片 | www.久久婷婷| 黄色国产高清 | 国内外成人在线视频 | 日韩欧美高清不卡 | 久久国产精品99精国产 | 五月天婷婷视频 | 激情五月开心 | 天天插日日操 | 久久久99国产精品免费 | av 一区二区三区四区 | 视频在线播放国产 | 激情欧美国产 | 久草在线最新免费 | 欧美日韩高清在线 | 亚洲永久精品在线 | 精品国产乱码久久久久久1区2匹 | 91九色国产在线 | 99视频网站 | 亚洲国产中文字幕在线观看 | 欧美久草在线 | 黄网站色欧美视频 | 999在线精品 | www视频免费在线观看 | 日韩欧美亚洲 | 狠狠色丁香婷婷综合久久片 | 精品亚洲免费视频 | 日本高清免费中文字幕 | 日韩特黄av | 亚洲免费永久精品国产 | 日韩精选在线 | 91秒拍国产福利一区 | 日韩激情一二三区 | 国产手机视频精品 | 精品视频中文字幕 | 亚洲精品av中文字幕在线在线 | 人人草网站| 日本三级全黄少妇三2023 | 久久一级片 | 国产视频一 | 视频在线观看入口黄最新永久免费国产 | 成人av在线播放网站 | 性色在线视频 | 国产一区二区在线观看免费 | 久草在线久草在线2 | 色a网 | 精品一区 在线 | av在线进入| 91亚洲精品乱码久久久久久蜜桃 | 香蕉蜜桃视频 | av成人在线电影 | 久久免费视频国产 | 中文字幕av免费在线观看 | 国产久草在线 | 国产一区二区三区在线免费观看 | 久久精品久久精品 | 手机av网站 | 午夜在线免费观看 | 在线观看视频你懂得 | 日av免费 | 国产系列 在线观看 | 日本在线观看一区 | 久久99在线 | 欧美精品乱码99久久影院 | 97在线视频网站 | 国产大片黄色 | 亚洲欧美激情精品一区二区 | 六月丁香激情综合色啪小说 | 国产精品一区二区久久精品爱微奶 | 久久精品福利视频 | 西西44人体做爰大胆视频 | 久久女同性恋中文字幕 | 福利片免费看 | 久草久草在线 | 国产精品一区二区精品视频免费看 | 亚洲欧美视频在线播放 | 999视频网 | 九九国产视频 | 中文字幕精品在线 | av电影中文 | 人人插人人做 | 中文字幕视频一区二区 | 久久久亚洲成人 | 国产亚洲精品久久久久动 | 九九九在线观看 | 久久人人爽人人片 | 九九热视频在线 | 三级在线国产 | 国产在线不卡精品 | 午夜在线观看一区 | 日韩精品视频免费专区在线播放 | 亚洲成人av影片 | 亚洲欧美视频在线播放 | 一区二区三区免费在线 | 日韩网站免费观看 | 婷婷四房综合激情五月 | 99免费在线| 亚洲精品tv久久久久久久久久 | 麻豆国产电影 | 国产视频在线观看一区 | 亚洲乱亚洲乱亚洲 | 欧美日韩国产一区 | 四虎在线免费 | 一本一道久久a久久精品蜜桃 | 久久蜜臀一区二区三区av | 插久久 | www.天天色.com | 麻豆视频国产精品 | 国产精品igao视频网入口 | 亚洲综合丁香 | 97精品国自产拍在线观看 | 亚洲成aⅴ人片久久青草影院 | 麻豆国产在线视频 | 久久99婷婷 | 欧美日韩一二三四区 | www.久久成人 | 亚洲成人av影片 | 欧美国产亚洲精品久久久8v | 久久国产日韩 | 91精品国产欧美一区二区成人 | 久久麻豆视频 | 亚洲免费在线播放视频 | 精品在线免费视频 | 成年人在线免费视频观看 | 97在线观看视频免费 | 日韩中文在线电影 | 亚洲黄色成人av | 91亚洲精品久久久中文字幕 | 免费成人av | 欧美一区二区三区免费看 | 国产精品一区在线播放 | 欧美精品中文在线免费观看 | 天天干天天色2020 | 欧美激情xxxx性bbbb | 亚洲欧美日韩中文在线 | 国产成人一区二 | 色九九视频 | 午夜精品久久久久久久久久久久 | 免费看一级特黄a大片 | 蜜臀91丨九色丨蝌蚪老版 | 亚洲美女精品区人人人人 | 久人人| 国产精品久久视频 | 99热这里只有精品国产首页 | 天天干天天操天天搞 | 久草视频资源 | 91传媒在线播放 | 肉色欧美久久久久久久免费看 | av在线免费网| 亚洲黄色免费在线 | 国产视频二区三区 | 人人澡人人澡人人 | 国产成年人av | www.天天操 | 国产黄色大片免费看 | 国产护士在线 | 欧美专区亚洲专区 | 69成人在线| 69国产成人综合久久精品欧美 | 视频在线观看99 | 国产中文字幕一区二区三区 | 中文亚洲欧美日韩 | 久久激情网站 | 国产专区在线播放 | 色多视频在线观看 | 在线观看免费高清视频大全追剧 | 日日婷婷夜日日天干 | 日韩精品一区二区在线观看 | 久久久久久久久久毛片 | 日本在线观看一区二区 | 欧美午夜寂寞影院 | 国产999精品久久久久久 | 午夜电影久久 | www.午夜 | 天天翘av | 亚洲一区二区三区四区精品 | 五月开心六月伊人色婷婷 | 毛片永久免费 | 在线观看 国产 | 国产黄色免费观看 | 亚洲国产成人久久 | 国产玖玖精品视频 | 午夜在线观看 | 成人在线小视频 | 五月婷婷丁香激情 | 激情图片久久 | 亚洲视频综合在线 | 国内精品中文字幕 | 欧美a影视| 五月激情五月激情 | 97色免费视频 | 丁香婷婷激情 | 丁香激情网 | 日韩欧美久久 | 久久精品电影 | 亚洲撸撸 | 欧美成人手机版 | 亚洲黄色在线播放 | 成人午夜电影网站 | 六月激情丁香 | 精品在线视频播放 | 国产精品久久久999 国产91九色视频 | 91av视频免费在线观看 | 欧美精品v国产精品v日韩精品 | 欧美人交a欧美精品 | 中文字幕在线观看一区二区三区 | a天堂在线看 | 91精品麻豆 | 超碰97中文 | 西西444www大胆无视频 | 亚洲成a人片在线观看网站口工 | 亚洲黑丝少妇 | 欧美做受69| 成人免费视频网址 | 97视频资源 | 中文字幕 国产精品 | 免费视频国产 | 久久久精品99 | 日日操夜 | 操操碰| 日韩欧美在线视频一区二区 | 成人av片在线观看 | 狠狠狠狠狠狠操 | 亚洲三级av | av久久久 | 日韩精品免费在线播放 | 国产97在线播放 | 天天艹天天干天天 | 久久久亚洲精华液 | 国产资源在线免费观看 | 久久天天躁狠狠躁亚洲综合公司 | 欧美日韩在线观看视频 | 在线超碰av | 99精品国产亚洲 | 国产日韩精品一区二区在线观看播放 | 久久99网站 | 色欧美88888久久久久久影院 | 99精品国产99久久久久久福利 | 五月天婷亚洲天综合网精品偷 | 精品久久久影院 | 亚洲精品一区二区三区新线路 | 一区二区三区免费在线观看视频 | 天天综合网久久综合网 | 欧美va天堂在线电影 | 日韩欧美视频一区二区三区 | 国产一线二线三线性视频 | 婷婷综合久久 | 国产午夜精品av一区二区 | 亚洲资源视频 | 热久精品 | 国产女人40精品一区毛片视频 | 国产精品爽爽爽 | 日本色小说视频 | 特级毛片在线免费观看 | 九九九视频精品 | 超碰在线人人 | 黄色在线视频网址 | 精品嫩模福利一区二区蜜臀 | 国产精品久久艹 | 精品国产免费av | 成人黄大片 | 亚洲精品字幕 | 免费观看丰满少妇做爰 | 亚洲久草网 | 在线看不卡av | 欧美精品第一 | 亚洲另类人人澡 | 国产乱对白刺激视频在线观看女王 | 国产精成人品免费观看 | 亚洲乱亚洲乱妇 | 成年人免费电影在线观看 | 国产白浆在线观看 | 亚洲日本欧美 | 九九热在线视频 | 午夜精品三区 | 亚洲免费在线播放视频 | 精品日韩在线一区 | 午夜精品一二三区 | 激情婷婷色 | 久久九九国产视频 | 久久毛片网站 | 美女视频黄是免费的 | 色在线免费 | 天天操天天干天天操天天干 | 久久精品亚洲综合专区 | 久久久国产99久久国产一 | 成人在线观看日韩 | 人人爱爱人人 | 91亚色视频在线观看 | 在线一区电影 | 成人黄色小说在线观看 | 99久久精品网 | 欧美做受高潮 | 性色va| 成人av电影免费在线观看 |