我有一个应用程序,可以将值写入文件,然后在while循环中将其读回程序。失败是因为仅在退出循环时才写入文件,而不是在每次迭代时才写入。因此,在下一个迭代中,我无法访问先前的迭代中应该写入文件的值。我该如何让每次迭代都写入文件,而不是在while循环结束时写入所有值?
我的应用程序使用Scalafix。它读取测试套件Scala文件,并在每次迭代时复制其测试用例。重要的细节由我的8条评论系列解释。关于FileWriter的工作是否有一些事情使它等待到循环的最后一轮才写回文件,因为它不会在循环的每次迭代中写回文件?
object Printer{
//1 . This is my filePrinter which I call at every iteration to print the new test file with its test cases duplicated.
def saveFile(filename:String, data: String): Unit ={
val fileWritter: FileWriter = new FileWriter(filename)
val bufferWritter: BufferedWriter = new BufferedWriter(fileWritter)
bufferWritter.write(data)
bufferWritter.flush()
bufferWritter.close()
}
}
object Main extends App {
//2. my loop starts here.
var n = 2
do {
// read in a semanticDocument (function provided below)
val ( sdoc1,base,filename)=SemanticDocumentBuilder.buildSemanticDocument()
implicit val sdoc = sdoc1 //4. P3 is a scalafix "patch" that collects all the test cases of
// test suite and duplicates them. It works just fine, see the next comment.
val p3 =sdoc.tree.collect {
case test@Term.ApplyInfix(Term.ApplyInfix(_,Term.Name(smc), _,
List(Lit.String(_))), Term.Name("in"), _, params) =>
Patch.addRight(test,"\n" +test.toString())
}.asPatch
//5. I collect the test cases in the next line and print
//out how many they are. At this moment, I have not
// applied the duplicate function, so they are still as
//originally read from the test file.
val staticAnalyzer = new StaticAnalyzer()
val testCases: List[Term.ApplyInfix] =
staticAnalyzer.collectTestCases()
println("Tests cases count: "+ testCases.length)
val r3 = RuleName(List(RuleIdentifier("r3")))
val map:Map[RuleName, Patch] = Map(r3->p3)
val r = PatchInternals(map, v0.RuleCtx(sdoc.tree), None)
//6. After applying the p3 patch in the previous three lines,
//I indeed print out the newly created test suite file
//and it contains each test case duplicated as shown
// by the below println(r._1.getClass).
println(r._1.getClass)
//7. I then call the my save file (see this function above - first lines of this code)
Printer.saveFile(base+"src/test/scala/"+filename,r._1)
n-=1
//8. Since I have saved my file with the duplicates,
//I would expect that it will save the file back to the
//file (overwrite the original file as I have not used "append = true".
//I would then expect that the next length of test cases will
//have doubled but this is never the case.
//The save function with FileWriter only works in the last loop.
//Therefore, no matter the number of loops, it only doubles once!
println("Loop: "+ n)
} while(n>0)
}
**编辑排除了semanticDocument
的读入** **此函数仅返回一个SemanticDocument
和两个字符串,分别表示我的文件路径和文件名。
object SemanticDocumentBuilder{
def buildSemanticDocument(): (SemanticDocument,String,String) ={
val base = "/Users/soft/Downloads/simpleAkkaProject/"
val local = new File(base)
//val dependenceisSBTCommand = s"sbt -ivy ./.ivy2 -Dsbt.ivy.home=./.ivy2 -Divy.home=./.ivy2
//val sbtCmd = s"sbt -ivy ./ivy2 -Dsbt.ivy.home=./ivy2 -Divy.home=./ivy2 -Dsbt.boot.directo
val result = sys.process.Process(Seq("sbt","semanticdb"), local).!
val jars = FileUtils.listFiles(local, Array("jar"), true).toArray(new Array[File](0))
.toList
.map(f => Classpath(f.getAbsolutePath))
.reduceOption(_ ++ _)
val classes = FileUtils.listFilesAndDirs(local, TrueFileFilter.INSTANCE, DirectoryFileFilte
.toList
.filter(p => p.isDirectory && !p.getAbsolutePath.contains(".sbt") && p.getAbsolutePath.co
.map(f => Classpath(f.getAbsolutePath))
.reduceOption(_ ++ _)
val classPath = ClassLoader.getSystemClassLoader.asInstanceOf[URLClassLoader].getURLs
.map(url => Classpath(url.getFile))
.reduceOption(_ ++ _)
val all = (jars ++ classes ++ classPath).reduceOption(_ ++ _).getOrElse(Classpath(""))
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)
val sourceFile = new File(base+"src/test/scala/"+filename)
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
Locator.apply(local.toPath)((path, db) => db.documents.foreach({
case document@TextDocument(_, uri, text, md5, _, _, _, _, _) if !md5.isEmpty => { // skip
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)
}
}))
//println(documents)
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))
}
}
(sdoc,base,filename)
}
}
答案 0 :(得分:2)
在中,您需要在关闭
saveFile
之后关闭fileWriter
。您不需要bufferedWriter
,因为flush
会为您做到这一点。
您还应该关闭在循环中创建的所有其他close
对象,因为它们可能会保持陈旧的文件句柄。 (例如File
,local
)
通常,通过将代码放入具有有意义名称的函数中来清理代码。循环之外还有很多代码。这样做可以更轻松地查看正在发生的情况,并允许您创建Minimal, Complete, and Verifiable example。就目前而言,要弄清楚正在发生的事情确实很困难。