20180314-程式碼分享
1.單元測試簡化
/**
* 下載單個材料(成功)
* <p>
* 用例1 jzId,clId均不為空
*
* @throws Exception Exception
* @see ClController#downloadCl(HttpServletResponse, String, String, String, String, String, Integer)
*/
@Test
public void downloadCl_success() throws Exception {
File file = File.createTempFile(UUIDUtils.getUuid(), ".jpg");
InputStream is = new FileInputStream(file);
Mockito.when(downloadTreeService.downloadTree(Mockito.anyString(), Mockito.any()
, Mockito.anyString(), Mockito.anyInt())).thenReturn(is);
Mockito.doNothing().when(czrzServiceImpl).addCzrz(any(CzrzEntity.class));
this.mockMvc.perform(
post("/rest/v4/cl/F995A1849D7F4BAC853964D8E0A5D958/actions/download?" + "jzId=C7B5327BBBBD4DC6B607F412978D6939&jzMc=juanzong&clMc=yfj.docx&type=CAI_LIAO&downloadType=1"))
.andExpect(status().isOk());
IOUtils.closeQuietly(is);
boolean delete = file.delete();
if (!delete){
throw new ResourceDeletedFailedException("臨時檔案刪除失敗, pash:" + file.getAbsolutePath());
}
}
問題:
- is需要手動關閉,甚至中間拋錯流還關閉不了
- 臨時檔案需要手動刪除
修改後:
/**
* 下載單個材料(成功)
* <p>
* 用例1 jzId,clId均不為空
*
* @throws Exception Exception
* @see ClController#downloadCl(HttpServletResponse, String, String, String, String, String, Integer)
*/
@Test
public void downloadCl_success() throws Exception {
File file = File.createTempFile(UUIDUtils.getUuid(), ".jpg");
try (InputStream is = new TempFileInputStream(file.getAbsolutePath(), new FileInputStream(file))) {
Mockito.when(downloadTreeService.downloadTree(Mockito.anyString(), Mockito.any()
, Mockito.anyString(), Mockito.anyInt())).thenReturn(is);
Mockito.doNothing().when(czrzServiceImpl).addCzrz(any(CzrzEntity.class));
this.mockMvc.perform(
post("/rest/v4/cl/F995A1849D7F4BAC853964D8E0A5D958/actions/download?" + "jzId=C7B5327BBBBD4DC6B607F412978D6939&jzMc=juanzong&clMc=yfj.docx&type=CAI_LIAO&downloadType=1"))
.andExpect(status().isOk());
}
}
再次升級
``` java
/**
* 下載單個材料(成功)
* <p>
* 用例1 jzId,clId均不為空
*
* @throws Exception Exception
* @see ClController#downloadCl(HttpServletResponse, String, String, String, String, String, Integer)
*/
@Test
public void downloadCl_success() throws Exception {
File file= ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + "rotate.jpg");
@Cleanup InputStream is = new FileInputStream(file);
Mockito.when(downloadTreeService.downloadTree(Mockito.anyString(), Mockito.any()
, Mockito.anyString(), Mockito.anyInt())).thenReturn(is);
Mockito.doNothing().when(czrzServiceImpl).addCzrz(any(CzrzEntity.class));
this.mockMvc.perform(
post("/rest/v4/cl/F995A1849D7F4BAC853964D8E0A5D958/actions/download?" + "jzId=C7B5327BBBBD4DC6B607F412978D6939&jzMc=juanzong&clMc=yfj.docx&type=CAI_LIAO&downloadType=1"))
.andExpect(status().isOk());
}
2.處理邏輯錯誤
Set<String> fmlIds = new HashSet<>();
for (JzmlEntity ml : jzmlList) {
fmlIds.add(ml.getPid());
}
//將目錄集合中的二級目錄剔除,並將二級目錄按照fml分組
Map<String, List<JzmlEntity>> fmlId2SecondMlsMap = Maps.newHashMap();
Iterator<JzmlEntity> iterator = jzmlList.iterator();
while (iterator.hasNext()) {
JzmlEntity ml = iterator.next();
if (!fmlIds.contains(ml.getId())) {
List<JzmlEntity> secondMl = fmlId2SecondMlsMap.computeIfAbsent(ml.getPid(), k -> new ArrayList<>());
secondMl.add(ml);
//剔除二級目錄
iterator.remove();
}
}
場景
此處要實現的效果,是通過程式碼將一級和二級目錄分開。程式碼完成後測試,一級目錄和二級目錄同時傳入時一切正常。但是,提測前只傳入一級目錄,也被剔除了。
問題
if中的程式碼塊!fmlIds.contains(ml.getId())
翻譯過來“是不屬於卷和一級目錄”,此處屬於邏輯混亂導致。
3.堆記憶體溢位
pdf檔案拼接,測試200+檔案發現堆記憶體溢位
@Slf4j
public class PdfCopyMerger {
public static void main(String[] args) {
String pdfPath = "F:\\test.pdf";
String pdfMergePath = "F:\\test-merge2.pdf";
try(FileOutputStream fileOutputStream = new leOutputStream(pdfMergePath)){
Document document = new Document();
PdfCopy pdfCopy = new PdfCopy(document, fileOutputStream);
document.open();
int num = 500;
for(int i=0; i< num; i++) {
System.out.println(i);
FileInputStream stream = new FileInputStream(pdfPath);
PdfReader pdfReader = new PdfReader(stream);
pdfCopy.addDocument(pdfReader);
IOUtils.closeQuietly(stream);
}
document.close();
} catch(FileNotFoundException e) {
log.error("file not found", e);
} catch (DocumentException e) {
log.error("已存在一個writer繫結document,不允許多個", e);
} catch (IOException e) {
log.error("io讀寫異常", e);
} catch(Exception e) {
log.error("", e);
}
}
}
日誌
Exception in thread "RMI TCP Connection(idle)" java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.lang.Thread.getName(Thread.java:1135)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:677)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3236)
at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153)
at com.itextpdf.text.io.StreamUtil.inputStreamToArray(StreamUtil.java:73)
at com.itextpdf.text.io.RandomAccessSourceFactory.createSource(RandomAccessSourceFactory.java:145)
at com.itextpdf.text.pdf.PdfReader.<init>(PdfReader.java:411)
at com.itextpdf.text.pdf.PdfReader.<init>(PdfReader.java:431)
at com.thunisoft.dzjz.server.PdfCopyMerger.main(PdfCopyMerger.java:34)
問題定位
圖中框定的數量會是n(pdf個數)*m(pdf單頁的屬性),也就是說你合併的數量越多記憶體空間佔用越大
改後
public class PdfMerger {
/**
* 實現pdf拼接
* @param args
*/
public static void main(String[] args) throws IOException, DocumentException {
long startTime = System.currentTimeMillis();
String pdfPath = "C:\\Users\\liull\\Downloads\\test.pdf";
String pdfMergePath = "C:\\Users\\liull\\Downloads\\test-merge2.pdf";
int n = 1000;
Document document = new Document();
FileOutputStream fileOut = new FileOutputStream(pdfMergePath);
PdfWriter pdfWriter = PdfWriter.getInstance(document, fileOut);
document.open();
PdfContentByte pdfContent = pdfWriter.getDirectContent();
for(int i=0; i< n; i++) {
System.out.println(i);
InputStream in = new FileInputStream(pdfPath);
PdfReader pdfReader = new PdfReader(in);
int count = pdfReader.getNumberOfPages();
for(int num = 0; num < count; ) {
document.newPage();
PdfImportedPage pdfImportedPage = pdfWriter.getImportedPage(pdfReader, ++num);
pdfContent.addTemplate(pdfImportedPage, 0,0);
pdfWriter.flush();
}
pdfWriter.freeReader(pdfReader);
IOUtils.closeQuietly(in);
pdfReader.close();
}
document.close();
long end = System.currentTimeMillis();
System.out.println(end-startTime);
}
}
為啥用它
PDFWriter其實快取的只有每次的PdfReader所有pdfImportedPage(template),在pdfWriter.freeReader中將快取的內容重新整理至OutputStream中。
引用
第三個例子結論引用麗利姐內網發的帖子,求頂:
http://artery.thunisoft.com/form/5f31836588723b4adbe808c2d4434c1a/insert?id=ba962a412f3647f6b8cd6c7295ad7b85
相關文章
- 分享個程式碼
- HashTable實現程式碼分享
- 直播系統程式碼,小程式全域性分享和頁面分享
- 520專屬Python程式碼分享Python
- 分享一個canvas程式碼2Canvas
- 分享一段牛逼程式碼
- 分享前端開發常用程式碼片段前端
- 分享一個奇怪得程式碼寫法
- Jquery實現的高亮效果程式碼分享jQuery
- 分享 程式碼大全 節選 -- 程式設計師的習慣程式設計師
- Visual Studio模板程式碼註釋小技巧分享
- 好程式設計師web前端分享css初始化程式碼程式設計師Web前端CSS
- 小程式獲取帶有分享者資訊的小程式碼
- OpenAI ChatGPT API介面免費測試程式碼分享OpenAIChatGPTAPI
- 例項程式碼分享Python實現Linux監控PythonLinux
- 百度分享程式碼已升級到2.0
- WIN10UI—實現思路分享及程式碼Win10UI
- 分享Flask電子書PDF及程式碼+資料Flask
- 免費404頁面程式碼分享 404錯誤頁面原始碼原始碼
- 有意思的JavaScript程式碼寫法【持續更新,歡迎留言分享有趣程式碼】JavaScript
- html網頁中如何實現居中效果(程式碼分享)HTML網頁
- 淺析Linux中伺服器程式碼部署篇(分享)Linux伺服器
- Java培訓分享5個常用Java程式碼混淆器Java
- 分享一個域名ICP備案接入檢測程式碼
- 程式碼分享:體現js靈活性的def.jsJS
- 使用 implode.io 記錄分享你的程式碼片段
- 小程式入門到實戰(二)--案例原始碼分享原始碼
- 小程式分享
- 進行了1000多次程式碼評審的經驗分享 - DEVdev
- 分享一段Android許可權設定的程式碼Android
- 微信域名檢測實現機制與程式碼分享
- Python實戰專案:打乒乓(原始碼分享)(文章較短,直接上程式碼)Python原始碼
- 好程式設計師web前端分享在HTML中使用JavaScript例項程式碼程式設計師Web前端HTMLJavaScript
- 【程式碼修煉系列分享】改掉這些壞習慣,還怕寫不出健壯的程式碼?(一)
- 【程式碼修煉系列分享】改掉這些壞習慣,還怕寫不出健壯的程式碼?(二)
- Linux指令碼分享Linux指令碼
- 【深度學習】TensorFlow實現線性迴歸,程式碼演示。全md文件筆記(程式碼文件已分享)深度學習筆記
- 分享二智慧合約自動檢測工具程式碼介紹