Scala在while循环内写入和读取文件 [英] Scala writing and reading from a file inside a while loop

查看:195
本文介绍了Scala在while循环内写入和读取文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,可以在其中将值写入文件,然后在while循环中将其读回到程序中.失败是因为仅在退出循环时才写入文件,而不是在每次迭代时才写入.因此,在接下来的迭代中,我无法访问在先前的迭代中应该写入文件的值.我该如何让每次迭代都写入文件,而不是在while循环结束时写入所有值?

I have an application where I am to write values into a file and read them back into the program in a while loop. This fails because the file is only written when I exit the loop and not in every iteration. Therefore, in the next iterations, I cannot access values that were supposed to be written into the file in the previous iterations. How can I make every iteration write into the file as opposed to writing all values at the end of the while loop?

我的应用程序使用Scalafix.它读取测试套件Scala文件,并在每次迭代时复制其测试用例.重要的细节由我的8条评论系列解释. FileWriter的工作是否有一些事情使它等待到循环的最后一轮才写回文件,因为它不会在循环的每次迭代中写回文件?

My application uses Scalafix. It reads in a test suite Scala file and duplicates its test cases at each iteration. The important details are explained by my series of 8 comments. Is there something about the working of the FileWriter that makes it wait until the last round of the loop to write back to file as it does not write back to file at every iteration of the loop?

   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和两个字符串,分别表示我的文件路径和文件名.

**Edit factored out the reading in of the semanticDocument ** This function simply returns a SemanticDocument and two strings representing my file path and filename.

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


推荐答案

saveFile中,您需要在关闭bufferedWriter之后关闭fileWriter.您不需要flush,因为close会为您完成此操作.

In saveFile you need to close the fileWriter after closing the bufferedWriter. You don't need to flush because close will do this for you.

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

You should also close all the other File objects that you create in the loop, because they may be holding on to stale file handles. (e.g. local, ast)

通常,通过将代码放入具有有意义名称的函数中来清理代码.循环外还有很多代码.这样做可以更轻松地查看正在发生的情况,并允许您创建一个最小,完整和可验证的示例.就目前而言,要弄清楚正在发生的事情确实很困难.

More generally, clean up the code by putting code in functions with meaningful names. There is also a lot of code that can be outside the loop. Doing this will make it easier to see what is going on and allow you create a Minimal, Complete, and Verifiable example. As it stands it is really difficult to work out what is going on.

这篇关于Scala在while循环内写入和读取文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆