关闭流时,抛出异常:java.io.IOException: Stream Closed

首先,这个异常大部分原因是因为关闭流的顺序导致的,下面看一下官方API的描述

void close()
           throws IOException
    Closes this stream and releases any system resources associated with it. If the stream is already closed then invoking this method has no effect.
    Throws:
        IOException - if an I/O error occurs

很关键的一点就是:关闭该流并释放与之关联的所有资源。
所以,一般情况下,关闭流都讲究:先打开的后关闭,后打开的先关闭。例如处理流a依赖节点流b,应该先关闭处理流a,再关闭节点流b。
另外,在关闭流的写法上,一般建议加上空判断

if(a!=null) a.close;
if(b!=null) b.close;

然而,我还是遇到了一个神奇的场景。

public static void splitExistFile() {
		// 文档路径
		String path = "D:\\Personality\\pdf\\";
		// 文件名
		String pdfFileName = "test.pdf";
		// 每个文件最大页数
		int filePageSize = 2;
		// 待拆分文件的总页数
		int totalPage;
		// 拆分后的文件数量
		int splitFileNum;
		int pageIndex = 1;
		PdfReader reader = null;
		try {
			String orignName = pdfFileName.split("\\.")[0];
			reader = new PdfReader(path + pdfFileName);
			totalPage = reader.getNumberOfPages();
			splitFileNum = totalPage % filePageSize == 0 ? totalPage / filePageSize : totalPage / filePageSize + 1;
			for (int i = 0; i < splitFileNum; i++) {
				String newFileName = path + orignName + "_" + (i + 1) + ".pdf";
				// 新建一个PDF文件
				Document document = null;
				PdfWriter writer = null;
				try {
					document = new Document();
					writer = PdfWriter.getInstance(document, new FileOutputStream(newFileName));
					document.open();
					PdfContentByte pdfContentByte = writer.getDirectContent();
					for (int j = 0; j < filePageSize; j++) {
						document.newPage();
						pdfContentByte.addTemplate(writer.getImportedPage(reader, pageIndex), 0, 0);
						pageIndex ++;
						if (pageIndex > totalPage)
							break;

					}
				}  catch (IOException e) {
					e.printStackTrace();
				} catch (DocumentException e) {
					e.printStackTrace();
				}catch (Exception e) {
					e.printStackTrace();
				}finally {
					try {
					if (writer != null)
						writer.close();
					}catch (Exception e) {
						e.printStackTrace();
						}
					if (document != null)
						document.close();
				}			
			}
		} catch (IOException e1) {
			e1.printStackTrace();
		} finally {
			if(reader!=null) reader.close();
		}

	}

上面代码大概的逻辑就是将一个pdf文件,根据需求拆分成多个pdf文件,在关闭writer时,按照上述写法就会报错,必须先关闭document,在关闭writer。具体的原因算不上特别清楚,虽然看过了源码。document关闭的其实是文件的监听状态,writer关闭的是io流,writer创建在document之后,甚至说对document对象有依赖关系,但是如果先关闭此对象,在循环内部有一个输出流刷新的动作,然后再关闭,第二次执行时,刷新动作就会抛出异常,因为流已经在第一次循环后关闭掉了。这方面有研究的朋友欢迎交流交流~

你可能感兴趣的:(java,pdf)