key words : POI java读取Excel
java.io.IOException Unable to read entire block版本:2.5.1final
错误提示:
java.io.IOException Unable to read entire block
出这个问题具有随机性,有时候没问题,有时候将Excel里的CellType改一下好像就没问题,但也不总是这样,真是莫名其妙.
Google了一下是一个bug,重新下载src文件,将RawDataBlock.java文件的RawDataBlock(final InputStream stream)constructor覆盖:
public RawDataBlock(final InputStream stream) throws IOException
{
_data = new byte[ POIFSConstants.BIG_BLOCK_SIZE ];
int count = 0;
int totalBytesRead = 0;
while ((totalBytesRead < POIFSConstants.BIG_BLOCK_SIZE) &&
(count != -1)) {
count = stream.read(_data, totalBytesRead,
POIFSConstants.BIG_BLOCK_SIZE - totalBytesRead);
if (count != -1) {
totalBytesRead += count;
}
}
if (count == -1) {
_eof = true;
} else {
_eof = false;
}
if ((totalBytesRead != POIFSConstants.BIG_BLOCK_SIZE) && (totalBytesRead != 0)) {
String type = " byte" + ((totalBytesRead == 1) ? (""): ("s"));
throw new IOException("Unable to read entire block; " +
totalBytesRead + type + " read; expected " + POIFSConstants.BIG_BLOCK_SIZE + "bytes");
}
}
打包:
ant jar
重启app,OK!
说明:
主要问题出在 InputStream的read上,原来的实现用ReadFully方法:public static int readFully(InputStream in, byte[] b, int off, int len)
throws IOException
{
int total = 0;
for (;;) {
int got = in.read(b, off + total, len - total);
if (got < 0) {
return (total == 0) ? -1 : total;
} else {
total += got;
if (total == len)
return total;
}
}
}
InputStream的read不能确保返回的是最大字节数,但是另一个实现却可以:ByteInputStream
所以,下面的方法也可以修改这个问题:
// read entire stream into byte array:
ByteArrayOutputStream byteOS = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int count;
while (count = inputStream.read(buffer)) != -1)
byteOS.append(buffer, 0, count);
byteOS.close();
byte[] allBytes = byteOS.betByteArray();
// create workbook from array:
InputStream byteIS = new ByteArrayInputStream(allBytes);
HSSFWorkbook wb = new HSSFWorkbook(byteIS);