Описание проблемы
У меня есть приложение, в котором я должен записывать значения в файл и считывать их обратно в программу в цикле while.Это не удается, потому что файл записывается только после выхода из цикла, а не на каждой итерации.Поэтому на следующих итерациях я не могу получить доступ к значениям, которые должны были быть записаны в файл на предыдущих итерациях.Это приложение для чтения тестового файла из проекта scala и его зависимостей, затем редактировать его и записывать обратно в исходный файл.Редактирование итеративно в цикле.Я использую скалафикс и скаламета.
Мои файлы
После некоторых предыдущих обсуждений мне пришло в голову, что у меня есть два файла: local
и sourceFile
.local
содержит sourceFile
.local
- это каталог проекта Scala, а sourceFile
- это файл .scala
в подкаталоге test/scala/
.
Код Описание
В методе main
я получаю классы и файлы jar из local
и создаю синтаксический документ из sourceFile
.Затем я выполняю редактирование, используя SemanticDocument
через API патчей ScalaFix.Наконец, я хочу записать отредактированную строку обратно в sourceFile
, и это не получится, пока я не выйду из цикла (и, возможно, JVM). Смотрите комментарии к коду .Это похоже на проблему с блокировкой.Возможно, мои ранние функции, которые искали jar, классы и semanticdb
, не снимают блокировки для sourceFile
и local
.Я проверил это, написав в другом файле за пределами local
, и я получил ожидаемое поведение.
Вопрос
Как я могу заставить scala снять блокировку этих файлов?Я попытался пройти через эти функции, и я все перепутал.Я не нашел способ выпустить файлы.относящиеся к: Scala запись и чтение из файла внутри цикла while
package scalafix
import java.io.File
import java.net.URLClassLoader
import java.nio.file.Paths
import org.apache.commons.io.FileUtils
import org.apache.commons.io.filefilter.{DirectoryFileFilter, TrueFileFilter}
import scalafix.internal.patch.PatchInternals
import scalafix.internal.v1.InternalSemanticDoc
import scalafix.rule.RuleIdentifier
import scalafix.v1.{Patch, SemanticDocument, SyntacticDocument, _}
import scalafix.{Patch, RuleCtx, RuleName}
import scala.meta.Term.ApplyInfix
import scala.meta._
import scala.meta.inputs.Input
import scala.meta.internal.semanticdb.{Locator, TextDocument}
import scala.meta.internal.symtab.GlobalSymbolTable
import scala.meta.io.{AbsolutePath, Classpath}
import scala.meta.transversers.{SimpleTraverser, Transformer}
import scala.meta.{Name, Source}
import FileIO.enrichFile
import scala.sys.process._
import java.io.PrintWriter
import java.io.BufferedWriter
import java.io.FileWriter
object Printer{
//My function to write back to file
def saveFile(filename: File, data: String): Unit ={
val fileWritter: FileWriter = new FileWriter(filename)
fileWritter.write(data)
fileWritter.close()
}
}
object Main extends App {
//My variables to be updated after every loop
var doc: SyntacticDocument = null
var ast: Source = null
var n = 3
val firstRound = n
var editedSuite:String = null
do {
val base = "/Users/soft/Downloads/simpleAkkaProject/"
// The local file
val local = new File(base)
// run an external command to compile source files in local into SemanticDocuments
val result = sys.process.Process(Seq("sbt","semanticdb"), local).!
// find jars in local.
val jars = FileUtils.listFiles(local, Array("jar"), true).toArray(new Array[File](0))
.toList
.map(f => Classpath(f.getAbsolutePath))
.reduceOption(_ ++ _)
// find classes in local
val classes = FileUtils.listFilesAndDirs(local, TrueFileFilter.INSTANCE, DirectoryFileFilter.DIRECTORY).toArray(new Array[File](0))
.toList
.filter(p => p.isDirectory && !p.getAbsolutePath.contains(".sbt") && p.getAbsolutePath.contains("target") && p.getAbsolutePath.contains("classes"))
.map(f => Classpath(f.getAbsolutePath))
.reduceOption(_ ++ _)
// compute the classpath
val classPath = ClassLoader.getSystemClassLoader.asInstanceOf[URLClassLoader].getURLs
.map(url => Classpath(url.getFile))
.reduceOption(_ ++ _)
val all = (jars ++ classes ++ classPath).reduceOption(_ ++ _).getOrElse(Classpath(""))
//combine classes, jars, and classpaths as dependencies into GlobalSymbolTable
val symbolTable = GlobalSymbolTable(all)
val filename = "AkkaQuickstartSpec.scala"
val root = AbsolutePath(base).resolve("src/test/scala/")
println(root)
val abspath = root.resolve(filename)
println(root)
val relpath = abspath.toRelative(AbsolutePath(base))
println(relpath)
// The sourceFile
val sourceFile = new File(base+"src/test/scala/"+filename)
// use source file to compute a syntactic document
val input = Input.File(sourceFile)
println(input)
if (n == firstRound){
doc = SyntacticDocument.fromInput(input)
}
//println(doc.tree.structure(30))
var documents: Map[String, TextDocument] = Map.empty
//use scalameta internalSemantic document to locate semantic documents in the local directory
Locator.apply(local.toPath)((path, db) => db.documents.foreach({
case document@TextDocument(_, uri, text, md5, _, _, _, _, _) if !md5.isEmpty => { // skip diagnostics files
if (n == firstRound){
ast= sourceFile.parse[Source].getOrElse(Source(List()))
}
documents = documents + (uri -> document)
println(uri)
}
println(local.canWrite)
if (editedSuite != null){
Printer.saveFile(sourceFile,editedSuite)
}
}))
//compute an implicit semantic document of the sourceFile for editing
val impl = new InternalSemanticDoc(doc, documents(relpath.toString()), symbolTable)
implicit val sdoc = new SemanticDocument(impl)
val symbols = sdoc.tree.collect {
case t@ Term.Name("<") => {
println(s"symbol for $t")
println(t.symbol.value)
println(symbolTable.info(t.symbol.value))
}
}
//edit the sourceFile semanticDocument
val staticAnalyzer = new StaticAnalyzer()
val p3 = staticAnalyzer.duplicateTestCase()
val r3 = RuleName(List(RuleIdentifier("r3")))
val map:Map[RuleName, Patch] = Map(r3->p3)
val r = PatchInternals(map, v0.RuleCtx(sdoc.tree), None)
val parsed = r._1.parse[Source]
ast = parsed.getOrElse(Source(List()))
doc =SyntacticDocument.fromTree(parsed.get)
val list: List[Int] = List()
editedSuite = r._1
println(local.canWrite)
//Write back to the sourceFile for every loop. This works only when we exit!
Printer.saveFile(sourceFile,r._1)
println("Loop: "+ n)
n-=1
} while(n>0)
}
[1]: /12280036/scala-zapis-i-chtenie-iz-faila-vnutri-tsikla-while