360 * Closing this ZIP file will, in turn, close all input streams that
361 * have been returned by invocations of this method.
362 *
363 * @param entry the zip file entry
364 * @return the input stream for reading the contents of the specified
365 * zip file entry.
366 * @throws ZipException if a ZIP format error has occurred
367 * @throws IOException if an I/O error has occurred
368 * @throws IllegalStateException if the zip file has been closed
369 */
370 public InputStream getInputStream(ZipEntry entry) throws IOException {
371 Objects.requireNonNull(entry, "entry");
372 int pos = -1;
373 ZipFileInputStream in;
374 Source zsrc = res.zsrc;
375 Set<InputStream> istreams = res.istreams;
376 synchronized (this) {
377 ensureOpen();
378 if (Objects.equals(lastEntryName, entry.name)) {
379 pos = lastEntryPos;
380 } else if (!zc.isUTF8() && (entry.flag & EFS) != 0) {
381 pos = zsrc.getEntryPos(zc.getBytesUTF8(entry.name), false);
382 } else {
383 pos = zsrc.getEntryPos(zc.getBytes(entry.name), false);
384 }
385 if (pos == -1) {
386 return null;
387 }
388 in = new ZipFileInputStream(zsrc.cen, pos);
389 switch (CENHOW(zsrc.cen, pos)) {
390 case STORED:
391 synchronized (istreams) {
392 istreams.add(in);
393 }
394 return in;
395 case DEFLATED:
396 // Inflater likes a bit of slack
397 // MORE: Compute good size for inflater stream:
398 long size = CENLEN(zsrc.cen, pos) + 2;
399 if (size > 65536) {
400 size = 8192;
401 }
538
539 /**
540 * Returns an enumeration of the ZIP file entries.
541 * @return an enumeration of the ZIP file entries
542 * @throws IllegalStateException if the zip file has been closed
543 */
544 public Enumeration<? extends ZipEntry> entries() {
545 synchronized (this) {
546 ensureOpen();
547 return new ZipEntryIterator<ZipEntry>(res.zsrc.total, ZipEntry::new);
548 }
549 }
550
551 private Enumeration<JarEntry> entries(Function<String, JarEntry> func) {
552 synchronized (this) {
553 ensureOpen();
554 return new ZipEntryIterator<JarEntry>(res.zsrc.total, func);
555 }
556 }
557
558 private class EntrySpliterator<T> extends Spliterators.AbstractSpliterator<T> {
559 private int index;
560 private final int fence;
561 private final IntFunction<T> gen;
562
563 EntrySpliterator(int index, int fence, IntFunction<T> gen) {
564 super((long)fence,
565 Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.IMMUTABLE |
566 Spliterator.NONNULL);
567 this.index = index;
568 this.fence = fence;
569 this.gen = gen;
570 }
571
572 @Override
573 public boolean tryAdvance(Consumer<? super T> action) {
574 if (action == null)
575 throw new NullPointerException();
576 if (index >= 0 && index < fence) {
577 synchronized (ZipFile.this) {
589 *
590 * Entries appear in the {@code Stream} in the order they appear in
591 * the central directory of the ZIP file.
592 *
593 * @return an ordered {@code Stream} of entries in this ZIP file
594 * @throws IllegalStateException if the zip file has been closed
595 * @since 1.8
596 */
597 public Stream<? extends ZipEntry> stream() {
598 synchronized (this) {
599 ensureOpen();
600 return StreamSupport.stream(new EntrySpliterator<>(0, res.zsrc.total,
601 pos -> getZipEntry(null, null, pos, ZipEntry::new)), false);
602 }
603 }
604
605 private String getEntryName(int pos) {
606 byte[] cen = res.zsrc.cen;
607 int nlen = CENNAM(cen, pos);
608 if (!zc.isUTF8() && (CENFLG(cen, pos) & EFS) != 0) {
609 return zc.toStringUTF8(cen, pos + CENHDR, nlen);
610 } else {
611 return zc.toString(cen, pos + CENHDR, nlen);
612 }
613 }
614
615 /*
616 * Returns an ordered {@code Stream} over the zip file entry names.
617 *
618 * Entry names appear in the {@code Stream} in the order they appear in
619 * the central directory of the ZIP file.
620 *
621 * @return an ordered {@code Stream} of entry names in this zip file
622 * @throws IllegalStateException if the zip file has been closed
623 * @since 10
624 */
625 private Stream<String> entryNameStream() {
626 synchronized (this) {
627 ensureOpen();
628 return StreamSupport.stream(
629 new EntrySpliterator<>(0, res.zsrc.total, this::getEntryName), false);
649 }
650 }
651
652 private String lastEntryName;
653 private int lastEntryPos;
654
655 /* Checks ensureOpen() before invoke this method */
656 private ZipEntry getZipEntry(String name, byte[] bname, int pos,
657 Function<String, ? extends ZipEntry> func) {
658 byte[] cen = res.zsrc.cen;
659 int nlen = CENNAM(cen, pos);
660 int elen = CENEXT(cen, pos);
661 int clen = CENCOM(cen, pos);
662 int flag = CENFLG(cen, pos);
663 if (name == null || bname.length != nlen) {
664 // to use the entry name stored in cen, if the passed in name is
665 // (1) null, invoked from iterator, or
666 // (2) not equal to the name stored, a slash is appended during
667 // getEntryPos() search.
668 if (!zc.isUTF8() && (flag & EFS) != 0) {
669 name = zc.toStringUTF8(cen, pos + CENHDR, nlen);
670 } else {
671 name = zc.toString(cen, pos + CENHDR, nlen);
672 }
673 }
674 ZipEntry e = func.apply(name); //ZipEntry e = new ZipEntry(name);
675 e.flag = flag;
676 e.xdostime = CENTIM(cen, pos);
677 e.crc = CENCRC(cen, pos);
678 e.size = CENLEN(cen, pos);
679 e.csize = CENSIZ(cen, pos);
680 e.method = CENHOW(cen, pos);
681 if (elen != 0) {
682 int start = pos + CENHDR + nlen;
683 e.setExtra0(Arrays.copyOfRange(cen, start, start + elen), true);
684 }
685 if (clen != 0) {
686 int start = pos + CENHDR + nlen + elen;
687 if (!zc.isUTF8() && (flag & EFS) != 0) {
688 e.comment = zc.toStringUTF8(cen, start, clen);
689 } else {
690 e.comment = zc.toString(cen, start, clen);
691 }
692 }
693 lastEntryName = e.name;
694 lastEntryPos = pos;
695 return e;
696 }
697
698 /**
699 * Returns the number of entries in the ZIP file.
700 *
701 * @return the number of entries in the ZIP file
702 * @throws IllegalStateException if the zip file has been closed
703 */
704 public int size() {
705 synchronized (this) {
706 ensureOpen();
707 return res.zsrc.total;
708 }
|
360 * Closing this ZIP file will, in turn, close all input streams that
361 * have been returned by invocations of this method.
362 *
363 * @param entry the zip file entry
364 * @return the input stream for reading the contents of the specified
365 * zip file entry.
366 * @throws ZipException if a ZIP format error has occurred
367 * @throws IOException if an I/O error has occurred
368 * @throws IllegalStateException if the zip file has been closed
369 */
370 public InputStream getInputStream(ZipEntry entry) throws IOException {
371 Objects.requireNonNull(entry, "entry");
372 int pos = -1;
373 ZipFileInputStream in;
374 Source zsrc = res.zsrc;
375 Set<InputStream> istreams = res.istreams;
376 synchronized (this) {
377 ensureOpen();
378 if (Objects.equals(lastEntryName, entry.name)) {
379 pos = lastEntryPos;
380 } else if (zc.isUTF8() || (entry.flag & EFS) != 0) {
381 pos = zsrc.getEntryPos(ZipCoder.getBytesUTF8(entry.name), false);
382 } else {
383 pos = zsrc.getEntryPos(zc.getBytes(entry.name), false);
384 }
385 if (pos == -1) {
386 return null;
387 }
388 in = new ZipFileInputStream(zsrc.cen, pos);
389 switch (CENHOW(zsrc.cen, pos)) {
390 case STORED:
391 synchronized (istreams) {
392 istreams.add(in);
393 }
394 return in;
395 case DEFLATED:
396 // Inflater likes a bit of slack
397 // MORE: Compute good size for inflater stream:
398 long size = CENLEN(zsrc.cen, pos) + 2;
399 if (size > 65536) {
400 size = 8192;
401 }
538
539 /**
540 * Returns an enumeration of the ZIP file entries.
541 * @return an enumeration of the ZIP file entries
542 * @throws IllegalStateException if the zip file has been closed
543 */
544 public Enumeration<? extends ZipEntry> entries() {
545 synchronized (this) {
546 ensureOpen();
547 return new ZipEntryIterator<ZipEntry>(res.zsrc.total, ZipEntry::new);
548 }
549 }
550
551 private Enumeration<JarEntry> entries(Function<String, JarEntry> func) {
552 synchronized (this) {
553 ensureOpen();
554 return new ZipEntryIterator<JarEntry>(res.zsrc.total, func);
555 }
556 }
557
558 private static class MartinSpliterator extends Spliterators.AbstractIntSpliterator {
559 private int index;
560 private final @Stable int fence;
561 //private final @Stable byte[] cen;
562 private final @Stable int[] entries;
563
564 MartinSpliterator(int fence, int[] entries) {
565 super(fence, Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.IMMUTABLE);
566 this.index = 0;
567 this.fence = fence;
568 this.entries = entries;
569 }
570
571 @Override
572 public boolean tryAdvance(java.util.function.IntConsumer action) {
573 if (action == null) throw new NullPointerException();
574 //if (closeRequested) throw new IllegalStateException("zip file closed");
575 if (index >= fence)
576 return false;
577 action.accept(entries[(index++ * 3) + 2]);
578 return true;
579 }
580 }
581
582 private Stream<String> martinNames() {
583 final byte[] cen;
584 final java.util.stream.IntStream intStream;
585 synchronized (this) {
586 ensureOpen();
587 cen = res.zsrc.cen;
588 intStream = StreamSupport.intStream(
589 new MartinSpliterator(res.zsrc.total, res.zsrc.entries),
590 false);
591 }
592 return (zc.isUTF8())
593 ? intStream.mapToObj(i -> martinNameUTF8(zc, cen, i))
594 : intStream.mapToObj(i -> martinName(zc, cen, i));
595 }
596
597 private static String martinNameUTF8(ZipCoder zc, byte[] cen, int pos) {
598 return ZipCoder.toStringUTF8(cen, pos + CENHDR, CENNAM(cen, pos));
599 }
600
601 private static String martinName(ZipCoder zc, byte[] cen, int pos) {
602 int nlen = CENNAM(cen, pos);
603 return ((CENFLG(cen, pos) & EFS) != 0)
604 ? ZipCoder.toStringUTF8(cen, pos + CENHDR, nlen)
605 : zc.toString(cen, pos + CENHDR, nlen);
606 }
607
608 private class EntrySpliterator<T> extends Spliterators.AbstractSpliterator<T> {
609 private int index;
610 private final int fence;
611 private final IntFunction<T> gen;
612
613 EntrySpliterator(int index, int fence, IntFunction<T> gen) {
614 super((long)fence,
615 Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.IMMUTABLE |
616 Spliterator.NONNULL);
617 this.index = index;
618 this.fence = fence;
619 this.gen = gen;
620 }
621
622 @Override
623 public boolean tryAdvance(Consumer<? super T> action) {
624 if (action == null)
625 throw new NullPointerException();
626 if (index >= 0 && index < fence) {
627 synchronized (ZipFile.this) {
639 *
640 * Entries appear in the {@code Stream} in the order they appear in
641 * the central directory of the ZIP file.
642 *
643 * @return an ordered {@code Stream} of entries in this ZIP file
644 * @throws IllegalStateException if the zip file has been closed
645 * @since 1.8
646 */
647 public Stream<? extends ZipEntry> stream() {
648 synchronized (this) {
649 ensureOpen();
650 return StreamSupport.stream(new EntrySpliterator<>(0, res.zsrc.total,
651 pos -> getZipEntry(null, null, pos, ZipEntry::new)), false);
652 }
653 }
654
655 private String getEntryName(int pos) {
656 byte[] cen = res.zsrc.cen;
657 int nlen = CENNAM(cen, pos);
658 if (!zc.isUTF8() && (CENFLG(cen, pos) & EFS) != 0) {
659 return ZipCoder.toStringUTF8(cen, pos + CENHDR, nlen);
660 } else {
661 return zc.toString(cen, pos + CENHDR, nlen);
662 }
663 }
664
665 /*
666 * Returns an ordered {@code Stream} over the zip file entry names.
667 *
668 * Entry names appear in the {@code Stream} in the order they appear in
669 * the central directory of the ZIP file.
670 *
671 * @return an ordered {@code Stream} of entry names in this zip file
672 * @throws IllegalStateException if the zip file has been closed
673 * @since 10
674 */
675 private Stream<String> entryNameStream() {
676 synchronized (this) {
677 ensureOpen();
678 return StreamSupport.stream(
679 new EntrySpliterator<>(0, res.zsrc.total, this::getEntryName), false);
699 }
700 }
701
702 private String lastEntryName;
703 private int lastEntryPos;
704
705 /* Checks ensureOpen() before invoke this method */
706 private ZipEntry getZipEntry(String name, byte[] bname, int pos,
707 Function<String, ? extends ZipEntry> func) {
708 byte[] cen = res.zsrc.cen;
709 int nlen = CENNAM(cen, pos);
710 int elen = CENEXT(cen, pos);
711 int clen = CENCOM(cen, pos);
712 int flag = CENFLG(cen, pos);
713 if (name == null || bname.length != nlen) {
714 // to use the entry name stored in cen, if the passed in name is
715 // (1) null, invoked from iterator, or
716 // (2) not equal to the name stored, a slash is appended during
717 // getEntryPos() search.
718 if (!zc.isUTF8() && (flag & EFS) != 0) {
719 name = ZipCoder.toStringUTF8(cen, pos + CENHDR, nlen);
720 } else {
721 name = zc.toString(cen, pos + CENHDR, nlen);
722 }
723 }
724 ZipEntry e = func.apply(name); //ZipEntry e = new ZipEntry(name);
725 e.flag = flag;
726 e.xdostime = CENTIM(cen, pos);
727 e.crc = CENCRC(cen, pos);
728 e.size = CENLEN(cen, pos);
729 e.csize = CENSIZ(cen, pos);
730 e.method = CENHOW(cen, pos);
731 if (elen != 0) {
732 int start = pos + CENHDR + nlen;
733 e.setExtra0(Arrays.copyOfRange(cen, start, start + elen), true);
734 }
735 if (clen != 0) {
736 int start = pos + CENHDR + nlen + elen;
737 if (!zc.isUTF8() && (flag & EFS) != 0) {
738 e.comment = ZipCoder.toStringUTF8(cen, start, clen);
739 } else {
740 e.comment = zc.toString(cen, start, clen);
741 }
742 }
743 lastEntryName = e.name;
744 lastEntryPos = pos;
745 return e;
746 }
747
748 /**
749 * Returns the number of entries in the ZIP file.
750 *
751 * @return the number of entries in the ZIP file
752 * @throws IllegalStateException if the zip file has been closed
753 */
754 public int size() {
755 synchronized (this) {
756 ensureOpen();
757 return res.zsrc.total;
758 }
|