I think the reason ZipInputStream works and ZipFile does not is because of the two different ways that zip files are read. The ZipFile constructor attempts to read the ZipFile's table of contents, which is written to the end of the file. If it can't read the TOC, it throws a ZipException (with almost no helpful info contained therein), which I think is what you're seeing. ZipInputStream, however, reads the entries out of the zip file sequentially starting at the beginning of the file, so it seems more robust in this case.
This is all very poorly documented and I've run into similar problems myself using ZipFile. Both methods of reading from a zip file are valid, but you'd think the API docs would mention the implications of the random access/TOC method of reading through constructor versus reading through a ZipInputStream.