ZLib supports streaming decompression, which is what our PRT implementation uses. In the zlib docs, please refer to zlib.net/manual.html#struct%20z_stream_s. You would load a chunk of compressed data using a std::ifstream perhaps, into a buffer of some fixed size. Then you would set the next_in member to point at the start of this array, and the avail_in member to be the size of the array. After a call to inflate(), ZLib will decompress as much of that array as it can, leaving the amount of uncompressed bytes in the avail_in member. You would then re-fill the input buffer, and call inflate() again.
Regarding a system for working on particles in the PRT format: The simplest approach that you mention has the drawback that accessing multiple data members within the same particle will potentially cause cache misses, since the individual members are stored in very different locations. We use a system where each particle is stored as a contiguous block, and we use accessor objects to extract the individual data members of a particle relative to the start of a particle.
If you aren’t doing heavy processing (ie. multiple passes), the performance difference is probably negligible. The simpler solution is probably a lot easier to code, debug, and maintain.