Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Подсчет количества слов в файле


Автор: Zhenia87 4.2.2008, 15:24
У меня есть txt файл. Мне нужно подсчитать количество вхождений каждого слова в этом файле. Подскажите пожалуйста как мне выделять слова и записывать в массив !!! Задание спасибо! 

Автор: _Y_ 4.2.2008, 16:05
Я бы 
  • сделал коллекцию TreeMap<String, Integer> myCollection = new TreeMap<String, Integer>();
  • читал бы файл в StringBuffer
  • откусывал от буфера по слову
  • проверял бы если слова нет в коллекции, то добавлял бы новый обьект myCollection.put("Word", new Integer(1));
  • если же слово уже есть в коллекции, увеличивал бы значение его счетчика.

Автор: Zhenia87 5.2.2008, 00:15
Когда у меня в файле одно слово, то программа нормально работает, но когда несколько слов, то не работает. 1)Наверное надо обнулять s после каждого слова, но я не знаю как это сделать. 2)Как правильно учитывать ENTER  при проверке символов?     
код:
Код

package showfile;
import java.io.*;
import java.util.*;
class ShowFile {
    public static void main(String[] args) 
    throws IOException
    {
     int i;
     FileInputStream fin;
      try{
       fin=new FileInputStream("TESt.txt");
      } catch(FileNotFoundException e){
        System.out.println("Файл не найден");
        return;
      } catch(ArrayIndexOutOfBoundsException e){
        System.out.println("ShowFile имя_файла");
        return;
      }
      
StringBuffer s= new StringBuffer();
TreeMap tm=new TreeMap();
      do{  
      i=fin.read();
      if (i==-1 || i==' ' || i=='!' ||
         i=='"' || i==';' || i==':' ||
         i=='?' || i=='.' || i==','
         || i==')'|| i=='(' || i==' '){}              
      else 
          while(i!=-1 & i!=' ' & i!='!' &
         i!='"' & i!=';' & i!=':' &
         i!='?' & i!='.' & i!=','
         & i!=')'& i!='(' & i!=' '){
              s.append((char)i).toString();              
              i=fin.read();
          }                     
        tm.put(s, new Integer(2));           
      } while(i!=-1 );
Set set=tm.entrySet();
Iterator it= set.iterator();
while(it.hasNext()){
    Map.Entry me=(Map.Entry)it.next();
    System.out.print(me.getKey()+": ");
    System.out.println(me.getValue());
}
    }
}

 
результат(когда более одного слова):
Код

Compiling 1 source file to D:\МОЯ ПАПКА\Java\Ноутон & Шилдт\Example_STRING\ShowFile\build\classes
Note: D:\МОЯ ПАПКА\Java\Ноутон & Шилдт\Example_STRING\ShowFile\src\showfile\ShowFile.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
compile:
run:
Exception in thread "main" java.lang.ClassCastException: java.lang.StringBuffer
        at java.util.TreeMap.compare(TreeMap.java:1093)
        at java.util.TreeMap.put(TreeMap.java:465)
        at showfile.ShowFile.main(ShowFile.java:54)
Java Result: 1
BUILD SUCCESSFUL (total time: 1 second)

Автор: Tamerlann 5.2.2008, 01:41
1. В Map нужно ложить не StringBuffer, а String. Т.е. 
tm.put(s.toString(), new Integer(2));

2. Это все равно не будет работать. Потому что, после этого, нужно создавать новый StringBuffer
s = new StringBuffer();

3. Это тоже не будет работать smile . Потому что в Map постоянно подкладывается 2-ка ;)

4. Чтобы разбивать строки на слова лучше пользоваться классом StringTokenizer. Это гораздо удобнее  smile 

Автор: Kangaroo 5.2.2008, 02:06
Вот код из моей программки:
Код

    //parse File
    private void parseFile(File file) {
        Scanner scanner;
        try {
            //create new scanner for file
            scanner = new Scanner(file);
            
            //set delimiter - all symbols except english letters
                        // Словом считается последовательность, в которой только латинские буквы
            scanner.useDelimiter("[^a-zA-Z]+");
            
            //for each word in file
            while (scanner.hasNext()) {
                //convert word to lower case and put in database
                String word = scanner.next().toLowerCase();
                putWordInDatabase(word, file.getCanonicalPath());
            }
            
            //close scanner
            scanner.close();
        } catch (FileNotFoundException fnfe) {
            //file not found
        } catch (IOException e) {
            System.err.println(e);
        }
        
    }
    
    //put word and fileName in database
    private void putWordInDatabase(String word, String fileName) {
        if (dbMap.containsKey(word)) {
            // увеличить счетчик этого слово
        }
        else {
            // счетчик поставить в ноль и добавить слово в мапу
            dbMap.put(word, fileNames);
        }
    }

dbMap - у вас это будет TreeMap<String, Integer>

Автор: Zhenia87 5.2.2008, 17:06
Я искал информацию про StreamTokenizer в Bruce Eckel и наткнулся на готовую программу smile . Думаю разберусь с ней. Только это одна часть моей программы, мне еще надо проверить есть ли такие слова в другом txt файле, но я думаю это уже попроще. Спасибо всем за советы!     

Bruce Eckel code:
Код

import java.io.*;
import java.util.*;

class Counter {
  private int i = 1;
  int read() { return i; }
  void increment() { i++; }
}

class WordCount {
  private FileReader file;
  private StreamTokenizer st;
  // TreeMap хранит ключи в отсортированном порядке:
  private TreeMap counts = new TreeMap();
  WordCount(String filename)
    throws FileNotFoundException {
    try {
      file = new FileReader(filename);
      st = new StreamTokenizer(
        new BufferedReader(file));
      st.ordinaryChar('.');
      st.ordinaryChar('-');
     
    } catch(FileNotFoundException e) {
      System.err.println(
        "Could not open " + filename);
      throw e;
    } 
  }
  void cleanup() {
    try {
      file.close();
    } catch(IOException e) {
      System.err.println(
        "file.close() unsuccessful");
    }
  }
  void countWords() {
    try {
      while(st.nextToken() !=
        StreamTokenizer.TT_EOF) {
        String s;
        switch(st.ttype) {
          case StreamTokenizer.TT_EOL:
            s = new String("EOL");
            break;
          case StreamTokenizer.TT_NUMBER:
            s = Double.toString(st.nval);
            break;
          case StreamTokenizer.TT_WORD:
            s = st.sval; // Уже String
            break;
          default: // единственный символ в ttype
            s = String.valueOf((char)st.ttype);
        }
        if(counts.containsKey(s))
          ((Counter)counts.get(s)).increment();
        else
          counts.put(s, new Counter());
      }
    } catch(IOException e) {
      System.err.println(
        "st.nextToken() unsuccessful");
    }
  }
  Collection values() {
    return counts.values();
  }
  Set keySet() { return counts.keySet(); }
  Counter getCounter(String s) {
    return (Counter)counts.get(s);
  }
  public static void main(String[] args) 
  throws FileNotFoundException {
    WordCount wc =
      new WordCount("TEST.txt");
    wc.countWords();
    Iterator keys = wc.keySet().iterator();
    while(keys.hasNext()) {
      String key = (String)keys.next();
      System.out.println(key + ": " + wc.getCounter(key).read());
    }
    wc.cleanup();
  }
} ///:~

Автор: Zhenia87 6.2.2008, 22:33
Еще вопросик, как мне добавить в список разделителей с помощью ordinaryChar( ) одинарную скобку??? Мне просто надо, что б слова с апострофом считались одним элементом(так как могут быть украинские тексты) 

Код

 try {
      file = new FileReader(filename);
      st = new StreamTokenizer(new BufferedReader(file));
      st.ordinaryChar('.');
      st.ordinaryChar('-');
      st.ordinaryChar(''');//если так написать, то выдает ошибку
    } 

Автор: Kangaroo 6.2.2008, 23:00
Код

st.ordinaryChar('\'');

Автор: Zhenia87 7.2.2008, 18:59
Добавлять в список разделителей апостроф нету смысла, тому что разделитель – это если он стоит в конце или на початку слова. Даже не знаю как мне сделать, что б можно было проверять программой украинские тексты   smile  

Автор: LSD 8.2.2008, 13:10
Цитата(Zhenia87 @  7.2.2008,  18:59 Найти цитируемый пост)
Добавлять в список разделителей апостроф нету смысла, тому что разделитель – это если он стоит в конце или на початку слова. Даже не знаю как мне сделать, что б можно было проверять программой украинские тексты

Значит выбрасываешь StreamTokenizer и переходишь на Scanner:
Код

Pattern wordPattern = Pattern.compile("([а-яёА-ЯЁ][а-яёА-ЯЁ']*[а-яёА-ЯЁ])|[а-яёА-ЯЁ]");
Pattern delimiterPattern = Pattern.compile("([\\s\\.,!?:;\"]')+|('[\\s\\.,!?:;\"])+|([\\s\\.,!?:;\"])+");
Scanner scanner = new Scanner("Мама мыла раму'с! Вот такая 'фигня' выходит.");
scanner.useDelimiter(delimiterPattern);
while(scanner.hasNext(wordPattern))
{
  String word = scanner.next(wordPattern);
  System.out.println("word = " + word);
}

Насчет wordPattern и delimiterPattern надо еще их потестировать и может быть доработать.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)