Reputation: 37
I'm trying to write a code that counts the number of lines and characters from a file, then sorts any character (including space and commas)
what I come up with.
import java.io.BufferedReader;
File file1 = new File("C:/input.txt");
BufferedReader in = new BufferedReader(new FileReader(file1));
int nextChar;
char ch;
int[] count = new int[1000];
in.close();
}
}
Thanks in advance!
Upvotes: 0
Views: 174
Reputation: 86
You could use a Map which you then sort using a self-written comparator (I stole the code from this thread), this way you don't have to pre-define what characters to count (as you would with arrays).
This would look something like this:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
public class CountCharsFromFile {
static BufferedReader b;
public static void main(String[] args) {
try {
FileReader fr = new FileReader("C:\\test.txt");
b = new BufferedReader(fr);
Map<String, Double> count = new HashMap<String,Double>();
ValueComparator bvc = new ValueComparator(count);
TreeMap<String, Double> sorted_map = new TreeMap<String, Double>(bvc);
int totalChars = 0;
int totalWords = 0;
String currentLine;
while ((currentLine = b.readLine()) != null){
for (int i = 0; i < currentLine.length(); i++) {
//Char count:
totalChars += 1;
//Adding all chars to the Map:
char currentChar = Character.toLowerCase(currentLine.charAt(i));
if (! count.containsKey(String.valueOf(currentChar))){
count.put(String.valueOf(currentChar), 1.0);
}else{
count.put(String.valueOf(currentChar), count.get(String.valueOf(currentChar)) + 1);
}
}
//Counting words:
String[] currentLineSplit= currentLine.split("\\s+");
for (String string : currentLineSplit) {
totalWords += 1;
}
}
sorted_map.putAll(count);
//Output:
System.out.println("Words: " + totalWords);
System.out.println("Chars: " + totalChars);
System.out.println(sorted_map.toString());
} catch (FileNotFoundException e) {
System.err.println("Error, file not found!");
e.printStackTrace();
} catch (IOException e) {
System.err.println("Error reading file!");
e.printStackTrace();
}finally{
try {
b.close();
} catch (IOException e) {
System.err.println("Couldn't close the BufferedReader!");
e.printStackTrace();
}
}
}
}
//comparator class:
class ValueComparator implements Comparator<String> {
Map<String, Double> base;
public ValueComparator(Map<String, Double> base) {
this.base = base;
}
// Note: this comparator imposes orderings that are inconsistent with
// equals.
public int compare(String a, String b) {
if (base.get(a) >= base.get(b)) {
return -1;
} else {
return 1;
} // returning 0 would merge keys
}
}
Output looks like this:
Words: 9
Chars: 59
{ =16.0, h=7.0, i=5.0, r=4.0, c=4.0, �=3.0, s=3.0, o=3.0, l=3.0, f=3.0, ,=2.0, w=1.0, u=1.0, n=1.0, m=1.0, b=1.0, a=1.0}
The output of "sorted_map.toString()" is not really nice, so I wrote a quick output method:
static void output(TreeMap<String, Double> sm) {
String map = sm.toString();
if (map.length() > 2) { //If the map is empty it looks like this: {}
map = map.substring(1, map.length() - 1); //cutting the leading and closing { }
String[] charCount = map.split(", "); //Splitting
//And then formatting:
for (String string : charCount) {
if (string.charAt(0) == ' ') {
string = string.substring(1, string.length() - 2);
string = " " + string.substring(0, 1) + " " + string.substring(1, string.length());
System.out.println("SPACE" + string);
} else {
string = string.substring(0, string.length() - 2);
string = string.substring(0, 1) + " " + string.substring(1, 2) + " "
+ string.substring(2, string.length());
System.out.println(string);
}
}
}
}
Which you call like so:
System.out.println("Words: " + totalWords);
System.out.println("Chars: " + totalChars);
System.out.println();
//System.out.println(sorted_map.toString()); <--- old
output(sorted_map);
And the Output looks like this:
Words: 9
Chars: 60
SPACE = 8
R = 6
T = 5
E = 5
A = 5
N = 3
U = 2
O = 2
M = 2
L = 2
I = 2
H = 2
. = 1
Z = 1
Y = 1
X = 1
W = 1
V = 1
S = 1
Q = 1
P = 1
K = 1
J = 1
G = 1
F = 1
D = 1
C = 1
B = 1
And there you go, it got a little bit messy (the comparator breaks the "TreeMap.get" method so I had to build a workaround using substrings) but I hope that this will somewhat help you :)
Upvotes: 1
Reputation: 8229
Okay, so the tricky thing here is how does one go about sorting an array of primitive type int
in descending order? Well, there are a bunch of posts on this site that talk about Arrays.sort(array, Collections.reverseOrder());
but this can only be used on arrays of objects, not primitive types like int
. So the best way to go about this is to sort the array in ascending order using the built-in Arrays
method and then traverse the entire array to reverse the elements in the array. So you should consider adding this snippet of code towards the end of your program,
Arrays.sort(count);//sort in ascending order
for(int i = 0; i < count.length; i++){ //reversing the order of the array
int k = count[i]; //swapping the i-th element with the i-th to last element
count[i] = count[count.length - 1 - i];
count[count.length - 1 - i] = k;
}
Personally, I'd suggest putting the code above before this for loop,
for (i = 0; i < 26; i++) {
System.out.printf("%c : %d", i + 'A', count[i]);
System.out.println("");
}
Upvotes: 1