开发者

Scala script to copy files

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 o开发者_开发问答f 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.


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(dest) getChannel() transferFrom(
    new FileInputStream(src) 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.


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.


Java 7 is now out and you have another option: java.nio.file.Files.copy. The probably easiest solution (And with Scalas superior import even easier). Provided that from and to are strings as in your question:

import java.nio.file.StandardCopyOption.REPLACE_EXISTING
import java.nio.file.Files.copy
import java.nio.file.Paths.get

implicit def toPath (filename: String) = get(filename)

copy (from, to, REPLACE_EXISTING)

Of course you should start using java.nio.file.Paths instead of strings.


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.


Hire sbt.IO. It's pure scala, it can copy only changed files, has usefull routines like copyDirectory, delete, listFiles etc . You can use it as follow:

import sbt._
IO.copyFile(file1, file2)

Note you should add proper dependency:

libraryDependencies += "org.scala-sbt" % "io" % "0.13.0"

EDIT: Actually this is not a good approach since dependency "org.scala-sbt" % "io" % "version" was compiled using particular scala version and for now you cannot use it with 2.10.X scala version. But maybe in future you will can add double %% in you dependency like "org.scala-sbt" %% "io" % "version" and it will work...


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).


Edit: 2.8 eats newlines, so you have to add them back in the write.


The os-lib project makes it easy to copy a file in Scala:

os.copy(
  os.pwd/"src"/"test"/"resources"/"a_file.csv",
  os.pwd/"newDir"/"a_file.csv"
)

The library uses java.nio and java.io underneath the hood, but hides all the messiness from end users. It's the easiest modern way to perform filesystem operations, by far. See here for more info.


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.


Scalax has scalax.io.FileExtras.copyTo(dest : File). But developement seems to have stopped.


From scala-io documentation:

import scalax.io._
import Resource._

fromFile("a.txt") copyDataTo fromFile("newDir/a.txt")
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜