Re: Read in & count characters from a text file
Jay Cee wrote:
Hi All,
Relatively new to java (ex VB) and could do with some help.
I need to read a text file character by character (can do),
and count each character as it appears, i.e
"A small sample text file" would have 1-A , 2-s, 2-m ,etc etc. and output
the results.
I have a few issues which I cannot seem to solve easily,
1/
I thought it would be a good idea to save the characters in a hashmap in
name-value pairs as they are read , map.put(tempStr,"1" )
I found I had to convert the character to a string before it would save to
the map.Ideally I would like to save as a character.
Maps (all Collections, in fact) deal only with objects,
so you cannot store primitive values like char in them. But
you can use a Character object, which expresses your intent
more directly than a String does.
Similarly, the mapped values must also be objects. I
think an Integer would be a better choice than a String; if
you expect counts greater than two billion use a Long.
2/
Before adding each character to the map
check first if it already exists
and if found increment the value portion of the name value pair
else
if not found insert into map with value of 1.
My problems seems to be I cannot "check the map" if the character exists and
if it does exist how do I get at the value to increment it.
The map has a containsKey() method that tells you whether
there is or isn't an entry for a key you're interested in.
If you're using an Integer (or Long) as the counter, you
can't just increment it: like String, an Integer cannot be
changed once it's created. Instead, you need to retrieve the
existing Integer from the map and replace it with a larger one.
... and since you need to retrieve the Integer anyhow, the
containsKey() method doesn't seem worth while: Just ask the map
for the Integer corresponding to such-and-such a Character. If
there is one, replace it. If there's not, you'll get a null
back from the map and this can be your signal to start a new
counter at unity:
Character key = Character.valueOf( (char)ch );
Integer val = (Integer)map.get(key);
if (val == null)
val = Integer.valueOf(1);
else
val = Integer.valueOf(val.intValue() + 1);
map.put(key, val);
Another approach would be to invent your own Counter class
that looks a lot like an Integer but is mutable: it has methods
like set() or increment() that change its value. Then the code
might look like
Character key = Character.valueOf( (char)ch );
Counter cnt = (Counter)map.get(key);
if (cnt == null)
map.put(key, new Counter()); // initial value zero
cnt.increment();
Here is what I have so far,
import java.io.*;
import java.util.*;
class TextTest
{
public static Map map = new HashMap();
private static TreeMap treeMap;
public static void main(String[] args) throws IOException
{
FileInputStream in = new FileInputStream("textfile.txt");
A word of warning: This is legal, but may not be what you
intend. InputStreams are for files made of bytes; Readers are
for files made of characters. If an InputStream encounters a
character that has been encoded in several bytes, it will deliver
those bytes to you individually. If a Reader encounters such a
thing, it will decode the multi-byte sequence and deliver you
the single corresponding character.
By the way, this sort of code is fine if your objective is
to learn about Maps and the like. But if your goal is really
to count char values (or byte values), an array of 65536 (or
256) ints or longs will be easier:
counts[ch]++;
--
Eric Sosman
esosman@ieee-dot-org.invalid