Basic Read Write

These examples are a quick introduction to performing basic IO using the Scala IO API

The basic IO object that will be used in most cases are Input,Output,ReadChars and WriteChars. These objects are used in the examples below.
Another common object is the {Seekable} object.

Java To Scala Right Way

The right way to convert java IO objects to Scala IO objects
    import scalax.io.Resource
    val in = Resource.fromReader(new StringReader("hello"))

    val numVowels = in.chars.filter("aeiou" contains _).size

    // resource can be reused because the *creation* of the reader is passed to fromReader
    // the creation code is captured so Resource can instantiate a new reader for each use of the resource
    val numNumbers = in.chars.filter('0' to '9' contains _)
  

Java To Scala Wrong Way

A discouraged method of creating Scala IO objects from java objects
    import scalax.io.Resource

    val reader = new StringReader("hello")
    // the fromReader method is passed a reference to a reader
    // this means the Resource can only be used a single time
    // only do this if you are passed a resource from a method and have
    // no way of constructing the resource within the fromReader method.
    val in = Resource.fromReader(reader)

    val numVowels = in.chars.filter("aeiou" contains _).size

    // *BOOM!* the second use will result in an exception because
    // Resource does not have access to the construction of the reader
    // just the reference to a previously created reader
    val numNumbers = in.chars.filter('0' to '9' contains _)

    // If you need a code block to construct the resource consider the following pattern:
    val in2 = Resource.fromReader {
      val string = "hello"
      new StringReader(string)
    }
  

Basic Input

Examples of basic IO
    import scalax.io._
    import scalax.io.Resource
    import java.net.URL
    import java.io.{
      InputStreamReader
    }

    // Note that in these example streams are closed automatically
    // Also note that normally a constructed stream is not passed to factory method because most factory methods are by-name parameters (=> R)
    // this means that the objects here can be reused without worrying about the stream being previously emptied
    val url = new URL("www.scala-lang.org")

    val input:Input = Resource.fromInputStream(url.openStream())

    // The simplest way to read data is to read bytes from an Input object
    val bytes: ResourceView[Byte] = input.bytes

    // you can also get the characters and strings from an Input object but you need a codec for decoding the bytes
    val chars: ResourceView[Char] = input.chars(Codec.UTF8)

    implicit val defaultCodec: Codec = Codec.UTF8

    // by declaring an _implicit_ codec I do not need to declare the codec explicitly in the next examples
    val chars2: ResourceView[Char] = input.chars

    // TODO make Lines return a ResourceView[String]
    // one can also iterate across all lines.  The line ending can be autodetected or can be explicitly declared
    val lines_Autodetect: Traversable[String] = input.lines(Line.Terminators.Auto())
    val lines_NewLineChar: Traversable[String] = input.lines(Line.Terminators.NewLine)
    val lines_CarriageReturn: Traversable[String] = input.lines(Line.Terminators.CarriageReturn)
    val lines_BothCarriageAndNewLine: Traversable[String] = input.lines(Line.Terminators.RNPair)
    val lines_CustomLineTerminator: Traversable[String] = input.lines(Line.Terminators.Custom("|"))
    val lines_KeepTerminator = input.lines(includeTerminator = true)

    // In some cases a ReadChars object is more useful.  One advantage is that the codec is already specified so the
    // codec is not needed to read characters.  Also if you start with a Reader object only a ReadChars object can
    // be constructed
    Resource.fromInputStream(url.openStream()).reader(defaultCodec).lines() foreach println _

    // Example of constructing a ReadChars object from a Reader
    Resource.fromReader(new InputStreamReader(url.openStream())).lines() foreach println _
  

Basic Output

Basic output options
    import scalax.io._
    import scalax.io.Resource
    import java.io.{
      ByteArrayOutputStream,FileOutputStream,
      PrintStream, OutputStreamWriter
    }

    // Note: The file API is nearly finished allowing one to write directly to files without the
    // cumbersome new FileOutputStream shown below.  This is the "pure" Scala IO solution
    Resource.fromOutputStream(new FileOutputStream("scala.html")) write "data".getBytes()
    Resource.fromOutputStream(new FileOutputStream("scala.html")) write Array[Byte](1,2,3)

    // strings and bytes can both be written to Output objects but strings need a Codec
    // for encoding the strings.  As usual the codec can be explicit or implicitly declared
    Resource.fromOutputStream(new ByteArrayOutputStream()).write("howdy")(Codec.UTF8)

    implicit val defaultCodec: Codec = Codec.UTF8

    // An Output object cannot be created from a Writer as a writer may have an unknown codec that is
    // used for encoding the strings and without knowing which coded is being used an Output object
    // cannot be created so a WriteChars object is created
    // WriteChars have the benefit of not needing to have a codec declared since the underlying writer
    // takes care of encoding
    Resource.fromWriter(new OutputStreamWriter(new ByteArrayOutputStream())).writeString("howdy")


    Resource.fromOutputStream(new PrintStream(new ByteArrayOutputStream())).writer.writeString("howdy")

    // Channels can also be wrapped in Resource objects and accessed as normal Input/Output objects
    val resource = Resource.fromWritableByteChannel(new FileOutputStream("file").getChannel)
  

Buffered I O

Demonstration of how to convert Input/Output to buffered counterparts
    import scalax.io._
    import java.io._

    // All io.Resource objects can be converted to a buffered equivalent if the buffered method is called
    val bufferedInput:Input = Resource.fromInputStream(new FileInputStream("file")).buffered
    val bufferedOutput:Output = Resource.fromOutputStream(new FileOutputStream("file")).buffered
    val bufferedRead:ReadChars = Resource.fromReader(new FileReader("file")).buffered
    val bufferedWrite:WriteChars = Resource.fromWriter(new FileWriter("file")).buffered
  

Using Codecs

When converting bytes to and from characters a Codec is needed for the encoding and decoding. Unlike Java Scala IO does not have a default it requires that the Codec be declared. However, to simplify the declaration most methods have implicit codec parameters so the Codec only needs to be declared once. The following examples show reading characters from input streams. Writing is follows the same pattern
    import scalax.io._
    import java.io._

    val in: InputStreamResource[FileInputStream] = Resource.fromInputStream(new FileInputStream("file"))

    // declare the Codec explicitly
    val string:String = in.slurpString(Codec.UTF8)
    val chars: ResourceView[Char] = in.chars(Codec("UTF8"))

    // create a ReadChars so that Codec only needs to be specified once
    val readChars: ReaderResource[Reader] = in.reader(Codec.ISO8859)
    val string2:String = readChars.slurpString
    val chars2: ResourceView[Char] = readChars.chars

    // Finally you can delcare an implicit val once and all calls will implicitly use that codec
    implicit val codec = Codec.UTF8

    val string3:String = in.slurpString
    val chars3: ResourceView[Char] = in.chars
    val readChars2: ReaderResource[Reader] = in.reader

  

Read Csv File

read comma separated file
    import scalax.io.Resource

    // see codec examples in scala io core for details on why there is an implicit codec here
    implicit val codec = scalax.io.Codec.UTF8

    val resource = Resource.fromBufferedReader(new BufferedReader(new FileReader("csv")))
    val records: Traversable[Array[String]] = resource.lines().map (_ split ',')

    // after this it is normal scala collection type operations
  

Add All Bytes

add all bytes in stream together
    import scalax.io._
    import java.io.InputStream
    import java.net.URL

    // see codec examples in scala io core for details on why there is an implicit codec here
    implicit val codec = scalax.io.Codec.UTF8

    val url:Input = Resource.fromURLString("file://someFile")

    // Actual type is InputStreamResource[InputStream] but that is only needed if you want to convert to a reader
    val url2: InputStreamResource[InputStream] = Resource.fromURLString("file://someFile")
    val sum: Int = url.bytesAsInts.reduceLeft (_ + _)
  

Load Into Memory

quickly (and unsafely) load all data into memory

    // first load as strings and remove vowels
    import scalax.io._
    import Resource._
    import java.net.URL
    import java.io.InputStream

    // see codec examples in scala io core for details on why there is an implicit codec here
    implicit val codec = scalax.io.Codec.UTF8

    val url: InputStreamResource[InputStream] = fromURLString("http://www.scala-lang.org")
    // You can convert an InputStreamResource to a _ReadChars_ type if desired.  That means that the codec needs to be
    // defined just once.
    val someReader: ReadChars = url.reader(Codec.UTF8)
    val consonants = url.slurpString.filterNot (c => "aeiou" contains c)

    // ok now as bytes
    val (small, large) = url.byteArray partition (_ < 128)
  

All Chars

iterate over all character in file
    import scalax.io._
    import Resource._

    // see codec examples in scala io core for details on why there is an implicit codec here
    implicit val codec = scalax.io.Codec.UTF8

    val url:Input = fromURLString("file://someFile")
    val doubled: Traversable[String] = for ( c <- url.chars ) yield "" + c + c
  

Print Lines

read and print out all lines from a URL
    import scalax.io._
    import Resource._
    import java.net.URL

    // see codec example for why codec is required
    implicit val codec = Codec.UTF8

    val url:Input = fromURLString("file://someFile")

    // by default the line terminator is stripped and is
    // auto detected
    url.lines() foreach println _

    // now do not strip terminator
    url.lines (includeTerminator = true) foreach print _

    // now declare explicitly the terminator
    // terminator is restricted to 1 or 2 characters
    url.lines (terminator = Line.Terminators.NewLine) foreach println _
  

More On Writing

several examples of writing data
    import scalax.io.Resource._
    import java.io.File
    import scalax.io.{Seekable,Codec}
    // see codec example for why codec is required
    implicit val codec = Codec.UTF8

    val someFile: Seekable = fromFileString("someFile")

    // write bytes
    // By default the file write will replace
    // an existing file with the new data
    someFile.write (Array (1,2,3) map ( _.toByte))

    // another option for write is openOptions which allows the caller
    // to specify in detail how the write should take place
    // the openOptions parameter takes a collections of OpenOptions objects
    // which are filesystem specific in general but the standard options
    // are defined in the OpenOption object
    // in addition to the definition common collections are also defined
    // WriteAppend for example is a List(Create, Append, Write)
    someFile.write (List (1,2,3) map (_.toByte))

    // write a string to the file
    someFile.write("Hello my dear file")

    // with all options (these are the default options explicitely declared)
    someFile.write("Hello my dear file")(codec = Codec.UTF8)

    // Convert several strings to the file
    // same options fromString as for write
    someFile.writeStrings( "It costs" :: "one" :: "dollar" :: Nil)

    // Now all options
    someFile.writeStrings("It costs" :: "one" :: "dollar" :: Nil,
                    separator="||\n||")(codec = Codec.UTF8)