简体   繁体   English

逐行将字符串写入文本文件时避免重复

[英]Avoid repetition when writing strings to text file line by line

I use the following code to write strings to my simple text file: 我使用以下代码将字符串写入我的简单文本文件:

EDITED: 编辑:

private String fileLocation="/mnt/sdcard/out.txt";

public void saveHisToFile()
{
    if (prefs.getBoolean("saveHis", true) && mWordHis != null && mWordHis.size() >= 1)
    {
        StringBuilder sbHis = new StringBuilder();          
        Set<String> wordSet= new HashSet<String>(mWordHis);
        for (String item : wordSet)
        {
            sbHis.append(item);
            sbHis.append("\n");
        }

        String strHis = sbHis.substring(0, sbHis.length()-1);  
        try {
             BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
                     fileLocation), true));
             bw.write(strHis);
             bw.newLine();
             bw.close();
        } catch (IOException e) {

        }
    }
}

The strings are successfully written to the text file, but weirdly, some strings are overwritten, such as: 这些字符串已成功写入文本文件,但是很奇怪,某些字符串被覆盖,例如:

apple
orange
grapes
grapes
grapes
apple 
kiwi

My question is: 我的问题是:

  1. how can I stop a string being written more than once? 如何停止多次写入字符串?
  2. how can I stop writing a string (a line) to the file if it has already existed in the file? 如果文件中已经存在一个字符串(行),我该如何停止呢?

I have consulted this post but failed to apply it to my case. 我已经咨询了这篇文章,但未能将其应用于我的案例。 Can you please give a little help? 你能帮一点忙吗? Thanks a lot in advance. 非常感谢。

Try this: 尝试这个:

public void saveHisToFile(Set<String> existingWords)
{
    if (prefs.getBoolean("saveHis", true) && mWordHis != null && mWordHis.size() >= 1)
    {
        StringBuilder sbHis = new StringBuilder();
        for (String item : mWordHis)
        {
            if (!existingWords.contains(item)) {
                sbHis.append(item);
                sbHis.append("\n");
            }
        }

        String strHis = sbHis.substring(0, sbHis.length()-1);
        try {
            BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
                    fileLocation), true));
            bw.write(strHis);
            bw.newLine();
            bw.close();
        } catch (IOException e) {

        }
    }
}

I guess mWordHis is a List , which can contain duplicate entries. 我猜mWordHis是一个List ,可以包含重复的条目。 You can first convert it to a Set (which doesn't allow duplicates) and print only the words in the Set . 您可以先将其转换为Set (不允许重复),然后仅打印Set的单词。

    Set<String> wordSet= new HashSet<>(mWordHis);

    for (String item : wordSet)
    {
        sbHis.append(item);
        sbHis.append("\n");
    }

As @fge commented, LinkedHashSet may also be used if insertion order matters. 正如@fge所评论的,如果插入顺序很重要,也可以使用LinkedHashSet

If you need to run the same code several times with the same file, you must either save in memory all the records you've already wrote to the file, or read the file and get all data before writing to it. 如果您需要对同一文件多次运行同一代码,则必须将已经写入该文件的所有记录保存在内存中,或者在写入文件之前先读取并获取所有数据。

Edit: 编辑:

I can only think about trimming the words as some may contain unneeded spaces: 我只能考虑修剪单词,因为有些单词可能包含不需要的空格:

    Set<String> wordSet= new HashSet<>();
    for (String item : mWordHis){
        wordSet.add(item.trim());
    }

You could add all the strings into a HashMap and check for each new String if it is are already in there. 您可以将所有字符串添加到HashMap中,并检查每个新字符串是否已经在其中。

Example: 例:

    HashMap<String,String> test = new HashMap<String,String>();
    if(!test.containsKey(item)) {
      test.put(item,"");
      // your processing: example
      System.out.println(item);
    } else {
      // Your processing of duplicates, example:
      System.out.println("Found duplicate of: " + item);
    }

Edit: or use a HashSet as shown by the other solutions ... 编辑:或使用其他解决方案所示的HashSet ...

    HashSet<String> test = new HashSet<String>();
    if(!test.contains(item)) {
      test.add(item);
      // your processing: example
      System.out.println(item);
    } else {
      // Your processing of duplicates, example:
      System.out.println("Found duplicate of: " + item);
    }

Edit2: 编辑2:

    private String fileLocation="/mnt/sdcard/out.txt";

    public void saveHisToFile()
    {
        if (prefs.getBoolean("saveHis", true) && mWordHis != null && mWordHis.size() >= 1)
        {
            StringBuilder sbHis = new StringBuilder();  
            HashSet<String> test = new HashSet<String>();

            Set<String> wordSet= new HashSet<String>(mWordHis);
            for (String item : wordSet)
            {
                if(!test.contains(item)) {
                    test.add(item);
                    // your processing: example
                    sbHis.append(item+System.lineSeparator());
                } else {
                    // Your processing of duplicates, example:
                    //System.out.println("Found duplicate of: " + item);
                }
            }

            String strHis = sbHis.toString();  
            try {
                 BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
                         fileLocation), true));
                 bw.write(strHis);
                 bw.newLine();
                 bw.close();
            } catch (IOException e) {

            }
        }
    }

This is a complete example on how to solve your problem: 这是有关如何解决问题的完整示例:

      import java.io.BufferedReader;
      import java.io.BufferedWriter;
      import java.io.File;
      import java.io.FileReader;
      import java.io.FileWriter;
      import java.io.IOException;
      import java.util.HashSet;

      public class HisSaver {
        private HashSet<String> uniqueTester = new HashSet<String>();

        private String fileLocation="/mnt/sdcard/out.txt";

        private static HisSaver instance = null;


        private HisSaver() {
            readWordsFromFile();
        }

        public static HisSaver getInstance() {
            if(instance == null)
                instance = new HisSaver();
            return instance;
        }

        public void saveWord(String word) {
            if(!uniqueTester.contains(word)) {
                uniqueTester.add(word);
                writeWordToFile(word);
            }
        }

        private void writeWordToFile(String word) {
          try {
               BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
                       fileLocation), true));
               bw.write(word);
               bw.newLine();
               bw.close();
          } catch (IOException e) {

          }
        }

        private void readWordsFromFile() {
          try {
            BufferedReader br = new BufferedReader(new FileReader(new File(
                fileLocation)));
            String line;
            while((line = br.readLine()) != null) {
                if(!uniqueTester.contains(line)) {
                    uniqueTester.add(line);
                }
            }
          } catch (IOException e) {

          }
        }
      }

Now to use this, you simply do the following in your code: 现在使用它,您只需在代码中执行以下操作:

    HisSaver hs = HisSaver.getInstance();
    hs.saveWord("newWord");

This will insert the "newWord" if and only if it is not already in your file, provided that no other function in your code accesses this file. 当且仅当文件中还没有“ newWord”时,这将插入“ newWord”,前提是您的代码中没有其他函数可以访问该文件。 Please note: this solution is NOT thread safe!!! 请注意:此解决方案不是线程安全的!!!

Edit: Explanation of what the code does: We create a class HisSaver which is a singleton. 编辑:代码做什么的解释:我们创建一个类HisSaver,它是一个单例。 This is realized by making it's constructor private and providing a static method getInstance() which returns an initialized HisSaver. 这是通过将其构造函数设为私有并提供静态方法getInstance()来返回已初始化的HisSaver来实现的。 This HisSaver will already contain all preexisting words in your file and thus only append new words to it. 该HisSaver将已经包含文件中所有先前存在的单词,因此只能在其中附加新单词。 Calling the getInstance() method from another class will give you a handle for this singleton and allow you to call saveWord without having to worry whether you have the right object in your hands, since only one instance of it can ever be instantiated. 从另一个类中调用getInstance()方法将为您提供此单例的句柄,并允许您调用saveWord而不必担心手中是否有正确的对象,因为只能实例化该对象的一个​​实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM