Getting Wrong Count in JAVA Count Letters Program - java

Can anyone tell me what's wrong with my code, why am I not getting the correct letter count?
This program reads a text file and count each English letters, A-Z, and a-z, not case sensitive.
Thank you for helping.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
public class Solution {
private static int a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;
public static void print(){
int[] in = {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z};
for (int i = 0; i < in.length; i++){
System.out.println(in[i]);
}
}
public static void main(String[] args) throws FileNotFoundException{
File file = new File("t.txt");
Scanner scan = new Scanner(file);
while (scan.hasNextLine()) {
String line = scan.nextLine();
line = line.toLowerCase();
for (int i = 0; i < line.length(); i++) {
switch(line.charAt(i)) {
case 'a': a++;break;
case 'b': b++;break;
case 'c': c++;break;
case 'd': d++;break;
case 'e': e++;break;
case 'f': f++;break;
case 'g': g++;break;
case 'h': h++;break;
case 'i': i++;break;
case 'j': j++;break;
case 'k': k++;break;
case 'l': l++;break;
case 'm': m++;break;
case 'n': n++;break;
case 'o': o++;break;
case 'p': p++;break;
case 'q': q++;break;
case 'r': r++;break;
case 's': s++;break;
case 't': t++;break;
case 'u': u++;break;
case 'v': v++;break;
case 'w': w++;break;
case 'x': x++;break;
case 'y': y++;break;
case 'z': z++;break;
}
}
}
print();
}
}

The problem is that when you encounter a i, that will increment the variable of the loop, not the one in the array. So you will skip letters.
Change it with :
for (int counter = 0; counter < line.length(); counter++) {
switch(line.charAt(counter)) {

your problem is in the use the variable i
in your for loop the index counter is i and i is also a variable which you are using to count the occurrences of alphabet 'i'. use this main method, it will work.
public static void main(String[] args) throws FileNotFoundException{
File file = new File("t.txt");
Scanner scan = new Scanner(file);
while (scan.hasNextLine()) {
String line = scan.nextLine();
line = line.toLowerCase();
for (int index = 0; index < line.length(); index++) {
switch(line.charAt(index)) {
case 'a': a++;break;
case 'b': b++;break;
case 'c': c++;break;
case 'd': d++;break;
case 'e': e++;break;
case 'f': f++;break;
case 'g': g++;break;
case 'h': h++;break;
case 'i': i++;break;
case 'j': j++;break;
case 'k': k++;break;
case 'l': l++;break;
case 'm': m++;break;
case 'n': n++;break;
case 'o': o++;break;
case 'p': p++;break;
case 'q': q++;break;
case 'r': r++;break;
case 's': s++;break;
case 't': t++;break;
case 'u': u++;break;
case 'v': v++;break;
case 'w': w++;break;
case 'x': x++;break;
case 'y': y++;break;
case 'z': z++;break;
}
}
}
print();
}
also dont forget to close the scanner after you are done.

Related

How do I get my for loop to go to the next character?

I'm creating a code that will output a number based on the input letter. My code is stuck was stuck on a loop of doing character 0 repeatedly. Friend said that char Check = userInput.charAt(numTelephone); would fix it. When I placed that into my code I recieved the error: error: char cannot be dereferenced char Check = userInput.charAt(numTelephone);
import java.util.Scanner;
public class PhoneWords {
public static void main(String []args){
Scanner scnr = new Scanner(System.in);
int numTelephone;
char userInput;
userInput = scnr.next().charAt(0);
System.out.println("Enter a telephone number using letters (EXIT to quit): ");
System.out.println("The corresponding telephone number is: ");
if ((userInput >= 'A') || (userInput <= 'Z') || (userInput >= 'a') || (userInput <= 'z')){
for (numTelephone = 0; numTelephone < 7; numTelephone++){
char Check = userInput.charAt(numTelephone);
if (numTelephone == 3){
System.out.print("-");
}
switch (userInput) {
case 'A':
case 'a':
case 'B':
case 'b':
case 'C':
case 'c':
System.out.print("2");
break;
case 'D':
case 'd':
case 'E':
case 'e':
case 'F':
case 'f':
System.out.print("3");
break;
case 'G':
case 'g':
case 'H':
case 'h':
case 'I':
case 'i':
System.out.print("4");
break;
case 'J':
case 'j':
case 'K':
case 'k':
case 'L':
case 'l':
System.out.print("5");
break;
case 'M':
case 'm':
case 'N':
case 'n':
case 'O':
case 'o':
System.out.print("6");
break;
case 'P':
case 'p':
case 'Q':
case 'q':
case 'R':
case 'r':
case 'S':
case 's':
System.out.print("7");
break;
case 'T':
case 't':
case 'U':
case 'u':
case 'V':
case 'v':
System.out.print("8");
break;
case 'W':
case 'w':
case 'X':
case 'x':
case 'Y':
case 'y':
case 'Z':
case 'z':
System.out.print("9");
break;
default:
break;
}
}
}
}
}
The type char is primitive -- not an object -- so it cannot be dereferenced
Dereferencing is the process of accessing the value referred to by a reference. Since a char is already a value (not a reference), it can not be dereferenced.
so get the char from the given input like:
char userInput = scnr.nextLine().charAt(0);
And comment this line which is suggested by your friend which is not used any where:
//char Check = userInput.charAt(numTelephone);

Take character and return the Keypad equivalant

So I am writing code that will take a character and return its alpha-numeric keypad equivalent as a character.
The problem is, I am getting a question mark in a box as a return. I have checked that the input is correct. For example, with a char 'h' input, i should get a char '4' return. Hoping someone is able to spot my error.
Code is below:
public char getDigit(char letter) throws Exception{
switch (letter) {
case 'a': case 'b': case 'c': case '2':
return 2;
case 'd': case 'e': case 'f': case '3':
return 3;
case 'g': case 'h': case 'i': case '4':
return 4;
case 'j': case 'k': case 'l': case '5':
return 5;
case 'm': case 'n': case 'o': case '6':
return 6;
case 'p': case 'q': case 'r': case 's': case '7':
return 7;
case 't': case 'u': case 'v': case '8':
return 8;
case 'w': case 'x': case 'y': case 'z': case '9':
return 9;
default:
throw new IllegalArgumentException("Must be a letter or number on the Alpha-Numeric Keypad.");
}
}
The return type of your method is char.
Now take your switch statement. You return char values in the range from 2 to 9. Now look at an ASCII table.
Surprise: these chars are all "unprintable" control characters. Thus your console gives you "?" when you print them!
If you want '4', your code has to return '4', not 4! Or 52, because that entry in the ASCII table represents '4'.
You are not getting proper output because you are using char as a return type of getDigit(..) function. You should use int as a return type instead of char as in switch case you are comparing with characters and returning digit values So replace your code with the following code, this will work:
public int getDigit(char letter) throws Exception{
switch (letter) {
case 'a': case 'b': case 'c': case '2':
return 2;
case 'd': case 'e': case 'f': case '3':
return 3;
case 'g': case 'h': case 'i': case '4':
return 4;
case 'j': case 'k': case 'l': case '5':
return 5;
case 'm': case 'n': case 'o': case '6':
return 6;
case 'p': case 'q': case 'r': case 's': case '7':
return 7;
case 't': case 'u': case 'v': case '8':
return 8;
case 'w': case 'x': case 'y': case 'z': case '9':
return 9;
default:
throw new IllegalArgumentException("Must be a letter or number on the Alpha-Numeric Keypad.");
}
}

Having trouble creating a bag of objects - Scrabble word search

I have to create a scrabble word search for my data structures class. I haven't reached the actual search yet. First, I need to create a bag of scrabble tiles. However, I keep getting errors when trying to add ScrabbleTile objects to my bag.
I have four classes: ScrabbleTile, ScrabbleBag, ScrabbleHand, and WordFinder.
Here is ScrabbleTile:
public class ScrabbleTile {
private char letter;
private int points;
ScrabbleTile (char letter)
{
this.letter = letter;
switch (letter)
{
case '_':
points = 0;
case 'e':
case 'a':
case 'i':
case 'o':
case 'n':
case 'r':
case 't':
case 'l':
case 's':
case 'u':
points = 1; break;
case 'd':
case 'g':
points = 2; break;
case 'b':
case 'c':
case 'm':
case 'p':
points = 3; break;
case 'f':
case 'h':
case 'v':
case 'w':
case 'y':
points = 4; break;
case 'k':
points = 5; break;
case 'j':
case 'x':
points = 8; break;
case 'q':
case 'z':
points = 10; break;
default: System.out.println("Incorrect character. Please enter a lowercase letter, a-z.");
break;
}
}
public char getLetter()
{
return letter;
}
public int getPoints()
{
return points;
}
}
Here is my ScrabbleBag class:
import DSLib.*;
public class ScrabbleBag {
private BagADT<ScrabbleTile> letterBag;
ScrabbleBag()
{
letterBag = new Bag<>();
for (int i = 0; i < 12; i++) {letterBag.add(ScrabbleTile('e'));}
}
}
In the ScrabbleBag constructor, I'm trying to add the correct number of each letter tile, starting with "e". Netbeans had a few suggestions which I tried, but then it was telling me the line syntax was wrong, after creating a few more instance variables in the ScrabbleBag class. How can I properly add ScrabbleTile objects to the bag?
My professor was very clear that we cannot use methods ahead of what we've gone over in class. Thanks in advance!
I think you missed new when create ScrabbleTitle object
for (int i = 0; i < 12; i++) {
letterBag.add(new ScrabbleTile('e'));
}
To create a ScrabbleTile you need the new keyword:
for (int i = 0; i < 12; i++) {
ScrabbleTile tile = new ScrabbleTile('e');
letterBag.add(tile);
}

I want to write a program to find the coordinate number for each letter on the phone pad. I wote like this

import java.util.Scanner;
public class ConvertLetterToNumber {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter one letter");
String str = input.next();
char ch = str.charAt(0);
switch (ch){
case 'A': case 'a': case 'B': case 'b': case 'C': case 'c':
System.out.println("the number is 2");
break;
case 'D': case 'd': case 'E': case 'e': case 'F': case 'f':
System.out.println("the number is 3");
break;
case 'G': case 'g': case 'H': case 'h': case 'I': case 'i':
System.out.println("the number is 4");
break;
case 'J': case 'j': case 'K': case 'k': case 'L': case 'l':
System.out.println("the number is 5");
break;
case 'M': case 'm': case 'N': case 'n': case 'O': case 'o':
System.out.println("the number is 6");
break;
case 'P':case 'p': case 'Q': case 'q': case 'R': case 'r': case 'S': case's':
System.out.println("the number is 7");
break;
case 'T':case 't':case 'U':case'u':case'V':case 'v':
System.out.println("the number is 8");
break;
case 'W':case 'w':case 'X': case 'x': case 'Y':case'y':case 'Z':case 'z':
System.out.println("the number is 9");
break;
default :System.out.println("Error:invalid input");
System.exit(1);
}
}
}
the problem is if I enter two or more letters at one time (for example "ab" the answer will be "2", but what I want is "Invalid input". How can I add this instruction to ask user to enter only one letter?
You could check the str length before your switch, and return like so:
if (str.length > 1){
return;
}

Convert String to KeyEvents

I want to convert a String into KeyEvent to do something like this :
writeKeyboard(myBot,"abcd");
public void writeKeyboard(Robot bot, String st){
char[] arr = arr.toCharArray();
int i = arr.length();
int j = 0;
int keycode;
while (j<i) {
keycode = arr[j].something;
bot.keyPress(keycode);
bot.keyRelease(keycode);
j++;
}
}
I'm basically using a glorified switch statement. Simple and fast:
import static java.awt.event.KeyEvent.*;
public class Keyboard {
private Robot robot;
public static void main(String... args) throws Exception {
Keyboard keyboard = new Keyboard();
keyboard.type("Hello there, how are you?");
}
public Keyboard() throws AWTException {
this.robot = new Robot();
}
public Keyboard(Robot robot) {
this.robot = robot;
}
public void type(CharSequence characters) {
int length = characters.length();
for (int i = 0; i < length; i++) {
char character = characters.charAt(i);
type(character);
}
}
public void type(char character) {
switch (character) {
case 'a': doType(VK_A); break;
case 'b': doType(VK_B); break;
case 'c': doType(VK_C); break;
case 'd': doType(VK_D); break;
case 'e': doType(VK_E); break;
case 'f': doType(VK_F); break;
case 'g': doType(VK_G); break;
case 'h': doType(VK_H); break;
case 'i': doType(VK_I); break;
case 'j': doType(VK_J); break;
case 'k': doType(VK_K); break;
case 'l': doType(VK_L); break;
case 'm': doType(VK_M); break;
case 'n': doType(VK_N); break;
case 'o': doType(VK_O); break;
case 'p': doType(VK_P); break;
case 'q': doType(VK_Q); break;
case 'r': doType(VK_R); break;
case 's': doType(VK_S); break;
case 't': doType(VK_T); break;
case 'u': doType(VK_U); break;
case 'v': doType(VK_V); break;
case 'w': doType(VK_W); break;
case 'x': doType(VK_X); break;
case 'y': doType(VK_Y); break;
case 'z': doType(VK_Z); break;
case 'A': doType(VK_SHIFT, VK_A); break;
case 'B': doType(VK_SHIFT, VK_B); break;
case 'C': doType(VK_SHIFT, VK_C); break;
case 'D': doType(VK_SHIFT, VK_D); break;
case 'E': doType(VK_SHIFT, VK_E); break;
case 'F': doType(VK_SHIFT, VK_F); break;
case 'G': doType(VK_SHIFT, VK_G); break;
case 'H': doType(VK_SHIFT, VK_H); break;
case 'I': doType(VK_SHIFT, VK_I); break;
case 'J': doType(VK_SHIFT, VK_J); break;
case 'K': doType(VK_SHIFT, VK_K); break;
case 'L': doType(VK_SHIFT, VK_L); break;
case 'M': doType(VK_SHIFT, VK_M); break;
case 'N': doType(VK_SHIFT, VK_N); break;
case 'O': doType(VK_SHIFT, VK_O); break;
case 'P': doType(VK_SHIFT, VK_P); break;
case 'Q': doType(VK_SHIFT, VK_Q); break;
case 'R': doType(VK_SHIFT, VK_R); break;
case 'S': doType(VK_SHIFT, VK_S); break;
case 'T': doType(VK_SHIFT, VK_T); break;
case 'U': doType(VK_SHIFT, VK_U); break;
case 'V': doType(VK_SHIFT, VK_V); break;
case 'W': doType(VK_SHIFT, VK_W); break;
case 'X': doType(VK_SHIFT, VK_X); break;
case 'Y': doType(VK_SHIFT, VK_Y); break;
case 'Z': doType(VK_SHIFT, VK_Z); break;
case '`': doType(VK_BACK_QUOTE); break;
case '0': doType(VK_0); break;
case '1': doType(VK_1); break;
case '2': doType(VK_2); break;
case '3': doType(VK_3); break;
case '4': doType(VK_4); break;
case '5': doType(VK_5); break;
case '6': doType(VK_6); break;
case '7': doType(VK_7); break;
case '8': doType(VK_8); break;
case '9': doType(VK_9); break;
case '-': doType(VK_MINUS); break;
case '=': doType(VK_EQUALS); break;
case '~': doType(VK_SHIFT, VK_BACK_QUOTE); break;
case '!': doType(VK_EXCLAMATION_MARK); break;
case '#': doType(VK_AT); break;
case '#': doType(VK_NUMBER_SIGN); break;
case '$': doType(VK_DOLLAR); break;
case '%': doType(VK_SHIFT, VK_5); break;
case '^': doType(VK_CIRCUMFLEX); break;
case '&': doType(VK_AMPERSAND); break;
case '*': doType(VK_ASTERISK); break;
case '(': doType(VK_LEFT_PARENTHESIS); break;
case ')': doType(VK_RIGHT_PARENTHESIS); break;
case '_': doType(VK_UNDERSCORE); break;
case '+': doType(VK_PLUS); break;
case '\t': doType(VK_TAB); break;
case '\n': doType(VK_ENTER); break;
case '[': doType(VK_OPEN_BRACKET); break;
case ']': doType(VK_CLOSE_BRACKET); break;
case '\\': doType(VK_BACK_SLASH); break;
case '{': doType(VK_SHIFT, VK_OPEN_BRACKET); break;
case '}': doType(VK_SHIFT, VK_CLOSE_BRACKET); break;
case '|': doType(VK_SHIFT, VK_BACK_SLASH); break;
case ';': doType(VK_SEMICOLON); break;
case ':': doType(VK_COLON); break;
case '\'': doType(VK_QUOTE); break;
case '"': doType(VK_QUOTEDBL); break;
case ',': doType(VK_COMMA); break;
case '<': doType(VK_SHIFT, VK_COMMA); break;
case '.': doType(VK_PERIOD); break;
case '>': doType(VK_SHIFT, VK_PERIOD); break;
case '/': doType(VK_SLASH); break;
case '?': doType(VK_SHIFT, VK_SLASH); break;
case ' ': doType(VK_SPACE); break;
default:
throw new IllegalArgumentException("Cannot type character " + character);
}
}
private void doType(int... keyCodes) {
doType(keyCodes, 0, keyCodes.length);
}
private void doType(int[] keyCodes, int offset, int length) {
if (length == 0) {
return;
}
robot.keyPress(keyCodes[offset]);
doType(keyCodes, offset + 1, length - 1);
robot.keyRelease(keyCodes[offset]);
}
}
If you want some custom key typing, you can extend the class and override the type(char) method. For example:
import static java.awt.event.KeyEvent.*;
public class WindowUnicodeKeyboard extends Keyboard {
private Robot robot;
public WindowUnicodeKeyboard(Robot robot) {
super(robot);
this.robot = robot;
}
#Override
public void type(char character) {
try {
super.type(character);
} catch (IllegalArgumentException e) {
String unicodeDigits = String.valueOf(Character.getCodePoint(character));
robot.keyPress(VK_ALT);
for (int i = 0; i < unicodeDigits.length(); i++) {
typeNumPad(Integer.parseInt(unicodeDigits.substring(i, i + 1)));
}
robot.keyRelease(VK_ALT);
}
}
private void typeNumPad(int digit) {
switch (digit) {
case 0: doType(VK_NUMPAD0); break;
case 1: doType(VK_NUMPAD1); break;
case 2: doType(VK_NUMPAD2); break;
case 3: doType(VK_NUMPAD3); break;
case 4: doType(VK_NUMPAD4); break;
case 5: doType(VK_NUMPAD5); break;
case 6: doType(VK_NUMPAD6); break;
case 7: doType(VK_NUMPAD7); break;
case 8: doType(VK_NUMPAD8); break;
case 9: doType(VK_NUMPAD9); break;
}
}
}
There is, of course, room for improvement, but you get the idea.
I used the clipboard to solve the problem...
public static void type(String characters) {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
StringSelection stringSelection = new StringSelection( characters );
clipboard.setContents(stringSelection, clipboardOwner);
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_V);
robot.keyRelease(KeyEvent.VK_V);
robot.keyRelease(KeyEvent.VK_CONTROL);
}
You can do it simply via Java reflection API:
public void writeKeyboard(Robot bot, String st) {
String upperCase = st.toUpperCase();
for(int i = 0; i < upperCase.length(); i++) {
String letter = Character.toString(upperCase.charAt(i));
String code = "VK_" + letter
Field f = KeyEvent.class.getField(code);
int keyEvent = f.getInt(null);
bot.press(keyEvent);
bot.release(keyEvent);
}
}
I recently wrote a class to do this. It enters the Alt code of each character, instead of figuring out the key combination for every case individually. Not the fastest solution, but it's concise and works for a very wide range of characters.
import java.awt.AWTException;
import java.awt.Robot;
import static java.awt.event.KeyEvent.VK_ALT;
import static java.awt.event.KeyEvent.VK_NUMPAD0;
public class Altbot extends Robot{
Altbot()throws AWTException{}
public void type(CharSequence cs){
for(int i=0;i<cs.length();i++){
type(cs.charAt(i));
}
}
public void type(char c){
keyPress(VK_ALT);
keyPress(VK_NUMPAD0);
keyRelease(VK_NUMPAD0);
String altCode=Integer.toString(c);
for(int i=0;i<altCode.length();i++){
c=(char)(altCode.charAt(i)+'0');
//delay(20);//may be needed for certain applications
keyPress(c);
//delay(20);//uncomment if necessary
keyRelease(c);
}
keyRelease(VK_ALT);
}
}
This is how I managed to use all available keys. Create a Map and fill the map using the method fillKeyMap. Now you can use String representation of key events and convert it back into KeyEvent codes using the map.
/** Create map with string values to integer pairs
*/
public static final void fillKeyMap(Map<String, Integer> into) {
try {
Field[] fields = KeyEvent.class.getDeclaredFields();
for(Field f : fields) {
if(f.getName().startsWith("VK_")) { //we only want these fields
int code = ((Integer)f.get(null)).intValue();
into.put(f.getName().substring(3), code);
}
}
} catch(Exception ex) {}
}
I'm basically using the Command pattern as Rich Seller does in his answer, with two minor modifications for the brevity's sake:
use of the Decoration pattern for reusing instances of a-z command
use of reflection to remove KeyEvent.VK_???
Command interface:
interface Command {
void pressKey(Robot robot);
}
and the decorator (for modification #1):
class ShiftCommand implements Command {
private final Command command;
public ShiftCommand(Command command) {
this.command = command;
}
public void pressKey(Robot robot) {
robot.keyPress(KeyEvent.VK_SHIFT);
command.pressKey(robot);
robot.keyRelease(KeyEvent.VK_SHIFT);
}
#Override
public String toString() {
return "SHIFT + " + command.toString();
}
}
using this helper (for modification #2):
public static int getKeyEvent(Character c) {
Field f = KeyEvent.class.getField("VK_" + Character.toUpperCase(c));
f.setAccessible(true);
return (Integer) f.get(null);
}
BEWARE: I'm not handling exceptions here, this is left as exercise for you :))
then populating the command using a for loop:
Map<Character, Command> commandMap = new HashMap<Character, Command>();
for (int i = 'a'; i <= 'z'; i++) {
final Character c = Character.valueOf((char) i);
Command pressKeyCommand = new Command() {
public void pressKey(Robot robot) {
int keyEventCode = getKeyEvent(c);
robot.keyPress(c);
robot.keyRelease(c);
}
#Override
public String toString() {
return String.format("%c", c);
}
};
// 'a' .. 'z'
commandMap.put(c, pressKeyCommand);
// 'A' .. 'Z' by decorating pressKeyCommand
commandMap.put(Character.toUpperCase(c), new ShiftCommand(pressKeyCommand));
}
TestCase
String test = "aaaBBB";
for (int i = 0; i < test.length(); i++) {
System.out.println(commandMap.get(test.charAt(i)));
}
as expected this outputs:
a
a
a
SHIFT + b
SHIFT + b
SHIFT + b
It's a bit of a Kludge, but you can use the Command pattern to encapsulate the keystrokes for each character in the String, then get the Command for each character in turn and invoke the method. The advantage of this is that you only have to set up the map once. The disadvantage is it still involves a bunch of bolierplate:
public interface Command {
void pressKey(Robot bot);
}
//add a command to the map for each keystroke
commandMap.put("A", new Command() {
void pressKey(Robot bot) {
pressWithShift(KeyEvent.VK_A);
}
});
commandMap.put ("a", new Command() {
void pressKey (Robot bot) {
press (KeyEvent.VK_A);
}
});
commandMap.put("B", new Command() {
void pressKey(Robot bot) {
pressWithShift(KeyEvent.VK_B);
}
});
...
//loads more definitions here
//helper methods
private void pressWithShift (Robot bot, KeyEvent event) {
bot.keyPress (KeyEvent.VK_SHIFT);
press(bot, event);
bot.keyRelase(KeyEvent.VK_SHIFT);
}
private void press(Robot bot, KeyEvent event) {
bot.keyPress(event);
bot.keyRelease(event);
}
Then to use the Map:
for (int i = 0; i < st.length(); i++) {
String subString = st.substring(i, i + 1);
commandMap.get(subString).pressKey(bot);
}
The accepted answer seems very bloated to me. Here is a little more concise solution that is sort of based off of the accepted answer. It should handle pretty much any use case. Also handles \n (newline), \t (tab), and \b (backspace), as demonstrated in the example.
import java.awt.AWTException;
import java.awt.AWTKeyStroke;
import static java.awt.AWTKeyStroke.getAWTKeyStroke;
import java.awt.Robot;
import static java.awt.event.InputEvent.SHIFT_DOWN_MASK;
import java.awt.event.KeyEvent;
public class Keyboard {
private final Robot robot;
public Keyboard() throws AWTException {
this.robot = new Robot();
}
public static void main(String[] args) throws Exception {
Runtime.getRuntime().exec("notepad.exe");
Thread.sleep(3000L);
Keyboard keyboard = new Keyboard();
keyboard.type("`1234567890-=[]\\;',./\n");
keyboard.type("~!##$%^&*()_+{}|:\"<>?\n");
keyboard.type("abcdefghijklmnopqrstuvwxyz\n\tABCDEFGHIJKLMNOPQRSTUVWXYZ");
keyboard.type("\n\n\twh\bat");
}
private static AWTKeyStroke getKeyStroke(char c) {
String upper = "`~'\"!##$%^&*()_+{}|:<>?";
String lower = "`~'\"1234567890-=[]\\;,./";
int index = upper.indexOf(c);
if (index != -1) {
int keyCode;
boolean shift = false;
switch (c) {
// these chars need to be handled specially because
// they don't directly translate into the correct keycode
case '~':
shift = true;
case '`':
keyCode = KeyEvent.VK_BACK_QUOTE;
break;
case '\"':
shift = true;
case '\'':
keyCode = KeyEvent.VK_QUOTE;
break;
default:
keyCode = (int) Character.toUpperCase(lower.charAt(index));
shift = true;
}
return getAWTKeyStroke(keyCode, shift ? SHIFT_DOWN_MASK : 0);
}
return getAWTKeyStroke((int) Character.toUpperCase(c), 0);
}
public void type(CharSequence chars) {
type(chars, 0);
}
public void type(CharSequence chars, int ms) {
ms = ms > 0 ? ms : 0;
for (int i = 0, len = chars.length(); i < len; i++) {
char c = chars.charAt(i);
AWTKeyStroke keyStroke = getKeyStroke(c);
int keyCode = keyStroke.getKeyCode();
boolean shift = Character.isUpperCase(c) || keyStroke.getModifiers() == (SHIFT_DOWN_MASK + 1);
if (shift) {
robot.keyPress(KeyEvent.VK_SHIFT);
}
robot.keyPress(keyCode);
robot.keyRelease(keyCode);
if (shift) {
robot.keyRelease(KeyEvent.VK_SHIFT);
}
if (ms > 0) {
robot.delay(ms);
}
}
}
}
Your code will work as long as you are using alpha numeric characters only, it will not work for characters like ":". SmartRobot class will handle this.
I wish I had 50 reputation points to comment on Adam Paynter solution, but not yet....
His Keyboard class worked good, but I had issues with keys that aren't alphabetical, such as :, \ and /.
The solution I found was pressing and holding <ALT> while the <ASCII code> of such keys are typed.
First of all, I changed the method doType() to hold only SHIFT and/or ALTpressed, but not every single key that composes the ASCII code. Pretty much, that's how humans use keyboards :)
private void doType(int[] keyCodes, int offset, int length) {
if (length == 0) {
return;
}
robot.keyPress(keyCodes[offset]);
if (keyCodes[offset] == KeyEvent.VK_ALT
|| keyCodes[offset] == KeyEvent.VK_SHIFT) {
doType(keyCodes, offset + 1, length - 1);
robot.keyRelease(keyCodes[offset]);
} else {
robot.keyRelease(keyCodes[offset]);
doType(keyCodes, offset + 1, length - 1);
}
}
Then, I changed the switch case to pass ALT and the ASCII code:
case '\\' :
doType(KeyEvent.VK_ALT, KeyEvent.VK_NUMPAD9,
KeyEvent.VK_NUMPAD2);
case ':' :
doType(KeyEvent.VK_ALT, KeyEvent.VK_NUMPAD5,
KeyEvent.VK_NUMPAD8);
case '/' :
doType(KeyEvent.VK_ALT, KeyEvent.VK_NUMPAD4,
KeyEvent.VK_NUMPAD7);
=======================================================
ADDITION
I tweaked this class a little more:
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Keyboard {
private static final Logger LOG = LoggerFactory.getLogger(Utils.class);
private Robot robot;
public Keyboard() {
try {
this.robot = new Robot();
} catch (AWTException e) {
LOG.error("Unable to create Robot object", e);
throw new RuntimeException(e);
}
}
public void type(String text) {
char c;
for (int ii = 0; ii < text.length(); ii++) {
c = text.charAt(ii);
if (c <= 31 || c == 129) {
pressControlKey(c);
} else {
typeAsciiCode(c);
}
}
}
private void pressControlKey(char c) {
robot.keyPress(c);
robot.keyRelease(c);
}
private void typeAsciiCode(char c) {
robot.keyPress(KeyEvent.VK_ALT);
String asciiCode = Integer.toString(c);
for (int i = 0; i < asciiCode.length(); i++) {
c = (char) (asciiCode.charAt(i) + '0');
robot.keyPress(c);
robot.keyRelease(c);
}
robot.keyRelease(KeyEvent.VK_ALT);
}
}
import java.awt.Robot;
import java.awt.event.KeyEvent;
/**
* #author Trevor
* Handles alpha numerics and common punctuation
*/
public class RobotKeyboard{
private Robot robot;
public RobotKeyboard(Robot robot){
this.robot = robot;
}
public void typeMessage(String message){
for (int i = 0; i < message.length(); i++){
handleRepeatCharacter(message, i);
type(message.charAt(i));
}
}
private void handleRepeatCharacter(String message, int i){
if(i == 0)
return;
//The robot won't type the same letter twice unless we release a key.
if(message.charAt(i) == message.charAt(i-1)){
robot.keyPress(KeyEvent.VK_SHIFT);
robot.keyRelease(KeyEvent.VK_SHIFT);
}
}
private void type(char character){
handleSpecialCharacter(character);
if (Character.isLowerCase(character)){
typeCharacter(Character.toUpperCase(character));
}
if (Character.isUpperCase(character)){
typeShiftCharacter(character);
}
if (Character.isDigit(character)){
typeCharacter(character);
}
}
private void handleSpecialCharacter(char character){
if (character == ' ')
typeCharacter(KeyEvent.VK_SPACE);
if (character == '.')
typeCharacter(KeyEvent.VK_PERIOD);
if (character == '!')
typeShiftCharacter(KeyEvent.VK_1);
if (character == '?')
typeShiftCharacter(KeyEvent.VK_SLASH);
if (character == ',')
typeCharacter(KeyEvent.VK_COMMA);
//More specials here as needed
}
private void typeCharacter(int character){
robot.keyPress(character);
}
private void typeShiftCharacter(int character){
robot.keyPress(KeyEvent.VK_SHIFT);
robot.keyPress(character);
robot.keyRelease(KeyEvent.VK_SHIFT);
}
}
I had the same issue. I found that the code below was a simple way to translate a string into key events. It seems that most people had very implementation specific fixes to account for the differences between lower & upper case. Because the VK keys don't care about upper/lower case, casting everything to upper case seems to fix the problem.
for(int i = 0; i < string.length(); i++){
char c = Character.toUpperCase(s.charAt(i));
KeyEvent ke = new KeyEvent(source, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0, (int)c, c);
//do whatever with key event
}
I also wanted to say this works well for letters and number, but it may not work for other characters. This technique translated the accent/backtick mark into numberpad 0 (VK_NUMPAD0)
Slight modification to Adam Paynter's answer because code was not working for all keys e.g. !, #, #, $ etc.
(Needed to press VK_SHIFT first)
public void type(char character) {
switch (character) {
case 'a': doType(VK_A); break;
case 'b': doType(VK_B); break;
case 'c': doType(VK_C); break;
case 'd': doType(VK_D); break;
case 'e': doType(VK_E); break;
case 'f': doType(VK_F); break;
case 'g': doType(VK_G); break;
case 'h': doType(VK_H); break;
case 'i': doType(VK_I); break;
case 'j': doType(VK_J); break;
case 'k': doType(VK_K); break;
case 'l': doType(VK_L); break;
case 'm': doType(VK_M); break;
case 'n': doType(VK_N); break;
case 'o': doType(VK_O); break;
case 'p': doType(VK_P); break;
case 'q': doType(VK_Q); break;
case 'r': doType(VK_R); break;
case 's': doType(VK_S); break;
case 't': doType(VK_T); break;
case 'u': doType(VK_U); break;
case 'v': doType(VK_V); break;
case 'w': doType(VK_W); break;
case 'x': doType(VK_X); break;
case 'y': doType(VK_Y); break;
case 'z': doType(VK_Z); break;
case 'A': doType(VK_SHIFT, VK_A); break;
case 'B': doType(VK_SHIFT, VK_B); break;
case 'C': doType(VK_SHIFT, VK_C); break;
case 'D': doType(VK_SHIFT, VK_D); break;
case 'E': doType(VK_SHIFT, VK_E); break;
case 'F': doType(VK_SHIFT, VK_F); break;
case 'G': doType(VK_SHIFT, VK_G); break;
case 'H': doType(VK_SHIFT, VK_H); break;
case 'I': doType(VK_SHIFT, VK_I); break;
case 'J': doType(VK_SHIFT, VK_J); break;
case 'K': doType(VK_SHIFT, VK_K); break;
case 'L': doType(VK_SHIFT, VK_L); break;
case 'M': doType(VK_SHIFT, VK_M); break;
case 'N': doType(VK_SHIFT, VK_N); break;
case 'O': doType(VK_SHIFT, VK_O); break;
case 'P': doType(VK_SHIFT, VK_P); break;
case 'Q': doType(VK_SHIFT, VK_Q); break;
case 'R': doType(VK_SHIFT, VK_R); break;
case 'S': doType(VK_SHIFT, VK_S); break;
case 'T': doType(VK_SHIFT, VK_T); break;
case 'U': doType(VK_SHIFT, VK_U); break;
case 'V': doType(VK_SHIFT, VK_V); break;
case 'W': doType(VK_SHIFT, VK_W); break;
case 'X': doType(VK_SHIFT, VK_X); break;
case 'Y': doType(VK_SHIFT, VK_Y); break;
case 'Z': doType(VK_SHIFT, VK_Z); break;
case '`': doType(VK_BACK_QUOTE); break;
case '0': doType(VK_0); break;
case '1': doType(VK_1); break;
case '2': doType(VK_2); break;
case '3': doType(VK_3); break;
case '4': doType(VK_4); break;
case '5': doType(VK_5); break;
case '6': doType(VK_6); break;
case '7': doType(VK_7); break;
case '8': doType(VK_8); break;
case '9': doType(VK_9); break;
case '-': doType(VK_MINUS); break;
case '=': doType(VK_EQUALS); break;
case '~': doType(VK_BACK_QUOTE); break;
case '!': doType(VK_SHIFT, VK_EXCLAMATION_MARK); break;
case '#': doType(VK_SHIFT, VK_AT); break;
case '#': doType(VK_SHIFT, VK_NUMBER_SIGN); break;
case '$': doType(VK_SHIFT, VK_DOLLAR); break;
case '%': doType(VK_SHIFT, VK_5); break;
case '^': doType(VK_SHIFT, VK_CIRCUMFLEX); break;
case '&': doType(VK_SHIFT, VK_AMPERSAND); break;
case '*': doType(VK_SHIFT, VK_ASTERISK); break;
case '(': doType(VK_LEFT_PARENTHESIS); break;
case ')': doType(VK_RIGHT_PARENTHESIS); break;
case '_': doType(VK_SHIFT, VK_UNDERSCORE); break;
case '+': doType(VK_SHIFT, VK_PLUS); break;
case '\t': doType(VK_TAB); break;
case '\n': doType(VK_ENTER); break;
case '[': doType(VK_OPEN_BRACKET); break;
case ']': doType(VK_CLOSE_BRACKET); break;
case '\\': doType(VK_BACK_SLASH); break;
case '{': doType(VK_SHIFT, VK_OPEN_BRACKET); break;
case '}': doType(VK_SHIFT, VK_CLOSE_BRACKET); break;
case '|': doType(VK_SHIFT, VK_BACK_SLASH); break;
case ';': doType(VK_SEMICOLON); break;
case ':': doType(VK_SHIFT, VK_COLON); break;
case '\'': doType(VK_QUOTE); break;
case '"': doType(VK_SHIFT, VK_QUOTEDBL); break;
case ',': doType(VK_COMMA); break;
case '<': doType(VK_SHIFT, VK_COMMA); break;
case '.': doType(VK_PERIOD); break;
case '>': doType(VK_SHIFT, VK_PERIOD); break;
case '/': doType(VK_SLASH); break;
case '?': doType(VK_SHIFT, VK_SLASH); break;
case ' ': doType(VK_SPACE); break;
case '\b': doType(VK_BACK_SPACE); break;
default:
throw new IllegalArgumentException("Cannot type character " + character);
}
}
I don't know the commandmap method but looks good, I'll have a look.
Finally I discover that the keycode for a to z is 65 to 90.
So
private void write(Robot bot, String st) {
char[] arr = st.toCharArray();
int i = arr.length;
int j = 0;
while (j<i) {
int kcode = (int) arr[j] - 32;
bot.keyPress(kcode);
bot.keyRelease(kcode);
j++;
}
}
It just works for lowercase letters (you can easily correct it with a simple test for uppercase).
For what I was looking for it works perfectly :-)
I found that combining the answers of Ryan Hilbert and Adam Paynter gave me the best result. It combines the speed of single keys with the robustness of alt-codes. The combined code:
/**
* Created by Daniel on 25/8/2016.
*/
import java.awt.AWTException;
import java.awt.Robot;
import static java.awt.event.KeyEvent.VK_0;
import static java.awt.event.KeyEvent.VK_1;
import static java.awt.event.KeyEvent.VK_2;
import static java.awt.event.KeyEvent.VK_3;
import static java.awt.event.KeyEvent.VK_4;
import static java.awt.event.KeyEvent.VK_5;
import static java.awt.event.KeyEvent.VK_6;
import static java.awt.event.KeyEvent.VK_7;
import static java.awt.event.KeyEvent.VK_8;
import static java.awt.event.KeyEvent.VK_9;
import static java.awt.event.KeyEvent.VK_A;
import static java.awt.event.KeyEvent.VK_ALT;
import static java.awt.event.KeyEvent.VK_B;
import static java.awt.event.KeyEvent.VK_BACK_QUOTE;
import static java.awt.event.KeyEvent.VK_BACK_SLASH;
import static java.awt.event.KeyEvent.VK_C;
import static java.awt.event.KeyEvent.VK_CLOSE_BRACKET;
import static java.awt.event.KeyEvent.VK_COLON;
import static java.awt.event.KeyEvent.VK_COMMA;
import static java.awt.event.KeyEvent.VK_D;
import static java.awt.event.KeyEvent.VK_E;
import static java.awt.event.KeyEvent.VK_ENTER;
import static java.awt.event.KeyEvent.VK_EQUALS;
import static java.awt.event.KeyEvent.VK_F;
import static java.awt.event.KeyEvent.VK_G;
import static java.awt.event.KeyEvent.VK_H;
import static java.awt.event.KeyEvent.VK_I;
import static java.awt.event.KeyEvent.VK_J;
import static java.awt.event.KeyEvent.VK_K;
import static java.awt.event.KeyEvent.VK_L;
import static java.awt.event.KeyEvent.VK_M;
import static java.awt.event.KeyEvent.VK_MINUS;
import static java.awt.event.KeyEvent.VK_N;
import static java.awt.event.KeyEvent.VK_NUMPAD0;
import static java.awt.event.KeyEvent.VK_O;
import static java.awt.event.KeyEvent.VK_OPEN_BRACKET;
import static java.awt.event.KeyEvent.VK_P;
import static java.awt.event.KeyEvent.VK_PERIOD;
import static java.awt.event.KeyEvent.VK_Q;
import static java.awt.event.KeyEvent.VK_QUOTE;
import static java.awt.event.KeyEvent.VK_QUOTEDBL;
import static java.awt.event.KeyEvent.VK_R;
import static java.awt.event.KeyEvent.VK_S;
import static java.awt.event.KeyEvent.VK_SEMICOLON;
import static java.awt.event.KeyEvent.VK_SHIFT;
import static java.awt.event.KeyEvent.VK_SLASH;
import static java.awt.event.KeyEvent.VK_SPACE;
import static java.awt.event.KeyEvent.VK_T;
import static java.awt.event.KeyEvent.VK_TAB;
import static java.awt.event.KeyEvent.VK_U;
import static java.awt.event.KeyEvent.VK_V;
import static java.awt.event.KeyEvent.VK_W;
import static java.awt.event.KeyEvent.VK_X;
import static java.awt.event.KeyEvent.VK_Y;
import static java.awt.event.KeyEvent.VK_Z;
public class Keyboard { // http://stackoverflow.com/a/1248709/4330555
private Robot robot;
public Keyboard() throws AWTException {
this.robot = new Robot();
}
public Keyboard(Robot robot) {
this.robot = robot;
}
public void type(CharSequence characters) {
int length = characters.length();
for (int i = 0; i < length; i++) {
char character = characters.charAt(i);
try {
type(character);
} catch (IllegalArgumentException e) {
robot.keyPress(VK_ALT);
robot.keyPress(VK_NUMPAD0);
robot.keyRelease(VK_NUMPAD0);
String altCode = Integer.toString(character);
for (int j = 0; j < altCode.length(); j++) {
char c = (char) (altCode.charAt(j) + '0');
robot.keyPress(c);
robot.keyRelease(c);
}
robot.keyRelease(VK_ALT);
}
}
}
public void type(char character) {
switch (character) {
case 'a':
doType(VK_A);
break;
case 'b':
doType(VK_B);
break;
case 'c':
doType(VK_C);
break;
case 'd':
doType(VK_D);
break;
case 'e':
doType(VK_E);
break;
case 'f':
doType(VK_F);
break;
case 'g':
doType(VK_G);
break;
case 'h':
doType(VK_H);
break;
case 'i':
doType(VK_I);
break;
case 'j':
doType(VK_J);
break;
case 'k':
doType(VK_K);
break;
case 'l':
doType(VK_L);
break;
case 'm':
doType(VK_M);
break;
case 'n':
doType(VK_N);
break;
case 'o':
doType(VK_O);
break;
case 'p':
doType(VK_P);
break;
case 'q':
doType(VK_Q);
break;
case 'r':
doType(VK_R);
break;
case 's':
doType(VK_S);
break;
case 't':
doType(VK_T);
break;
case 'u':
doType(VK_U);
break;
case 'v':
doType(VK_V);
break;
case 'w':
doType(VK_W);
break;
case 'x':
doType(VK_X);
break;
case 'y':
doType(VK_Y);
break;
case 'z':
doType(VK_Z);
break;
case 'A':
doType(VK_SHIFT, VK_A);
break;
case 'B':
doType(VK_SHIFT, VK_B);
break;
case 'C':
doType(VK_SHIFT, VK_C);
break;
case 'D':
doType(VK_SHIFT, VK_D);
break;
case 'E':
doType(VK_SHIFT, VK_E);
break;
case 'F':
doType(VK_SHIFT, VK_F);
break;
case 'G':
doType(VK_SHIFT, VK_G);
break;
case 'H':
doType(VK_SHIFT, VK_H);
break;
case 'I':
doType(VK_SHIFT, VK_I);
break;
case 'J':
doType(VK_SHIFT, VK_J);
break;
case 'K':
doType(VK_SHIFT, VK_K);
break;
case 'L':
doType(VK_SHIFT, VK_L);
break;
case 'M':
doType(VK_SHIFT, VK_M);
break;
case 'N':
doType(VK_SHIFT, VK_N);
break;
case 'O':
doType(VK_SHIFT, VK_O);
break;
case 'P':
doType(VK_SHIFT, VK_P);
break;
case 'Q':
doType(VK_SHIFT, VK_Q);
break;
case 'R':
doType(VK_SHIFT, VK_R);
break;
case 'S':
doType(VK_SHIFT, VK_S);
break;
case 'T':
doType(VK_SHIFT, VK_T);
break;
case 'U':
doType(VK_SHIFT, VK_U);
break;
case 'V':
doType(VK_SHIFT, VK_V);
break;
case 'W':
doType(VK_SHIFT, VK_W);
break;
case 'X':
doType(VK_SHIFT, VK_X);
break;
case 'Y':
doType(VK_SHIFT, VK_Y);
break;
case 'Z':
doType(VK_SHIFT, VK_Z);
break;
case '`':
doType(VK_BACK_QUOTE);
break;
case '0':
doType(VK_0);
break;
case '1':
doType(VK_1);
break;
case '2':
doType(VK_2);
break;
case '3':
doType(VK_3);
break;
case '4':
doType(VK_4);
break;
case '5':
doType(VK_5);
break;
case '6':
doType(VK_6);
break;
case '7':
doType(VK_7);
break;
case '8':
doType(VK_8);
break;
case '9':
doType(VK_9);
break;
case '-':
doType(VK_MINUS);
break;
case '=':
doType(VK_EQUALS);
break;
case '~':
doType(VK_SHIFT, VK_BACK_QUOTE);
break;
case '!':
doType(VK_SHIFT, VK_1);
break;
case '#':
doType(VK_SHIFT, VK_2);
break;
case '#':
doType(VK_SHIFT, VK_3);
break;
case '$':
doType(VK_SHIFT, VK_4);
break;
case '%':
doType(VK_SHIFT, VK_5);
break;
case '^':
doType(VK_SHIFT, VK_6);
break;
case '&':
doType(VK_SHIFT, VK_7);
break;
case '*':
doType(VK_SHIFT, VK_8);
break;
case '(':
doType(VK_SHIFT, VK_9);
break;
case ')':
doType(VK_SHIFT, VK_0);
break;
case '_':
doType(VK_SHIFT, VK_MINUS);
break;
case '+':
doType(VK_SHIFT, VK_EQUALS);
break;
case '\t':
doType(VK_TAB);
break;
case '\n':
doType(VK_ENTER);
break;
case '[':
doType(VK_OPEN_BRACKET);
break;
case ']':
doType(VK_CLOSE_BRACKET);
break;
case '\\':
doType(VK_BACK_SLASH);
break;
case '{':
doType(VK_SHIFT, VK_OPEN_BRACKET);
break;
case '}':
doType(VK_SHIFT, VK_CLOSE_BRACKET);
break;
case '|':
doType(VK_SHIFT, VK_BACK_SLASH);
break;
case ';':
doType(VK_SEMICOLON);
break;
case ':':
doType(VK_COLON);
break;
case '\'':
doType(VK_QUOTE);
break;
case '"':
doType(VK_QUOTEDBL);
break;
case ',':
doType(VK_COMMA);
break;
case '<':
doType(VK_SHIFT, VK_COMMA);
break;
case '.':
doType(VK_PERIOD);
break;
case '>':
doType(VK_SHIFT, VK_PERIOD);
break;
case '/':
doType(VK_SLASH);
break;
case '?':
doType(VK_SHIFT, VK_SLASH);
break;
case ' ':
doType(VK_SPACE);
break;
default:
throw new IllegalArgumentException("Cannot type character " + character);
}
}
private void doType(int... keyCodes) {
doType(keyCodes, 0, keyCodes.length);
}
private void doType(int[] keyCodes, int offset, int length) {
if (length == 0) {
return;
}
robot.keyPress(keyCodes[offset]);
doType(keyCodes, offset + 1, length - 1);
robot.keyRelease(keyCodes[offset]);
}
}
Just another example. May become handy.
public void writeKeyboard(Robot robot, String string) {
int ascii;
for(int i = 0; i < string.length(); i++) {
ascii = (int)string.charAt(i);
robot.keyPress(ascii);
robot.delay(10);// choose your time or random it
robot.keyRelease(ascii);
robot.delay(10);
}
}

Categories