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

scalax.file.FileOps.scala Maven / Gradle / Ivy

/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2009-2010, Jesse Eichar          **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

package scalax.file

import java.io.{
    InputStream, OutputStream
}
import java.nio.channels.{
    ByteChannel, FileChannel
}
import scalax.io._
import processing.SeekableProcessor
import scalax.io.managed._
import scala.collection.Traversable
import scalax.io.StandardOpenOption._
import scalax.io.Resource._
import scalax.io.{Codec, SeekableByteChannel, OpenOption, Seekable, LongTraversable}
import java.nio.ByteBuffer

/**
 * An object for reading and writing files.  FileOps provides
 * access to Channels and streams as well as providing methods for
 * performing simple tasks on files easily.
 * 

* Obtaining a FileOps from a object does not open a * file execution of methods will open a file. Thus it is important * to handle NotFileException and FileNotFoundException. Depending * on the method one or both exceptions must be handled. *

* Examples of exception handling: *


 *  try {
 *   file.lines flatMap _.split(":")
 *  } catch {
 *   case FileNotFoundException => fail
 *   case NotFileException => fail
 *  }
 * 
* or using the Exceptions object *

 * import scala.util.control.Exceptions
 * val catcher = catching(classOf[NotFileException], classOf[FileNotFoundException])
 *
 * catcher {
 *   file.lines flatMap _.split(":")
 * }
 * 
* * The API into 3 main sections *

*
    *
  • Resources - methods for obtaining ManagedResources of input/output * streams and byte/file channel.
  • *
  • Direct Operations - methods for directly obtaining or writing * the contents of the file.
  • *
  • Batch Operations - methods for performing several actions * on the file in sequence. *

    * open() attempts to perform all actions using the * open channel in order to improve the performance * of the operations. *

    * lock() performs all the actions using the same channel *

    *

  • *
* * * @author Jesse Eichar * @since 1.0 */ abstract class FileOps extends Seekable { self : Path => /** * Obtains an input stream resource for reading from the file * * The Resource will be configured with the associated fileSystem's ResourceContext */ def inputStream(): InputStreamResource[InputStream] /** * Obtains an OutputStreamResource for writing to the file * * The Resource will be configured with the associated fileSystem's ResourceContext * * All {@link OpenOption} can be used except Read which will be ignored if present * * @param openOptions * the options that define how the file is opened when using the stream * The Write option is implicitly added to the set of options * Default is write/create/truncate */ def outputStream(openOptions:OpenOption*) : OutputStreamResource[OutputStream] /** * Obtains a ByteChannel for read/write access to the file. If no OpenOptions are * specified the underlying file will be opened with read/write/create/truncate options. * * The Resource will be configured with the associated fileSystem's ResourceContext * * All {@link OpenOption} can be used * * @param openOptions * the options that define how the file is opened when using the stream * Default is options only */ def channel(openOptions:OpenOption*): SeekableByteChannelResource[SeekableByteChannel] /** * Obtains a FileChannel for read/write access to the file. Not all filesystems * can support FileChannels therefore None will be returned if the filesystem * does not support FileChannels. * If no OpenOptions are specified the underlying file will be * opened with read/write/create/truncate options * * All {@link OpenOption} can be used * * The Resource will be configured with the associated fileSystem's ResourceContext * * @param openOptions * the options that define how the file is opened when using the stream * Default is read/write/create/truncate */ def fileChannel(openOptions:OpenOption*): Option[SeekableByteChannelResource[SeekableByteChannel]] /** * Runs several operations as efficiently as possible. If the filesystem * permits random access then the same channel will be used to perform all operations. *

* Note: only the direct file operations (bytes,lines,write,patch etc...) * can be used and expected to use the same resource. The resource methods * all created new streams. *

* Note: not all file systems support this, if not then at worst the performance * is the same as if they where performed outside an open block *

* * @param openOptions * The options that define how the file is opened for the duration of the * operation * Default is Write/Create/Truncate * @param context * The context for controlling buffer sizes error handling and other low level configuration * defaults to filesystem Resource context */ def seekableProcessor(openOptions:Seq[OpenOption] = List(Read,Write), context:ResourceContext = fileSystem.context):SeekableProcessor = { new SeekableProcessor(channel(openOptions:_*).open, context) } /** * Performs an operation on the file with a FileLock *

* Not all filesystems support locking. If not then None will be returned by the method *

*

* The defaults will lock the entire file with an exclusive lock. It is possible to modify the lock so that * it only locks part of the file and may be a shared lock. Not all filesystems support shared locks but if that is * the case the lock will automatically be upgraded to a exclusiveLock *

*

* The semantics of this locking behavious are very similar to those in the {@link java.nio.channels.FileLock} * It is recommended that those javadocs are read and the warnings present in those docs are followed. *

* @param start * the start position of the lock. Must be a non-negative Long * @param size * the length in bits the lock. If -1 then the entire file from start to the end will be locked * @param shared * If true then a shared lock will be obtained if possible. If shared locks are not supported * then an exclusive lock will be obtained * @param context * The context for controlling buffer sizes error handling and other low level configuration * * @return the result * the result from the block or None if the filesystem does not support locking */ def withLock[R](start: Long = 0, size: Long = -1, shared: Boolean = false, context:ResourceContext = fileSystem.context)(block: Seekable => R): Option[R] // API ends here. // required for path // required methods for Input trait override def chars(implicit codec: Codec): LongTraversable[Char] = inputStream().chars(codec) protected override def toByteChannelResource():InputResource[ByteChannel] = channel(Read)/*{ def resource = { val r = channel(Read).open r.get.position(0) new ByteChannel { private[this] val wrapped = r.get def resetPosition() = wrapped.position(0) def isOpen = wrapped.isOpen def close() {r.close()} def write(src: ByteBuffer) = wrapped.write(src) def read(dst: ByteBuffer) = wrapped.read(dst) def size = wrapped.size } } new ByteChannelResource(resource,context, CloseAction.Noop,() => Some(resource.size)) }*/ // required method for Output trait override protected def underlyingOutput = if (canRead) channel(WriteTruncate : _*) else outputStream().writableByteChannel protected def underlyingChannel(append: Boolean) = { if(append) { channel((ReadWrite :+ Append) :_*).open } else { channel(ReadWrite : _*).open } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy