Comment préserver les nouvelles lignes lors de la lecture d’un fichier avec stream – java 8

try (Stream lines = Files.lines(targetFile)) { List replacedContent = lines.map(line -> SsortingngUtils.replaceEach(line,keys, values)) .parallel() .collect(Collectors.toList()); Files.write(targetFile, replacedContent); } 

J’essaie de remplacer plusieurs modèles de texte dans chaque ligne du fichier. Mais j’observe que “\ r \ n” (équivalent d’octet 10 et 13) est remplacé par juste “\ r” (seulement 10) et mes tests de comparaison échouent.

Je veux conserver les nouvelles lignes telles qu’elles sont dans le fichier d’entrée et je ne veux pas que Java les touche. Quelqu’un pourrait-il suggérer s’il existe un moyen de le faire sans avoir à utiliser un remplacement par défaut séparé pour “\ r \ n”.

Le problème est que Files.lines() est implémenté par-dessus BufferedReader.readLine() , qui lit une ligne jusqu’au terminateur de ligne et la jette. Ensuite, lorsque vous écrivez les lignes avec quelque chose comme Files.write() , cela fournit le terminateur de ligne spécifique au système après chaque ligne, ce qui peut différer de celui qui a été lu.

Si vous voulez vraiment conserver les terminateurs de ligne exactement comme ils sont, même s’ils sont un mélange de différents terminateurs de ligne, vous pouvez utiliser une expression régulière et un Scanner pour cela.

Commencez par définir un modèle correspondant à une ligne incluant les terminaisons de ligne valides ou EOF:

 Pattern pat = Pattern.comstack(".*\\R|.+\\z"); 

Le \\R est un matcher de saut de ligne spécial qui correspond aux terminateurs de ligne habituels et à quelques terminateurs de ligne Unicode dont je n’ai jamais entendu parler. 🙂 Vous pouvez utiliser quelque chose comme (\\r\\n|\\r|\\n) si vous voulez juste les terminateurs CRLF , CR ou LF habituels.

Vous devez inclure .+\\z afin de faire correspondre une dernière “ligne” potentielle dans le fichier sans terminateur de ligne. Assurez-vous que l’expression régulière correspond toujours à au moins un caractère afin qu’aucune correspondance ne soit trouvée lorsque le scanner atteint la fin du fichier.

Ensuite, lisez les lignes à l’aide d’un Scanner jusqu’à ce qu’il renvoie null :

 try (Scanner in = new Scanner(Paths.get(INFILE), "UTF-8")) { Ssortingng line; while ((line = in.findWithinHorizon(pat, 0)) != null) { // Process the line, then write the output using something like // FileWriter.write(Ssortingng) that doesn't add another line terminator. } } 

Les lignes de votre stream n’incluent aucun caractère de nouvelle ligne.

Ce serait bien si la documentation de la méthode de Files.lines() mentionnait. Cependant, si vous suivez l’implémentation, cela conduit finalement à BufferedReader.readLine() . Cette méthode est documentée pour renvoyer le contenu de la ligne, sans inclure les caractères de fin de ligne .

Vous pouvez append un caractère de nouvelle ligne aux lignes lorsque vous les écrivez.

Un séparateur de ligne dépendant du système est utilisé par la méthode Files.write() que vous appelez, comme Files.write() dans son frère . Vous pouvez également obtenir ce séparateur de ligne dépendant du système avec System.lineSeparator() .

Si vous voulez un séparateur de ligne différent et que vous savez ce que c’est, vous pouvez le spécifier. Par exemple:

  try ( PrintStream out = new PrintStream( Files.newOutputStream( targetFile ))) { lines.forEach( line -> out.print( line + "\r\n") ); } 

Si vous voulez les séparateurs de lignes du fichier d’origine, vous ne pouvez pas compter uniquement sur une méthode qui les supprime. Les options incluent:

  • Lire le séparateur de première ligne et deviner qu’il est cohérent dans tout le fichier. Cela vous permet de continuer à utiliser Files.lines() pour lire les lignes.
  • Utilisez une API qui vous permet d’obtenir des lignes avec leurs séparateurs.
  • Lisez caractère par caractère plutôt que ligne par ligne pour obtenir les séparateurs de lignes.

AVERTISSEMENT: votre code lit et écrit à partir du même fichier. Vous risquez de perdre vos données d’origine en raison d’une interruption anormale ou de bugs.