I am trying to recreate the following logic I created in JAVA to swift:
public String xorMessage(String message, String key) {
try {
if (message == null || key == null) return null;
char[] keys = key.toCharArray();
char[] mesg = message.toCharArray();
int ml = mesg.length;
int kl = keys.length;
char[] newmsg = new char[ml];
for (int i = 0; i < ml; i++) {
newmsg[i] = (char)(mesg[i] ^ keys[i % kl]);
}//for i
return new String(newmsg);
} catch (Exception e) {
return null;
}
I have reached till here while coding in swift3:
import UIKit
import Foundation
let t = "22-Jun-2017 12:30 pm"
let m = "message"
print(UInt8(t))
let a :[UInt8] = Array(t.utf8)
let v = m.characters.map{String ($0) }
print(v)
func encodeWithXorByte(key: UInt8 , Input : String) -> String {
return String(bytes: Input.utf8.map{$0 ^ key}, encoding: String.Encoding.utf8) ?? ""
}
var ml :Int = Int( m.characters.count )
var kl :Int = Int (t.characters.count)
var f = [String]()
for i in 0..<ml{
let key = a[i%kl]
let input = v[i]
f.append(String(bytes: input.utf8.map{$0 ^ key} , encoding : String.Encoding.utf8)!)
// f.append(<#T##newElement: Character##Character#>)
//m[i] = input.utf8.map{$0 ^ key}
}
I am trying to obtain a string(message) which has been xor'ed with a key passed into the above function. But my code in swift is not working as it is returning character array and I want a string, if I try to cast the character array to string it does not show the unicode like \u{0001} etc in the string...
Suppose I get following output :
["_", "W", "^", "9", "\u{14}", "\t", "H"]
and then I try to convert to string, I get this:
_W^9 H
I want :
_W^9\u{14}\tH
Please help.
There are different problems. First, if your intention is to print
"unprintable" characters in a string \u{} escaped then you can use
the .debugDescription method. Example:
let s = "a\u{04}\u{08}b"
print(s) // ab
print(s.debugDescription) // "a\u{04}\u{08}b"
Next, your Swift code converts the string to UTF-8, xor's the bytes
and then converts the result back to a String. That can easily fail
if the xor'ed byte sequence is not valid UTF-8.
The Java code operates on UTF-16 code units, so the equivalent Swift
code would be
func xorMessage(message: String, key: String) -> String {
let keyChars = Array(key.utf16)
let keyLen = keyChars.count
let newMsg = message.utf16.enumerated().map { $1 ^ keyChars[$0 % keyLen] }
return String(utf16CodeUnits: newMsg, count: newMsg.count)
}
Example:
let t = "22-Jun-2017 12:30 pm"
let m = "message"
let encrypted = xorMessage(message: m, key: t)
print(encrypted.debugDescription) // "_W^9\u{14}\tH"
Finally, even that can produce unexpected results unless you restrict
the input (key and message) to ASCII characters. Example:
let m = "😀"
print(Array(m.utf16).map { String($0, radix: 16)} ) // ["d83d", "de00"]
let t = "a€"
print(Array(t.utf16).map { String($0, radix: 16)} ) // ["61", "20ac"]
let e = xorMessage(message: m, key: t)
print(Array(e.utf16).map { String($0, radix: 16)} ) // ["fffd", "feac"]
let d = xorMessage(message: e, key: t)
print(Array(d.utf16).map { String($0, radix: 16)} ) // ["ff9c", "fffd"]
print(d) // ワ�
print(d == m) // false
The problem is that the xor'ing produces an invalid UTF-16 sequence
(an unbalanced surrogate pair), which is then replaced by the
"replacement character" U+FFFD.
I don't know how Java handles this, but Swift strings cannot invalid
Unicode scalar values, so the only solution would be to represent
the result as an [UInt16] array instead of a String.
I've posted about letters earlier, but this is an another topic, I have a json response that contain 2 objects, from and to , from is what to change, and to is what it will be changed to .
My code is :
// for example, the EnteredText is "ab b test a b" .
EnteredString = EnteredText.getText().toString();
for (int i = 0; i < m_jArry.length(); i++) {
JSONObject jo_inside = m_jArry.getJSONObject(i);
String Original = jo_inside.getString("from");
String To = jo_inside.getString("to");
if(isMethodConvertingIn){
EnteredString = EnteredString.replace(" ","_");
EnteredString = EnteredString.replace(Original,To + " ");
} else {
EnteredString = EnteredString.replace("_"," ");
EnteredString = EnteredString.replace(To + " ", Original);
}
}
LoadingProgress.setVisibility(View.GONE);
SetResultText(EnteredString);
ShowResultCardView();
For example, the json response is :
{
"Response":[
{"from":"a","to":"bhduh"},{"from":"b","to":"eieja"},{"from":"tes","to":"neesj"}
]
}
String.replace() method won't work here, because first it will replace a to bhduh, then b to eieja, BUT here's the problem, it will convert b in bhduh to eieja, which i don't want to.
I want to perfectly convert the letters and "words" in the String according the Json, but that what i'm failing at .
New Code :
if(m_jArry.length() > 0){
HashMap<String, String> m_li;
EnteredString = EnteredText.getText().toString();
Log.i("TestAf_","Before Converting: " + EnteredString);
HashMap<String,String> replacements = new HashMap<String,String>();
for (int i = 0; i < m_jArry.length(); i++) {
JSONObject jo_inside = m_jArry.getJSONObject(i);
String Original = jo_inside.getString("from");
String To = jo_inside.getString("to");
if(isMethodConvertingIn){
//EnteredString = EnteredString.replace(" ","_");
replacements.put(Original,To);
Log.i("TestAf_","From: " + Original + " - To: " + To + " - Loop: " + i);
//EnteredString = EnteredString.replace(" ","_");
//EnteredString = EnteredString.replace(Original,To + " ");
} else {
EnteredString = EnteredString.replace("_"," ");
EnteredString = EnteredString.replace("'" + To + "'", Original);
}
}
Log.i("TestAf_","After Converting: " + replaceTokens(EnteredString,replacements));
// Replace Logic Here
// When Finish, Do :
LoadingProgress.setVisibility(View.GONE);
SetResultText(replaceTokens(EnteredString,replacements));
ShowResultCardView();
Output :
10-10 19:51:19.757 12113-12113/? I/TestAf_: Before Converting: ab a ba
10-10 19:51:19.757 12113-12113/? I/TestAf_: From: a - To: bhduh - Loop: 0
10-10 19:51:19.757 12113-12113/? I/TestAf_: From: b - To: eieja - Loop: 1
10-10 19:51:19.757 12113-12113/? I/TestAf_: From: o - To: neesj - Loop: 2
10-10 19:51:19.758 12113-12113/? I/TestAf_: After Converting: ab a ba
You question would be clearer if you gave the expected output for the function.
Assuming it is: ab b test a b >>>> bhduheieja eieja neesjt bhduh eieja
then see the following, the key point in the Javadoc being "This will not repeat"
http://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/StringUtils.html#replaceEach(java.lang.String,%20java.lang.String[],%20java.lang.String[])
Replaces all occurrences of Strings within another String.
A null reference passed to this method is a no-op, or if any "search
string" or "string to replace" is null, that replace will be ignored.
This will not repeat. For repeating replaces, call the overloaded
method.
Example 1
import org.apache.commons.lang3.StringUtils;
public class StringReplacer {
public static void main(String[] args) {
String input = "ab b test a b";
String output = StringUtils.replaceEach(input, new String[] { "a", "b", "tes" },
new String[] { "bhduh", "eieja", "neesj" });
System.out.println(input + " >>>> " + output);
}
}
Example 2
import org.apache.commons.lang3.StringUtils;
public class StringReplacer {
public static void main(String[] args) {
String input = "this is a test string with foo";
String output = StringUtils.replaceEach(input, new String[] { "a", "foo" },
new String[] { "foo", "bar"});
System.out.println(input + " >>>> " + output);
}
}
Try following:
Solution 1:
Traverse the String characters one by one and move the new String to a new StringBuffer or StringBuilder, then call toString() to get the result. This will need you to implement string matching algorithm.
Solution 2 (Using Regex):
For this, you must know the domain of your string. For example, it is [a-zA-Z] then other arbitrary characters (not part of domain) can be used for intermediate step. First replace the actual characters with arbitrary one then arbitrary ones with the target. In example below, [!##] are the arbitrary characters. These can be any random \uxxxx value as well.
String input = "a-b-c";
String output = input.replaceAll("[a]", "!").replaceAll("[b]", "#").replaceAll("[c]", "#");
output = output.replaceAll("[!]", "bcd").replaceAll("[#]", "cde").replaceAll("[#]", "def");
System.out.println("input: " + input);
System.out.println("Expected: bcd-cde-def");
System.out.println("Actual: " + output);
Your issue is quite common. To sum things up :
String test = "this is a test string with foo";
System.out.println(test.replace("a", "foo").replace("foo", "bar"));
Gives : this is bar test string with bar
Expected by you : this is foo test string with bar
You can use StrSubstitutor from Apache Commons Lang
But first you will have to inject placeholders in your string :
String test = "this is a test string with foo";
Map<String, String> valuesMap = new HashMap<>();
valuesMap.put("a", "foo");
valuesMap.put("foo", "bar");
String testWithPlaceholder = test;
// Preparing the placeholders
for (String value : valuesMap.keySet())
{
testWithPlaceholder = testWithPlaceholder.replace(value, "${"+value+"}");
}
And then, use StrSubstitutor
System.out.println(StrSubstitutor.replace(testWithPlaceholder, valuesMap));
It gives : this is foo test string with bar
Here is an method which is strictly just Java. I tried not to use any Java 8 methods here.
public static String translate(final String str, List<String> from, List<String> to, int index) {
StringBuilder components = new StringBuilder();
String token, replace;
int p;
if (index < from.size()) {
token = from.get(index);
replace = to.get(index);
p = 0;
for (int i = str.indexOf(token, p); i != -1; i = str.indexOf(token, p)) {
if (i != p) {
components.append(translate(str.substring(p, i), from, to, index + 1));
}
components.append(replace);
p = i + token.length();
}
return components.append(translate(str.substring(p), from, to, index + 1)).toString();
}
return str;
}
public static String translate(final String str, List<String> from, List<String> to) {
if (null == str) {
return null;
}
return translate(str, from, to, 0);
}
Sample test program
public static void main(String []args) {
String EnteredString = "aa hjkyu batesh a";
List<String> from = new ArrayList<>(Arrays.asList("a", "b", "tes"));
List<String> to = new ArrayList<>(Arrays.asList("bhduh", "eieja", "neesj"));
System.out.println(translate(EnteredString, from, to));
}
Output:
bhduhbhduh hjkyu eiejabhduhneesjh bhduh
Explaination
The algorithm is recursive, and it simply does the following
If a pattern found in the string matches a pattern in the from list
if there is any string before that pattern, apply the algorithm to that string
replace the found pattern with the corresponding pattern in the to list
append the replacement to the new string
discard the pattern in the from list and repeat the algorithm for the rest of the string
Otherwise append the rest of the string to the new string
You could use split like:
String[] pieces = jsonResponse.split("},{");
then you just parse the from and to in each piece and apply them with replace() then put the string back together again. (and please get your capitalization of your variables/methods right - makes it very hard to read the way you have it)
Apache Commons StringUtils::replaceEach does this.
String[] froms = new String[] {"a", "b"};
String[] tos = new String[] {"b","c"};
String result = StringUtils.replaceEach("ab", froms, tos);
// result is "bc"
Why not keep it very simple (if the JSON is always in same format, EG: from the same system). Instead of replacing from with to, replace the entire markup:
replace "from":"*from*" with "from":"*to*"
Why not just change the actual "to" and "from" labels? That way, you don't run into a situation where "bhudh" becomes "eieja". Just do a string replace on "from" and "to".
I'm using serial event to pass rfid tags read from arduino to processing. In the serial event I am parsing and converting the variable to an integer. This working for the most part, only one rfid card keeps throwing an error.
void serialEvent(Serial thisPort)
{
String inString = thisPort.readString();
if(inString != null)
{
Serial connect1 = (Serial) connections.get(0);
if(thisPort == connect1 )
{
Chair chair = (Chair) chairs.get(0);
if(inString.contains("UID Value:"))
{
int p2 = inString.indexOf(":");
String pString = inString.substring(p2+1);
String pString2 = pString.substring (0,10);
//println(pString2);
pString2.trim();
println("String length: " + pString2.length());
chair.setRFID(pString2);
println(pString2);
}
}
}
}
void setRFID(String r)
{
try{
this.rfid = Integer.parseInt(r);
}
catch (Exception e) {
e.printStackTrace();
}
//set position of person to chair
for (Person person : people)
{
//println(this.rfid != chair.rfid);
//println(this.rfid + "," + "person: " + person.ID + "," + person.RFID);
if(this.rfid == person.RFID)
{
person.setPos(this.pos);
this.personID = person.ID;
}
}
}
The try-catch is not working, and this line is causing the problem this.rfid = Integer.parseInt(r);. I thought it might be a malformed string but the strings seems ok. Here the results of checking string consistency:
String length: 10
1811524219
String length: 10
1942302231
String length: 10
1010368230
String length: 10
9813023219
9813023219 is an invalid Integer as it is greater than Integer.MAX_VALUE, which is 2147483647. Use Long instead, who's MAX_VALUE is 9223372036854775807.
You have exceeded the maximum value for an integer. I suggest using a long instead.
Check for this by displaying Integer.MAX_VALUE - no int can exceed this value.
java.long.NumberFormatException is thrown when a given string does not match the expected layout.
The number 9813023219 is out of range for int data type, try changing your data type to long and it should work.
9813023219 is Invalid Integer, You can use Long for your requirement. If RFID is not exceeding Long.MAX_VALUE.
I have to convert String into float I am doing it like this :
float[] iLongs = new float[mLongs.length];
for(int i = 0; i < iLongs.length ; i++){
iLongs[i] = Float.valueOf(mLongs[i]).floatValue();
}
But it throws numberformat exception
But if I use the same function outside any loop it works.
What to do ?
The code looks fine, which leads me to suspect that it's a data issue. You need to verify that every index for mLongs contains a String that is actually valid as a float, how you do that is up to you.
Alternative code :
class StringToFloat {
public static void main (String[] args) {
// String s = "hello"; // do this if you want an exception
String s = "100.00";
try {
float f = Float.valueOf(s.trim()).floatValue();
System.out.println("float f = " + f);
}
catch (NumberFormatException e) {
System.out.println("NumberFormatException: " + e.getMessage());
}
}
}
// Output :float f = 100.0
There is nothing wrong with your code.
Exception happend because String is not a Float and cannot be parsed. Most common mistake - , instead of .
You are correct syntactically. I think problem is in mLongs. It might contain some alphabetic character.
this must be quite simple but I am having great difficulty. You see I am trying to find a string within another string as follows.
e = input.indexOf("-->");
s = input.indexOf("<!--");
input = input.replace(input.substring(s, e + 3), " ");
The integers e and s are returning -1 in that it was not found and this is causing the replace method to fail. The test string I am using is "Chartered Certified<!--lol--> Accountants (ACCA)". I tried to creat a new string object and pass in the string as an argument as follows
e=input.indexOf(new String("<!--"));
This yielded the same result.
Any ideas ?
This is a stand alone piece of code I wrote and it works perfectly.
public static void main(String[] args) {
int e = 0;
int s = 0;
while (e != -1) {
//input.replace("\"", "\'");
e = input.indexOf("-->");
s = input.indexOf("<!--");
input = input.replace(input.substring(s, e + 3), " ");
e = input.indexOf("-->");
System.out.println(input);
}
}
But I cannot seem to see why it fails when i use this logic in my action class.
System.out.println("!Chartered Certified<!--lol--> Accountants (ACCA)".indexOf("-->"));
prints 27
So your input string must not be what you expect
String input = "Chartered Certified<!--lol--> Accountants (ACCA)";
int e = input.indexOf("-->");
int s = input.indexOf("<!--");
System.out.println(e+" "+s);
yields
26 19
so I think that there's an error somewhere else, is there other code in the middle?
The string "Chartered Certified Accountants (ACCA)" does not contain "-->" or "<!--", so e and s will always be -1.
Maybe you are obtaining the string from a sort of xml parser and hides the commented string on rendering. Check that the input string just before the indexOf call really has the '<!--' and '-->' strings inside.
I ran the test real quick using a command-line argument. It worked just fine. Here's the code/results:
public static void main(String[] args) {
String input = args[0];
System.out.println(input);
int e = input.indexOf("-->");
int s = input.indexOf("<!--");
input = input.replace(input.substring(s, e + 3), "");
System.out.println(input);
}
Output:
Chartered Certified<!--lol--> Accountants (ACCA)
Chartered Certified Accountants (ACCA)
If you were passing input as a command-line argument, make sure it is in quotes, or else input will be set to Chartered because of the spaces.
This code should work, there is some other problem. You should code it for safety though as shown below.
e = input.indexOf("-->");
s = input.indexOf("<!--");
if (e > -1 && s > -1 && e > s + 4) {
input = input.replace(input.substring(s, e + "-->".length()), " ");
}
Your code seems OK. So if it fails. it may be that the string it parses is not what you think it is. Where does the string come from? Try printing the string just before parsing it to see what it actually is.