EOFException 的问题处理

近期工作中, 遇到了有送EOFException的抛出, 以此小节总结学习相关内容, 及如何解决问题。

问题描述

doUnZip(FileOperateUtil.java:239)] java.io.EOFException

com.tr..base.util.FileOperateUtil.doUnZip(FileOperateUtil.java:221)] java.io.EOFException
at java.util.zip.GZIPInputStream.readUByte(GZIPInputStream.java:268)
at java.util.zip.GZIPInputStream.readUShort(GZIPInputStream.java:258)
at java.util.zip.GZIPInputStream.readHeader(GZIPInputStream.java:164)
at java.util.zip.GZIPInputStream.(GZIPInputStream.java:79)
at java.util.zip.GZIPInputStream.(GZIPInputStream.java:91)
at com.tr..base.util.FileOperateUtil.doUnZip(FileOperateUtil.java:208)
at com.tr..framework.input.transformation.workflow.FileUncompressProcessor.process(FileUncompressProcessor.java:44)
at com.tr..workflow.Workflow.process(Workflow.java:50)
at com.tr..framework.input.transformation.PollingFileTask.run(PollingFileService.java:100)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
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)

应用程序运行的背景是, 从一个文件服务器上下载文件, 文件类型里面有压缩文件, 下载到本地需要解压缩。 在解压缩的过程中出现了EOFException的异常。

问题分析

首先查看出问题的代码片段:

// set the input and output stream
		InputStream input = null;
		GZIPInputStream zipInputStream = null;
		OutputStream output = null;
		try {
			input = new FileInputStream(file);
			zipInputStream = new GZIPInputStream(input);
			output = new FileOutputStream(unZipFilePath);
			byte[] data = new byte[BUFFER];
			while ((count = zipInputStream.read(data, 0, BUFFER)) != -1) {
				output.write(data, 0, count);
			}
			output.flush();
			success = true;
		} catch (FileNotFoundException e) {
			success = false;
			logger.error(ExceptionUtils.getStackTrace(e));
		} catch (IOException e) {
			success = false;
			logger.error(ExceptionUtils.getStackTrace(e));
		} finally {
			try {
				if (input != null) {
					input.close();
				}
				if (output != null) {
					output.flush();
					output.close();
				}
			} catch (IOException e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}

文件读入缓存后, 通过java.util.zip.GZIPInputStream解压缩,得到GZIPInputStream的输出流。这两个类在rt.jar里, 是Java提供的util API。

接下来查看Java API如何对这个异常及类的解析文件定义的。

1. 分析出问题的这一行源码:

at java.util.zip.GZIPInputStream.readUByte(GZIPInputStream.java:268)

    通过查看Java API的源码这个方法会抛出java.io.IOException:   

  /*
     * Reads unsigned byte.
     */
    private int readUByte(InputStream in) throws IOException {
        int b = in.read();
        if (b == -1) {
            throw new EOFException();
        }
        if (b < -1 || b > 255) {
            // Report on this.in, not argument in; see read{Header, Trailer}.
            throw new IOException(this.in.getClass().getName()
                + ".read() returned value out of range -1..255: " + b);
        }
        return b;
    }

2. 查看EOFException的类继承结构,如下图:

EOFException 的问题处理_第1张图片

由此可见EOFException是IOException的子类, 当{b == -1}时会抛出这个异常, 由此可以说明文件在开始读取时直接读到了文件尾结束的标识符, 由此可以推测,文件打包可能被破坏, 或者这是个空包。

结论

经过进一步分析发现文件被下载过程中, 上游程序的漏洞引起创建本地空压缩包引起的异常。当你用判断文件是否存在时, 这个文件是存在的。

// get the file object
		File file = new File(filePath);
		if (!file.exists()) {
			success = false;
			return success;
		}

因此只能通过判断InputStream是否为空来解决这问题。当input.available() == 0时, 说明文件已经读到末尾。因此,可以断定这是一个空文件。代码如下:

input = new FileInputStream(file);
			if(input.available() == 0){
				logger.debug("The file "+unZipFilePath+" is empty, ignore it.");
				success = false;
			}else{
				zipInputStream = new GZIPInputStream(input);
				output = new FileOutputStream(unZipFilePath);
				byte[] data = new byte[BUFFER];
				while ((count = zipInputStream.read(data, 0, BUFFER)) != -1) {
					output.write(data, 0, count);
				}
				output.flush();
				success = true;	
			}

 

你可能感兴趣的:(学习)