Seemingly Random Characters at End of Output When Using Scanner - java

The code below is intended to encrypt and decrypt messages input. When I encrypt and decrypt data, it sometimes works and at other times doesn't. The following is an example of the problems I am experiencing.
Encryption
Decryption
As you can see, when I try to decrypt, my program terminated and some gibberish is output into the console. What is the issue with my code?
I'm unsure if mentioning this helps, but I have Eclipse's file encoding set to UTF-8.
Please excuse any poor code. I'm still very much a beginner with Java and I'm puzzled as to why this is happening.
import java.util.Scanner;
public class Transcrypt {
static String mode = "",
msg,
key;
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while (!mode.equals("e") && !mode.equals("d")) { // Ask for mode until equal to "e" or "d"
System.out.print("Encrypt or decrypt? (e/d) ");
mode = input.nextLine().toLowerCase();
}
System.out.print("Message: "); // Ask for message
msg = input.nextLine();
System.out.print("Passkey: "); // Ask for key
key = input.nextLine();
input.close();
System.out.println(transcrypt(msg, key, mode.equals("d"))); // Transcrypt and output
}
public static String transcrypt(String msg, String key, boolean decode) {
String result = "";
for (int i=0; i<msg.length(); i++) {
// Add or subtract Unicode index of key.charAt(i % key.length()) and/from msg.msg.charAt(i) and convert back to character
result += (char) ((int) msg.charAt(i) + ((int) key.charAt(i % key.length())) * (decode ? -1 : 1));
}
return result;
}
}

Your encoded message looks like "¼ÊßàãÊãæÑ×", but actually, it is "¼Êßàã\u0085ÊãæÑ×\u0095".
Most notably, it contains the control character 0x85 in-between which has “new line” semantics. So when copying that string, you’re copying the control characters with it and when pasting into the console upon your application’s query for the message, you are basically entering ¼Êßàã as message, the input committed via the “new line” control character, causing the subsequent query for the password to consume the trailing ÊãæÑ× characters.
The garbage you see right after the Passkey: output, is the result of your attempt to decode ¼Êßàã using the key ÊãæÑ×, as there was no newline entered at this point as the characters being already in the console’s buffer have been used.
Generally, as already said by Nándor Előd Fekete in this comment, you should not write characters to the console, that are actually binary data, like the encoded string.
By the way, you shouldn’t declare variables as static fields that are actually local to a method, i.e. your main method. Further, you don’t need to cast char to int when doing computations. char values are already a subset of the int values.

Related

Remove carriage return and special characters from text

I am writing a code in java that takes text then remove all the Punctuations (, blanks - new line and numerals) all special character and just leave the A to Z letters. it works fine until gets to the first carriage return and stopped.
I tried many version of replaceAll but it did not work, please help!
for example
IHN EMATMG EECNIWEA RSHI A RESOEF ES RLTCMEE-COEAACIROH TLNHR PIRMOA
ECSHENEV CEDIAODED ULS NPHD TN EAE REIIY-MO TWL-EDTHTTEEN NTCIPRO TO
TUERYMT MORCCIECLL,
PIMAATODMC DNL IITIAMRO CUNAIMYNAOINI.
then I get:
IHNEMATMGEECNIWEARSHIARESOEFESRLTCMEECOEAACIROHTLNHRPIRMOAECSHENEVCEDIAODEDULSNPHDTNEAEREIIYMOTWLEDTHTTEENNTCIPROTOTUERYMTMORCCIECLL
package Cipher1;
import java.util.Scanner;
public class StripCipher
{
public static void main(String[] args)
{
// Take the input of the encrypted text from the user.
System.out.println(" Enter the cipher text : ");
Scanner ScanText = new Scanner(System.in);
String OriginalCipherText = ScanText.nextLine();
// Eliminate the wide space and special characters present in the input
// text.
String CipherText = OriginalCipherText.replaceAll("\\s+", "");
CipherText = OriginalCipherText.replaceAll("[^a-zA-Z]+", "");
System.out.println(" Striped Cipher text is : " + CipherText);
// Calculate the length of the text.
int CipherTextLength = CipherText.length();
System.out.println(" Lenght of the cipher text is : " + CipherTextLength);
}
}
for clarifications I used the following but none of them work:
replaceAll("[\n\r]", "");
replaceAll("\\r|\\n", "")
replaceAll("[^\\w\\s]","");
replaceAll("[^\\p{L}\\p{Z}]","");
replaceAll returns a String with the replacements. The original string stays the same. Now, the problem is that you're having two replaceAll calls from the same original String and the second simply overwrites the changes from the first one:
String CipherText = OriginalCipherText.replaceAll("\\s+", "");
CipherText = OriginalCipherText.replaceAll("[^a-zA-Z]+", "");
You probably want
String CipherText = OriginalCipherText.replaceAll("\\s+", "");
CipherText = CipherText.replaceAll("[^a-zA-Z]+", "");
or a combined Regular Expression.
Problem might be ScanText.nextLine() as it will read line until new line is detected so in your case it will stop taking string after MORCCIECLL, I have tried to supply hard coded string and its work fine
Scanner.nextLine() scans up to the next line separator. What you will probably have to do is continue reading lines and join them together.
one Never ever start a variable name with a capital letter! Capital letters are for types ("FooBar") and for constants ("FOO_BAR"), a variable should be called like "fooBar":
static final FooBar FOO_BAR = new FooBar();
FooBar fooBar = new FooBar();
two I agree with Artjom B. String is an immutable class. Every method that at first might look like it is changing the original string actually returns a new string containing the changed data. This way you can even easily chain the method calls using fluent notation:
String cipherText = originalCipherText.replaceAll("\\s+", "")
.replaceAll("[^a-zA-Z]+", "");
But then [^a-zA-Z] also contains \s, so your solution can be reduced to a one liner:
String cipherText = originalCipherText.replaceAll("[^a-zA-Z]+", "");
three I also agree with J Earls, Jekin Kalriya on the Scanner being the root of your problems. If you want to read multiple lines, you need to iterate the Scanner's lines:
while (true) {
final String cypherText = scanText.nextLine()
.replaceAll("[^a-zA-Z]", "");
System.out.println(cypherText);
}
Mind that in your scenario:
this get's you into an infinite loop as the System.in never ends! You would to check for a certain input like to stop the iteration.
The output comes after each line typed to the console.

take hex character, insert random character after it, take second hex character and insert another random character

I'm very new to programming, and this one has me scratching my head.
Well, more like banging my head.
The idea of this program is to take an input, convert it to ASCII, then to hex, then create a random character, insert it after the first hex character, take the second hex character, and then insert another random character after the second hex character.
such like: randChar1 + 1st char of hexString + randChar2 + 2nd char of hexString
for example,
the hex code for "asdf" is 61736466. what i need to do is seperate the 61 from the group, insert random characters i.e. "R,u" in such a way that it displays "6R1u" where the first and 3rd characters is one single hex code. I'm not quite sure how to do that since strings are immutable, and I'm seriously so stuck its ridiculous. I've searched hundreds of forums, literally, and have yet to come accross one as specific as this question is.
aside from the inserting random characters, what i need to do is take the new string consisting of 4 characters, and iterate through each hex code, which i also have no idea how to do.
i.e.
take 61, add random characters at index 1 and 3, take 73, repeat adding characters, and do this for the length of the word.
i am so absolutely stumped on how to do this, it's incredibly frustrating sitting here trying to figure something like this out when you havent the slightest clue.
I'm sorry if i'm not wording this properly or making this sound confusing.
This is essentially the pseudocode given to us by our professor, however i have made many modifications, so none of this code is final and half of it is still pseudocode.
again, apologies if this is terrible wording and format, it's my first post. I'm really just concerned with getting the encryption working, I'm not worried about decryption at this point.
it would just be wonderful if someone could point me in the right direction, to where i could write code that enables the program to achieve something to this degree:
(randChar1 + 1st char of hexString + randChar2 + 2nd char of hexString): gives me a 4 character string consisting of only one hex code. break each double digit hex and in between add random characters, and iterate through each hex code, adding random letters in the same fashion at indexes 2 and 4, until all hex code has been converted to a 4 character "encrypted" string
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package encryptionprogram;
import java.util.Random;
import java.util.Scanner;
/**
*
* #author Elliott Cade
*/
public class EncryptionProgram
{
public static void main(String[] args)
{
// TODO code application logic here
Scanner sc = new Scanner(System.in);
String plainText, encryptedText, decryptedText, asciiValue, ASCII;
System.out.print("Enter message: ");
plainText = sc.nextLine(); //takes user input
asciiValue= plainText;
System.out.println();
System.out.println("Encrypted message");
encryptedText = EncryptCharacter(asciiValue);
System.out.println(encryptedText); //disregard
System.out.println();
System.out.println("Decrypted message:");
decryptedText = DecryptMessage(encryptedText); //disregard
System.out.println(decryptedText);
ASCII = EncryptCharacter(asciiValue);
}
public static String EncryptMessage(String plainText)
{
encryptedMsg =
{ //disregard all
}
{
encryptedChar = EncryptCharacter(plainText.charAt(i));
encryptedMsg = encryptedMsg + encryptedChar;
}
Return encryptedMsg
}
public static String DecryptMessage(String encryptedText)
{ String decryptedMsg,encryptedLetter;
decryptedMsg = “”
for each group of 4 characters character in encryptedText
{
encryptedLetter = encryptedText.substring 4 characters
decryptedChar = DecryptCharacter(encryptedLetter);
encryptedMsg = encryptedMsg + decryptedChar;
}
return decryptedMsg;
}
private static String EncryptCharacter(String asciiValue)
{
char[] chars = asciiValue.toCharArray();
StringBuilder hex = new StringBuilder();
for (int i = 0; i < chars.length; i++) //takes input and converts it to hex format
hex.append(Integer.toHexString((int) chars[i]));
System.out.println();
{
}
return hex.toString();
}
public static char DecryptCharacter(String encryptedCharacter)
{
// You need to implement this function
decryptedChar = char1 + char3
ASCIICode = convert hexadecimal decryptedChar to an ASCII decimal code
decryptedChar = convert ASCII code to a character
return decryptedChar;
}
}
Use a StringBuilder. Then
for (int i = 0; i < str.length(); i++) {
char a = (char) rand.nextInt(range);
sb.append(str.charAt(i));
sb.append(a);
}
return sb.toString();
change rand.nextInt() to fit your range of characters you want.

Java String comparison issue with blank spaces

I invoke using java some web service which returns some values to me.
Those values are some attribute names which I successful receive. I put the returned values in database.
For example the values I retrieved are:
DSLAM port
Interfejs na ISP
So when I look in the database those values are stored in DB as DSLAM port and Interfejs na ISP.
That is how I received them and that is how they are stored in DB (so only with one blank space between the words).
So I'm receiving those values from a web service but when I try to do a comparison additional in the class:
if ( attribute.trim().equalsIgnoreCase("Interfejs na ISP") ) {
System.out.println("attr2");
}
or
if ( attribute.trim().equalsIgnoreCase("DSLAM port") ) {
System.out.println("attr3");
}
I am not having the System Print lines to my console, if is always false.
What can be the problem and how can I solve it?
This is a really strange behavior for me. Attributes are stored correctly and only when I try to compare it I get strange behavior. The if clause is never true. Can there be some issue with the language format?
Additionally if I try with single word:
if (attribute.trim().equalsIgnoreCase("Telefon"))
{ System.out.println("attr5");
}
Then it writes in System Out.
So with sinlge word it seems it does not have problems
Output a serialization of the byte array behind the values of attribute to see exactly what characters it contains. This will help you catch stuff like nbsp for whitespace etc. When this is done, you can change your string matching to what you actually get back from the database, or tune your persistence to produce straight forward values.
It is not enough to just println the variable, instead, you have to iterate over all the buckets in the array and output them in hex or dec - your target output is something like "[44, 53, 4C, .. ]", which would correspond to "DSL..". To convert the byte array to a hex representation, you can use this snippet, or as an exercise, try it on your own:
public static String convertToHexString(byte[] data) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < data.length; i++) {
int nibble = (data[i] >>> 4) & 0x0F;
int two_nibbles = 0;
do {
if ((0 <= nibble) && (nibble <= 9))
buf.append((char) ('0' + nibble));
else
buf.append((char) ('a' + (nibble - 10)));
nibble = data[i] & 0x0F;
} while (two_nibbles++ < 1);
}
return buf.toString();
}
Now when you have that output, take an ascii table to look up which values are contained in the string and change your ifs depending on what is actually contained in the Strings. Possibly by using a matching regex.
Chances are the whitespaces are some non-trivial blank characters like (Hex: A0), but it's also possible that you are having an encoding problem. Feel free to post the hex values if the character tables don't help.

Cipher/decipher textArea text using XOR

I have got a code which should cipher text from my textArea with some sort of String key, after the button is pressed down. The problem is, that this method can cipher text using only one character, not the whole string. I need to have a little longer key, so string is needed here. How can I change that?
btnCipher.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent klik) {
String textToCipher = textArea.getText();
String cipherKey = textField.getText();
String cipheredText = "";
int xor;
char temp;
for (int i=0; i<textToCipher.length(); i++){
xor = textToCipher.charAt(i)^cipherKey; //error
temp = (char)xor;
cipheredText += temp;
}
textArea.setText(cipheredText);
}
});
If your strings are in UTF-8 encoding, then using exclusive or between two strings (assume equal length for a moment) may NOT produce a valid UTF-8 result (in particular, you may create a "continuation" character if you have "a" and "æ" in the same position). Look here for a deeper discusion.
What is the use-case that you are trying to handle?
Change that line to:
xor = textToCipher.charAt(i) ^ cipherKey.charAt(i % cipherKey.length);
As mentioned in this post, while String class doesn't really mind storing a string with unpaired surrogates (which is actually invalid for a UTF-16 format), you will run into trouble encoding/decoding the string in other charset and when using code point related methods.

How can I extract the numbers from a string only using charAt(), length() and/or toCharArray() in Java

I have to do this for an assignment in my java class. I have been searching for a while now, but only find solutions with regex etc.
For my assignment however I may only use charAt(), length() and/or toCharArray(). I need to get from a string like gu578si300 for example just the numbers so it will become: 578300.
i know numbers are 48 - 57 in ASCII but i can't figure out how to do this in java. You guys any ideas?
i was thinking about a for loop that checks whether the (int) char is between 48-57 en if so puts the value into a seperate array. Howeevr i dont know how to programm that last thing.
I now have this;
public static String filterGetallenreeks(String reeks){
String temp = "";
for (char c : reeks.toCharArray()) {
if ((int) c > 47 && (int) c < 58)
temp += c;
}
return temp;
however it is not working, it just outputs the same as goes in.
is it something in my mainm which looks like this. If i'm right the return temp; will return the temp string into the reeks string in the main right? why is my input still the same a sthe output?
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Voer een zin, woord of cijferreeks in:");
String reeks = sc.nextLine();
if (isGetallenreeks(reeks)){
System.out.println("is getallenreeks");
filterGetallenreeks(reeks);
System.out.println(reeks);
}
Since this is homework I will not be providing the complete solution, however, this is how you should go about it:
Do a for loop that iterates for the total amount of characters within the string (.length). Check if the character is a digit using the charAt and isDigit methods.
You could do a loop that checks a character in the string, and if it's a number, append it to another string:
//I haven't tested this, so you know.
String test = "gu578si300 ";
String numbers = "";
for(int i=0; i<test.length(); i++){
if("0123456789".indexOf(test.charAt(i)) // if the character at position i is a number,
numbers = numbers + test.charAt(i); // Add it to the end of "numbers".
}
int final = Integer.parseInt(numbers); // If you need to do something with those numbers,
// Parse it.
Let me know if that works for you.
It seems like a reasonable approach, but I'd make a couple of changes from what you suggested:
If you need to result as a string then use a StringBuilder instead of an array.
Use character literals like '0' and '9' instead of ASCII codes to make your code more readable.
Update
The specific problem with your code is this line:
temp = temp + (int)c;
This converts the character to its ASCII value and then converts that to a decimal string containing the ASCII value. That's not what you want. Use this instead:
temp += c;

Categories