I want to copy file a.txt to newDir/ from within a scala script. In java this would be done by creating 2 file streams for the 2 files, reading into buffer from a.txt and writing it to the FileOutputStream of the new file. Is there a better way to achieve this in scala? May be something in scala.tools.nsc.io._. I searched around but could not find much.
Why not use Apache Commons IO and FileUtils.copyFile() in particular ? Note that FileUtils has a large number of methods to copy files/directories etc.
If you don't wanna use anything external, just do it as you would have done it in Java. The nice thing, is that you can.
If you don't care too much about speed, you can make your life slightly easier by reading the file using scala.io.Source (this implementation is for 2.7.7):
def copyF(from: java.io.File, to: String) {
val out = new java.io.BufferedWriter( new java.io.FileWriter(to) );
io.Source.fromFile(from).getLines.foreach(s => out.write(s,0,s.length));
out.close()
}
But Source goes to all the trouble of parsing the file line by line, and then you just write it out again without actually processing the lines. Using byte read/write Java style will be considerably faster (about 2-3x last time I benchmarked it).
Scalax has scalax.io.FileExtras.copyTo(dest : File). But developement seems to have stopped.
Runtime.getRuntime.exec("cp 01.txt 02.txt", Array(): Array[String], new java.io.File(".")).waitFor
Only works on real operating systems. :D
If you really want to do it yourself instead of using a library like commons-io, you can do the following in version 2.8. Create a helper method "use". It will give you a form of automatic resource management.
def use[T <: { def close(): Unit }](closable: T)(block: T => Unit) {
try {
block(closable)
}
finally {
closable.close()
}
}
Then you can define a copy method like this:
import java.io._
@throws(classOf[IOException])
def copy(from: String, to: String) {
use(new FileInputStream(from)) { in =>
use(new FileOutputStream(to)) { out =>
val buffer = new Array[Byte](1024)
Iterator.continually(in.read(buffer))
.takeWhile(_ != -1)
.foreach { out.write(buffer, 0 , _) }
}
}
}
Note that the buffer size (here: 1024) might need some tuning.
For performance reasons it is better to use java.nio.Channel to do the copying.
Listing of copy.scala:
import java.io.{File,FileInputStream,FileOutputStream}
val src = new File(args(0))
val dest = new File(args(1))
new FileOutputStream(src) getChannel() transferFrom(
new FileInputStream(dest) getChannel, 0, Long.MaxValue )
To try this out create a file called test.txt with the following content:
Hello World
After creating test.txt, run the following from the command line:
scala copy.scala test.txt test-copy.txt
Verify that test-copy.txt has Hello World
as its content.