【问题标题】:How can I Write contents in the nextline within a File? and Finding a String inside a File and Replacing it at the same exact line如何在文件的下一行中写入内容?并在文件中查找字符串并将其替换在同一行
【发布时间】:2016-11-26 16:51:09
【问题描述】:

我正在使用 SpringBoot 应用程序,并为显示的狗图片引入了一个“赞”按钮,并且在每个赞时它都会点击下面的 @RequestMapping(value="likedDog") 我正在用分隔符连接必要的信息。

Controller内部的方法如下图:

@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";
    }

如果喜欢属于不同的狗,我想在相应文件的换行符上写入连接字符串“内容”,代码如下所示,即使我介绍了bw.newLine 我不能在换行符中写它,而是它只是替换文件第一行中的旧现有内容。

DogLikes.txt 文件内容如下:

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

预期输出,每个Like要写入DogLikes.txt的内容如下:

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

第二个问题: 此外,如果我在 DogId 18 上单击“Like”,它应该如下替换第二行,

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

您对此的帮助非常可观,在此先感谢。

嘿@daniel,当我使用不同的方法进行恢复时,备份方法可以将内容逐行写入文件。然而,我想出了一个新的想法,将喜欢和不喜欢合并到同一行中,如下所示:

点击“喜欢”和“不喜欢”时的预期输出

   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

我在 backup() 方法中有点需要你的帮助,因为我尝试了不同的组合来更新同一行中的喜欢和不喜欢,因为你的方法动态更新只喜欢。此外,我期待根据最高喜欢到最低对狗的图像进行排序。 提前感谢您的帮助。

【问题讨论】:

  • 知道你想用这个文件实现什么会很有趣。此外,您是否已经考虑使用诸如 csv 或 xml 之类的标准而不是专有标准?关于你的第二个问题:为了替换你需要遍历已经存在的行的内容,找到匹配然后替换计数。使用您的方法,您只需附加到原始文件。
  • 感谢您先回复@DanielBubenheim。我在这里使用内存数据库 H2,当应用程序脱机或停止时,它不会保留数据并丢失所有存储的数据。因此,为了存储喜欢,我试图将其保存到 txt 文件中。第二个问题:是的,我确实使用了循环并尝试了 replace() 方法,然后使用了 bw.write(replaced text) 但似乎它覆盖了所有内容。你的解决方案在这里会很方便。
  • 因此,您可以使用持久存储,而不是使用内存存储。比写入文件安全得多,对吧?
  • 本来是这样的:)但是要求是这样的
  • 明白。很公平:-)我会看看我是否有时间为你做一个简短的例子。

标签: java replace newline filewriter bufferedwriter


【解决方案1】:

正如您在问题中所描述的,您的要求是对文件系统中的特定文件使用内存存储和备份机制。我尝试了一个使用 spring mvc 和 data rest 的简短原型。你可以在这里找到:https://github.com/dbubenheim/stackoverflow-40820684

最有趣的部分是我有以下两个服务类的数据的备份和恢复过程:

@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();
        }
    }
}

@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();
        }
    }
}    

思路是:每次spring数据存储库保存一个实体时,备份过程都会保存一个实体,以保持备份文件是最新的。 恢复过程基本上是在spring上下文初始化成功时(应用程序启动时)触发的。因此,您应该能够在内存和备份文件中拥有所有数据。

您可以通过 cURL 等基本操作与服务进行交互:

# 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>"

希望对您有所帮助!如果还有其他问题,请告诉我。

【讨论】:

  • 嘿@daniel 非常感谢,备份方法帮助我逐行写入值,同时我使用不同的方法进行恢复。然而,在工作时,我想到了在一行中写下喜欢和不喜欢的计数值,如下所示。
  • 作为问题延续的一部分,我已经发布了一些关于上述方法的担忧,你能看看吗?谢谢
猜你喜欢
  • 1970-01-01
  • 2021-05-20
  • 2019-06-29
  • 1970-01-01
  • 1970-01-01
  • 2021-11-29
  • 1970-01-01
  • 1970-01-01
  • 2021-11-25
相关资源
最近更新 更多