2016-11-26 1 views
0

J'utilise une application SpringBoot et ai introduit un bouton "J'aime" pour les images de chien affichées et sur chaque comme il va frapper le dessous @RequestMapping(value="likedDog") je concatène le nécessaire informations avec un délimiteur.Comment écrire du contenu dans la ligne suivante d'un fichier? et trouver une chaîne dans un fichier et le remplacer à la même ligne exacte

Méthode A l'intérieur du contrôleur ci-dessous:

@RequestMapping(value = "likedDog") 
    public String likedDogList(@RequestParam("breedType") String breedType, @RequestParam("id") String id, Model model){ 

     Long likes=0L; 
     String delimiter="_!_"; 



     Dogs dogObject= dogsService.returnDogById(Long.valueOf(id)); 
     if(dogObject.getLikes()==null){ 
     likes=0L; 
     } 
     else{ 
      likes=dogObject.getLikes(); 
     } 


     likes=likes+1;//1,2 
     dogObject.setLikes(likes);//set 1,2 
     dogObject=dogsService.saveDog(dogObject); 

     model.addAttribute("dogObj",dogObject); 
     model.addAttribute("dogBreedType",breedType); 

     String content=id+delimiter+breedType+delimiter+dogObject.getImgURL()+delimiter+dogObject.getLikes(); 
     String contentSub=id+delimiter+breedType+delimiter+dogObject.getImgURL(); 



     try{ 
     File file = new File("src/main/resources/data/DogLikes.txt"); 


     if (!file.exists()) { 
      file.createNewFile(); 
     } 

     FileWriter fw = new FileWriter(file.getAbsoluteFile()); 
     BufferedWriter bw = new BufferedWriter(fw); 

     bw.write(content); 
     bw.newLine(); 
     bw.flush();  // ORIGINAL 
     bw.close(); 
     } 
     catch(Exception e){ 
      System.out.println("Exception occured in likedDogList()"); 
      e.printStackTrace(); 
     } 


     return "liked"; 
    } 

Je veux écrire le « contenu » chaîne concaténée sur une nouvelle ligne dans le fichier respectif si aime appartiennent à des chiens, le code est illustré ci-dessous, même si Je présente bw.newLine je ne peux pas l'écrire dans newline à la place il remplace simplement l'ancien contenu existant dans la première ligne du fichier.

Contenu dans le fichier DogLikes.txt ci-dessous:

17_!_Pug_!_http://i.imgur.com/E5vBM5Z.png_!_1 //but on every click the contents are being replaced in this first line only 

Sortie prévue, le contenu à écrire dans DogLikes.txt sur tous Comme est indiqué ci-dessous:

17_!_Pug_!_http://i.imgur.com/E5vBM5Z.png_!_1 
18_!_Pug_!_http://i.imgur.com/E5vBM5Z.png_!_1 //should be written like this in newline on like of dogId 18 
19_!_Pug_!_http://i.imgur.com/E5vBM5Z.png_!_1 //should be written like this in newline on like of dogId 19 

DEUXIÈME PROBLÈME: Aussi si je clique sur "J'aime" sur DogId 18 il devrait aller et remplacer la deuxième ligne comme suit,

17_!_Pug_!_http://i.imgur.com/E5vBM5Z.png_!_1 
18_!_Pug_!_http://i.imgur.com/E5vBM5Z.png_!_2 //replacement of String in this exact location is expected 
19_!_Pug_!_http://i.imgur.com/E5vBM5Z.png_!_1 

Votre aide à ce sujet est très appréciable, Merci d'avance. Hey @daniel la méthode de sauvegarde a fonctionné pour écrire le contenu dans le fichier ligne par ligne pendant que j'utilise une approche différente pour la restauration. Cependant, je suis venu avec une nouvelle idée d'intégrer les deux goûts et aversions dans la même ligne comme indiqué ci-dessous:

Sortie prévue sur en cliquant sur « Like » et « Je n'aime »

1_!_Labrador_!_http://i.imgur.com/eE29vX4.png_!_like_!_11_!_dislike_!_5 
    2_!_Labrador_!_http://i.imgur.com/xX2AeDR.png_!_like_!_3_!_dislike_!_5 
    3_!_Labrador_!_http://i.imgur.com/hBFRUuW.png_!_like_!_1_!_dislike_!_5 
    16_!_Pug_!_http://i.imgur.com/E5vBM5Z.png_!_like_!_119_!_dislike_!_5 

J'ai besoin un peu de votre aide Méthode backup() car j'ai essayé différentes combinaisons pour mettre à jour les likes et les aversions dans la même ligne, car votre approche met à jour de façon dynamique uniquement les likes. Aussi, je suis impatient de trier les images des chiens en fonction des préférences les plus élevées au plus bas. Nous vous remercions de votre aide à l'avance.

+0

Il serait intéressant de savoir ce que vous voulez réaliser avec ce fichier. De plus avez-vous déjà envisagé d'utiliser un standard tel que csv ou xml au lieu d'un standard? En ce qui concerne votre deuxième problème: Pour remplacer le contenu, vous devez faire une boucle sur les lignes déjà existantes, trouver la correspondance, puis remplacer le nombre. Avec votre approche, vous ne faites qu'ajouter au fichier original. –

+0

merci de répondre d'abord @DanielBubenheim. J'utilise une base de données en mémoire ici H2, elle ne conserve pas les données et perd toutes les données stockées lorsque l'application est déconnectée ou arrêtée. Donc, pour stocker les J'aime j'essaie de l'enregistrer dans un fichier txt. POUR LE DEUXIÈME PROBLÈME: oui j'ai fait usage de la boucle et j'ai essayé la méthode replace() puis j'ai utilisé bw.write (** texte remplacé **) mais il semble qu'il ait écrasé tout le contenu. votre solution serait utile ici. –

+0

Ainsi, au lieu d'utiliser un stockage en mémoire, vous pouvez utiliser un stockage persistant à la place. Beaucoup plus sûr que d'écrire dans un fichier, n'est-ce pas? –

Répondre

0

Comme vous l'avez décrit dans votre question, vos exigences étaient d'utiliser un stockage en mémoire et un mécanisme de sauvegarde pour un fichier particulier dans le système de fichiers. J'ai essayé un prototype court qui utilise le ressort mvc et le repos de données. Vous pouvez trouver ici: https://github.com/dbubenheim/stackoverflow-40820684

La partie la plus intéressante est la sauvegarde et le processus de restauration des données pour lesquelles j'ai les deux classes de service suivantes:

@Service 
public class DogBackupServiceImpl implements DogBackupService { 

    @Value("${dog.backup.file}") 
    private String dogLikesFile; 

    private static final String DELIMITER = "_!_"; 

    @Override 
    public void backup(final Dog dog) throws IOException { 
     final Path dogLikesPath = Paths.get(this.dogLikesFile); 
     if (!Files.exists(dogLikesPath)) { 
      Files.createDirectories(dogLikesPath.getParent()); 
      Files.createFile(dogLikesPath); 
     } 
     final File dogLikesFile = Paths.get(this.dogLikesFile).toFile(); 
     final StringBuilder stringBuilder = new StringBuilder(); 
     String currentLine; 
     String oldLine = null; 
     try (final Scanner scanner = new Scanner(dogLikesFile)) { 
      while (scanner.hasNextLine()) { 
       currentLine = scanner.nextLine().trim(); 
       stringBuilder.append(currentLine); 
       if (currentLine != null && !currentLine.isEmpty()) { 
        stringBuilder.append("\n"); 
       } 
       if (currentLine != null && currentLine.startsWith(Long.toString(dog.getId()))) { 
        oldLine = currentLine; 
       } 
      } 
     } 
     String content = stringBuilder.toString(); 
     final boolean firstLike = (oldLine == null || oldLine.isEmpty()); 
     final String updateLine = dog.getId() + DELIMITER + dog.getBreedType() + DELIMITER + dog.getImgUrl() + DELIMITER + dog.getLikes(); 
     if (!firstLike) { 
      content = content.replace(oldLine, updateLine); 
     } 
     try (final BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(dogLikesFile))) { 
      bufferedWriter.write(content); 
      if (firstLike) { 
       bufferedWriter.write(updateLine); 
      } 
      bufferedWriter.close(); 
     } 
    } 
} 

et

@Service 
public class DogRestoreServiceImpl extends ContextLoaderListener implements DogRestoreService { 

    @Value("${dog.backup.file}") 
    private String dogLikesFile; 

    private static final int FIELD_ID = 0; 
    private static final int FIELD_BREED_TYPE = 1; 
    private static final int FIELD_IMG_URL = 2; 
    private static final int FIELD_LIKES = 3; 
    private static final String DELIMITER = "_!_"; 

    private final DogRepository dogRepository; 

    public DogRestoreServiceImpl(final DogRepository dogRepository) { 
     this.dogRepository = requireNonNull(dogRepository, "dogRepository must not be null!"); 
    } 

    @Override 
    public void restore() throws IOException { 
     final Path path = Paths.get(this.dogLikesFile); 
     if (!Files.exists(path)) { 
      System.out.println("nothing to restore"); 
      return; 
     } 
     final File dogLikesFile = path.toFile(); 
     final Set<Dog> dogs = new HashSet<>(); 
     String line; 
     try (final BufferedReader reader = new BufferedReader(new FileReader(dogLikesFile))) { 
      while ((line = reader.readLine()) != null) { 
       final String[] fields = line.split(DELIMITER); 
       final Dog dog = new Dog.DogBuilder(Long.parseLong(fields[FIELD_ID])) 
        .breedType(fields[FIELD_BREED_TYPE]) 
        .imgUrl(fields[FIELD_IMG_URL]) 
        .likes(Long.parseLong(fields[FIELD_LIKES])) 
        .build(); 
       dogs.add(dog); 
      } 
      this.dogRepository.save(dogs); 
     } 
    } 

    @Override 
    public void contextInitialized(final ServletContextEvent event) { 
     try { 
      System.out.println("context initialized. restoring data..."); 
      this.restore(); 
      System.out.println("data restoring completed!"); 
     } catch (final IOException ioException) { 
      ioException.printStackTrace(); 
     } 
    } 
}  

L'idée est: Le processus de sauvegarde enregistre chaque fois que le référentiel de données Spring enregistre une unité pour maintenir le fichier de sauvegarde à jour. Le processus de restauration est essentiellement déclenché lorsque le contexte de ressort est initialisé avec succès (au démarrage de l'application). Vous devriez donc pouvoir avoir toutes les données en mémoire et dans le fichier de sauvegarde.

Vous pouvez interagir avec le service par exemple via cURL avec les actions de base suivantes:

# retrieve all dogs 
curl -X GET "http://localhost:8080/dogs" 

# post dog 
curl -X POST -H "Content-Type: application/json" -d '{ 
    "breedType": "Husky", 
    "imgUrl": "http://i.imgur.com/abc123.png", 
    "likes": 0 
}' "http://localhost:8080/dogs" 

# like dog 
curl -X POST -H "Content-Type: application/json" -d '' http://localhost:8080/dogs/likeDog/<dogs-id>" 

Hope that helps! S'il y a d'autres questions faites le moi savoir.

+0

hey @daniel merci beaucoup, la méthode de sauvegarde m'a aidé à écrire des valeurs ligne par ligne pendant ce temps j'utilise une approche différente pour la restauration. Cependant, tout en travaillant, j'ai eu une idée d'écrire à la fois l'équivalent et n'aime pas les valeurs de comptage dans une seule ligne comme indiqué ci-dessous. –

+0

@ B.K. Vous êtes les bienvenus. Content de t'avoir aidé! –

+0

J'ai exprimé quelques inquiétudes concernant l'approche ci-dessus dans le cadre de la continuation de la question, pouvez-vous jeter un coup d'œil? Merci –