Friday, July 27, 2012

Scala-IO Getting Started

For the next several posts you will need to have Scala-IO installed and probably should have a sbt project as well.

There are currently 2 Scala-IO 0.4 releases.

  • Scala-io 0.4-seq - A version of Scala 0.4 without the Akka dependency and therefore no ASync support
  • Scala-io 0.4 - The full version that contains an Akka  dependency
The Scala 2.10 versions will have no Akka dependency but can optionally use Akka.

So getting started:

Download the example project on the docs website (http://jesseeichar.github.com/scala-io-doc/latest):
  • Go to Getting Started and follow instructions for downloading and running the example project.  The following goes through the steps for the 0.4.1 instructions.


1
2
3
4
5
6
7
8
9
10
11
12
13
sbt console
 
scala> import scalax.io._
import scalax.io._
 
scala> import java.net.URL
import java.net.URL
 
scala> Resource.fromURL(new URL("http://www.scala-lang.com")).
     | lines().async.size.onComplete(println)
res3: akka.dispatch.Future[Int] = akka.dispatch.DefaultPromise@363adfb4
 
scala> Right(770)

The last line (Right(770)) is not a command to enter; it is the result of the asynchonous call.

Thursday, July 26, 2012

Introducing Scala-IO


This is the start of a series of posts on Scala-IO.  Scala-IO is as the name implies a library for performing input and output operations with Scala.  There are 4 main facets to the library


  • Basic IO - Reading and writing to some underlying resource.  The current implementation is Java based and thus allows reading and writing to resources like java.io.Readers, Writers, Channels, Streams, etc...
  • File API - A library loosely designed after java 7 nio.file API with an additional simple unix like DSL for traversing and searching the filesystem.  It is a pluggable architecture which allows plugins for systems like WebDav or Zip filesystems to be addressed in a similar manner as the local filesystem.  The included implementation is for the local file system and is implemented on the java.io APIs
  • Asynchronous Access - Throughout the APIs are both synchronous and asynchronous options allowing both models of programming to be easily used.  
    • In the 2.10.x + versions the future implementations are pluggable but require no additional libraries if so that is the desire
    • In 2.9.x versions there are two different dependencies one with asynchronous APIs implemented on Akka and one without any asynchronous APIs
  • Processor API - An API for defining complex IO processes declaratively.
This series will look at normally a small and simple IO operation each day (or so) rather than only a few in-depth articles.  This is required because of my limited available time.

With the introduction done lets look at two small examples:

Read File with Core API (not File API):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import scalax.io._
 
// Create a resource from a file.  This is a convenience method and the string can be
// a relative path or a absolute path.  While this is convenient it is not portable
// so it is recommened to use the File API to create a Path object and read from that
val input:Input = Resource.fromFile("someFile")
 
// read all bytes into an in memory array
input.byteArray
 
// skip first 5 bytes and take the next 5
// force the operation to take place.
// The bytes is a ResourceView which is a LongTraversableView,
// meaning it will evaluate lazily until the data is forced
// or requested
input.bytes.drop(5).take(5).force
 
// read all bytes into a string
// note: codec can be passed implicitely as well
input.string(Codec.UTF8)
Same thing but with File API:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import scalax.file.Path
 
val path = Path("file")
 
// read all bytes into an in memory array
path.byteArray
 
// skip first 5 bytes and take the next 5
// force the operation to take place.
// The bytes is a ResourceView which is a LongTraversableView,
// meaning it will evaluate lazily until the data is forced
// or requested
path.bytes.drop(5).take(5).force
 
// read all bytes into a string
// note: codec can be passed implicitly as well
path.string(Codec.UTF8)