Scala запись и чтение из файла внутри цикла while - PullRequest
0 голосов
/ 21 февраля 2019

У меня есть приложение, в котором я должен записать значения в файл и прочитать их обратно в программу в цикле 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 голосов
/ 21 февраля 2019

В saveFile вам необходимо закрыть fileWriter после закрытия bufferedWriter.Вам не нужно flush, потому что close сделает это за вас.


Вам также следует закрыть все другие File объекты, которые вы создаете в цикле, потому что они могут бытьдержась за устаревшие ручки файлов.(например, local, ast)

В целом, очистите код, поместив код в функции со значимыми именами.Существует также много кода, который может быть за пределами цикла.Это поможет вам увидеть, что происходит, и позволит вам создать Минимальный, Полный и Проверяемый пример .В нынешнем виде действительно сложно понять, что происходит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...