web-dev-qa-db-ja.com

Scalaファイルをコピーするスクリプト

scalaスクリプト内からファイルa.txtをnewDir /にコピーしたい。Javaこれは、2つのファイルに対して2つのファイルストリームを作成することによって行われます。 、a.txtからバッファに読み込み、新しいファイルのFileOutputStreamに書き込みます。これをscalaで実現するためのより良い方法はありますか?scala.tools.nsc.io._にある可能性があります。検索しましたができませんでした。多くを見つける。

27
kulkarni

パフォーマンス上の理由から、コピーにはJava.nio.Channelを使用することをお勧めします。

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 )

これを試すには、次の内容のtest.txtというファイルを作成します。

Hello World

test.txtを作成したら、コマンドラインから次のコマンドを実行します。

scala copy.scala test.txt test-copy.txt

test-copy.txtの内容がHello Worldであることを確認します。

36
Alain O'Dea

特に Apache Commons IO および FileUtils.copyFile() を使用しないのはなぜですか? FileUtilsには、ファイル/ディレクトリなどをコピーするための多数のメソッドがあることに注意してください。

33
Brian Agnew

Java 7がリリースされ、別のオプションがあります:Java.nio.file.Files.copy。おそらく最も簡単な解決策(そしてScalasの優れたimportを使用するとさらに簡単になります)。 fromtoが質問のように文字列である場合:

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)

もちろん、文字列の代わりにJava.nio.file.Pathsを使い始める必要があります。

21
Martin

Commons-ioのようなライブラリを使用する代わりに、本当に自分でそれを実行したい場合は、バージョン2.8で次のことを実行できます。ヘルパーメソッド「use」を作成します。それはあなたに自動リソース管理の形を与えるでしょう。

def use[T <: { def close(): Unit }](closable: T)(block: T => Unit) {
  try {
    block(closable)
  }
  finally {
    closable.close()
  }
}

次に、次のようなコピー方法を定義できます。

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 , _) }
    }
  }
}

バッファサイズ(ここでは1024)には調整が必要な場合があることに注意してください。

9
Ruediger Keller

雇うsbt.IO。これは純粋なscalaであり、変更されたファイルのみをコピーでき、copyDirectorydeletelistFilesなどの便利なルーチンがあります。次のように使用できます。

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

適切な依存関係を追加する必要があることに注意してください。

_libraryDependencies += "org.scala-sbt" % "io" % "0.13.0"_

[〜#〜] edit [〜#〜]:依存関係_"org.scala-sbt" % "io" % "version"_は特定のscalaバージョンとのためにコンパイルされたので、実際にはこれは良いアプローチではありません現在、2.10.X scalaバージョンでは使用できません。しかし将来的には_"org.scala-sbt" %% "io" % "version"_のように依存関係に2倍の%%を追加でき、機能します...

3

速度をあまり気にしない場合は、scala.io.Sourceを使用してファイルを読み取ることで、作業を少し楽にすることができます(この実装は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()
}

しかし、Sourceは、ファイルを1行ずつ解析するという面倒な作業をすべて行っており、実際に行を処理せずに、ファイルを再度書き出すだけです。バイト読み取り/書き込みの使用Javaスタイルはかなり高速になります(前回ベンチマークしたときの約2〜3倍)。


編集:2.8は改行を食べるので、書き込みに戻す必要があります。

2
Rex Kerr

外部で何も使用したくない場合は、Javaで使用するのと同じように使用してください。いいことは、できるということです。

1
Geo

Scalax にはscalax.io.FileExtras.copyTo(dest:File)があります。しかし、開発は止まったようです。

0
Thomas Jung