Java >> Java-zelfstudie >  >> Java

Kotlin gzip decomprimeren mislukt

Ik probeer mijn java gzip uncompress code te vereenvoudigen tot kotlin. Maar nadat ik het had veranderd, was het kapot.

Hier is de Java-code

  public static byte[] uncompress(byte[] compressedBytes) {
    if (null == compressedBytes || compressedBytes.length == 0) {
      return null;
    }

    ByteArrayOutputStream out = null;
    ByteArrayInputStream in = null;
    GZIPInputStream gzipInputStream = null;

    try {
      out = new ByteArrayOutputStream();
      in = new ByteArrayInputStream(compressedBytes);
      gzipInputStream = new GZIPInputStream(in);
      byte[] buffer = new byte[256];
      int n = 0;

      while ((n = gzipInputStream.read(buffer)) >= 0) {
        out.write(buffer, 0, n);
      }

      return out.toByteArray();
    } catch (IOException ignore) {
    } finally {
      CloseableUtils.closeQuietly(gzipInputStream);
      CloseableUtils.closeQuietly(in);
      CloseableUtils.closeQuietly(out);
    }

    return null;
  }

Dit is mijn kotlin-code.

  payload = GZIPInputStream(payload.inputStream())
      .bufferedReader()
      .use { it.readText() }
      .toByteArray()

En ik kreeg deze fout.

com.google.protobuf.nano.InvalidProtocolBufferNanoException: While parsing a protocol message, the input ended unexpectedly in the middle of a field.  This could mean either than the input has been truncated or that an embedded message misreported its own length.

Het lijkt erop dat het decompressieproces werd onderbroken door de lezer?

Antwoord

De readText (charset:Charset =Charsets.UTF_8) decodeert de bytes in UTF-8-tekenset, daarom staat er "Dit zou kunnen betekenen dat de invoer is afgekapt", het heeft waarschijnlijk geprobeerd 8-bits om te zetten in een Char en bouw er een string van.

Gebruik de readBytes() om ByteArray . te krijgen wat hetzelfde wordt weergegeven als byte[] op het JVM-platform.

Voorbeeld:

GZIPInputStream(payload.inputStream())
      .bufferedReader()
      .use { it.readBytes() }

Bewerken:

Voor het lezen van bytes moet u de Reader . niet gebruiken , het is bedoeld voor het lezen van de tekst in UTF-8-indeling zoals gedefinieerd in de Kotlin's InputStream.bufferedReader :

public inline fun InputStream.bufferedReader(charset: Charset = Charsets.UTF_8): BufferedReader = reader(charset).buffered()

De InputStream.readBytes() leest de bytes zelf in een buffer van 8KB.

public fun InputStream.readBytes(): ByteArray {
    val buffer = ByteArrayOutputStream(maxOf(DEFAULT_BUFFER_SIZE, this.available()))
    copyTo(buffer)
    return buffer.toByteArray()
}
// This copies with 8KB buffer automatically
// DEFAULT_BUFFER_SIZE = 8 * 1024
public fun InputStream.copyTo(out: OutputStream, bufferSize: Int = DEFAULT_BUFFER_SIZE): Long {
    var bytesCopied: Long = 0
    val buffer = ByteArray(bufferSize)
    var bytes = read(buffer)
    while (bytes >= 0) {
        out.write(buffer, 0, bytes)
        bytesCopied += bytes
        bytes = read(buffer)
    }
    return bytesCopied
}

Dus je hoeft alleen maar te doen:

GZIPInputStream(payload.inputStream()).use { it.readBytes() }

Java-tag