Scala在while循环内读写文件

时间:2019-02-21 10:19:43

标签: scala filewriter

我有一个应用程序,可以将值写入文件,然后在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)
 }
}


1 个答案:

答案 0 :(得分:2)

中,您需要在关闭saveFile之后关闭fileWriter。您不需要bufferedWriter,因为flush会为您做到这一点。


您还应该关闭在循环中创建的所有其他close对象,因为它们可能会保持陈旧的文件句柄。 (例如Filelocal

通常,通过将代码放入具有有意义名称的函数中来清理代码。循环之外还有很多代码。这样做可以更轻松地查看正在发生的情况,并允许您创建Minimal, Complete, and Verifiable example。就目前而言,要弄清楚正在发生的事情确实很困难。