All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scalatra.util.io.package.scala Maven / Gradle / Ivy

package org.scalatra.util

import java.io._
import java.nio.channels.Channels

import scala.annotation.tailrec

/**
 * A collection of I/O utility methods.
 */
package object io {

  /**
   * Executes a block with a closeable resource, and closes it after the block runs
   *
   * @tparam A the return type of the block
   * @tparam B the closeable resource type
   * @param closeable the closeable resource
   * @param f the block
   */
  def using[A, B <: AutoCloseable](closeable: B)(f: B => A): A = {
    try {
      f(closeable)
    } finally {
      if (closeable != null) {
        closeable.close()
      }
    }
  }

  /**
   * Copies the input stream to the output stream.
   *
   * @param in the input stream to read.  The InputStream will be closed, unlike
   * commons-io's version.
   * @param out the output stream to write
   * @param bufferSize the size of buffer to use for each read
   */
  def copy(in: InputStream, out: OutputStream, bufferSize: Int = 4096): Unit = {
    using(in) { in =>
      val buf = new Array[Byte](bufferSize)
      @tailrec
      def loop(): Unit = {
        val n = in.read(buf)
        if (n >= 0) {
          out.write(buf, 0, n)
          loop()
        }
      }
      loop()
    }
  }

  def zeroCopy(in: FileInputStream, out: OutputStream): Unit = {
    using(in.getChannel) {
      ch =>
        var start = 0L
        while (start < ch.size) {
          start += ch.transferTo(start, ch.size, Channels.newChannel(out))
        }
    }
  }

  def readBytes(in: InputStream): Array[Byte] = {
    val out = new ByteArrayOutputStream()
    copy(in, out)

    out.toByteArray
  }

  /**
   * Creates a temp file, passes it to a block, and removes the temp file on the block's completion.
   *
   * @tparam A the return type of the block
   * @param content The content of the file
   * @param prefix The prefix of the temp file; must be at least three characters long
   * @param suffix The suffix of the temp file
   * @param directory The directory of the temp file; a system dependent temp directory if None
   * @param f the block
   * @return the result of f
   */
  def withTempFile[A](
    content: String,
    prefix: String = "scalatra",
    suffix: String = ".tmp",
    directory: Option[File] = None)(f: File => A): A = {
    val tmp = File.createTempFile(prefix, suffix, directory.orNull)
    try {
      using(new BufferedWriter(new FileWriter(tmp))) { out =>
        out.write(content)
        out.flush()
      }
      f(tmp)
    } finally {
      tmp.delete()
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy