how to reduce length of UUID generated using randomUUID( ) - java

I have a short utility in which I am generating a UUID using randomUUID().
String uuid = UUID.randomUUID().toString();
However, the uuid generated is too long which is 36 in length.
Is there any way I can reduce the length of the UUID from 36 to near 16 or make the UUID length dynamic?

If you don't need it to be unique, you can use any length you like.
For example, you can do this.
Random rand = new Random();
char[] chars = new char[16];
for(int i=0;i<chars.length;i++) {
chars[i] = (char) rand.nextInt(65536);
if (!Character.isValidCodePoint(chars[i]))
i--;
}
String s = new String(chars);
This will give you almost the same degree of randomness but will use every possible character between \u0000 and \ufffd
If you need printable ASCII characters you can make it as short as you like but the likelihood of uniqueness drops significantly. What can do is use base 36 instead of base 16
UUID uuid = UUID.randomUUID();
String s = Long.toString(uuid.getMostSignificantBits(), 36) + '-' + Long.toString(uuid.getLeastSignificantBits(), 36);
This will 26 characters on average, at most 27 character.
You can use base64 encoding and reduce it to 22 characters.
If you use base94 you can get it does to 20 characters.
If you use the whole range of valid chars fro \u0000 to \ufffd you can reduce it to just 9 characters or 17 bytes.
If you don't care about Strings you can use 16, 8-bit bytes.

String uuid = String.format("%040d", new BigInteger(UUID.randomUUID().toString().replace("-", ""), 16));
String uuid16digits = uuid.substring(uuid.length() - 16);
This will return the last 16 digits of actual uuid.

Convert it from base 16(0-9,A-F) to base 36(0-9,A-Z).. You could go to base 62 (0-9, A-Z, a-z) but if you need to read it over a phone or something then this can be error prone.
https://github.com/salieri/uuid-encoder is a lib that might work for you...
Also this means you still have a GUID -you haven't truncated it like the other answers

You can use the substring method to decrease the string length while generating uuid.
UUID.randomUUID().toString().substring(0, 5)

You could evaluate using the ${__time()} function

The following snippet is a dynamic UUID code. By default, the legth of the UUID depends on bits but the function randomly chooses characters from the UUID
public String myUUID(int length) {
String allChars = UUID.randomUUID().toString().replace("-", "");
Random random = new Random();
char[] otp = new char[length];
for (int i = 0; i < length; i++) {
otp[i] =
allChars.charAt(random.nextInt(allChars.length()));
}
return String.valueOf(otp);
}

Yes,You can create by using this function.
public static String shortUUID() {
UUID uuid = UUID.randomUUID();
long l = ByteBuffer.wrap(uuid.toString().getBytes()).getLong();
return Long.toString(l, Character.MAX_RADIX);
}

Related

(JAVA) convert decimal to Binary coded decimal?

For example, I would like to convert the int value 12 into a String output of BCD: 00 12 (0x00 0x12).
If I have int value of 256, it will be 02 56 (which is 0x02 0x56),
or if I have a int value of 999, it will be 09 99 (0x09 0x99),
9999 would be 99 99 (0x99 0x99).
Right now, my only solution is to create a String array of size 4, and calculate how many characters are there by converting the int value into String. If there are 2 characters, I will add 2 x 0 into the array first before adding the 2 characters, and then make them back into a single String variable.
Basically,
int value = 12;
String output = Integer.toString(value);
// then count the number of characters in the String.
// 4 minus (whatever number of characters in the String, add zeros
// add the characters:
stringArray[0] = "0";
stringArray[1] = "0";
stringArray[2] = "1";
stringArray[3] = "2";
// then, concatenate them back
If there are 3 characters, I will add one 0 into the array first before adding 3 characters. I was wondering if there is any other way?
You can use String.format to append leading 0 and use substring to split in to two part.
int value = 12;
String output = String.format("%04d",value);
System.out.println(output.substring(0,2)+" "+output.substring(2,4));
String.format("%04d",value) will append 0s in the front if the length is less than 4.
If you do not want to use substring you can use String.split and String.join like below.
System.out.println(
String.join(
" ",
Arrays.asList(
output.split("(?<=\\G.{2})")
)
)
);
output.split("(?<=\\G.{2})") will split the string in 2 characters each.
Is that what you are asking for?
public static String formatTheString(String string, int length) {
return String.format("%"+length+"s", string).replace(' ', '0');
}
and pass the values like
formatTheString(Integer.toString(256),4);
I think what you are asking is not correct.
refer this for BCD.
and below code is sufficient for what you need
System.out.printf("%04d",n);
in above code n is your number.

Add zeros to the left of Number

I know that I can add left zeros to String but what about Long?
I need to put left zeros until the Long size is 10 digits. For example, if it's 8 digits (12345678), it should add 2 left zeros (0012345678)
I want to add this in the getValue() method.
public Long getValue() {
// Should always be 10 digits, If it's 8, add zeros
return value;
}
I'm using spring. This issue is that the database that cuts the left zeros. Maybe is there a annotation to avoid extra code?
This is not possible. A Long does not contain data about the String representation of its value. In fact, the Long is actually stored in binary, not decimal, and the long object is unaware of this.
If you want to convert it to a String with leading zeroes, String.format("%017d" , number); will pad it to make sure it has 10 digits.
In java, a long (wrapped in a Long) will always be stored on 8 bytes,
There is no way to "add" extra zeros as they're already existing.
Either your database must change its type to String and add padding zeros when you store your Long object either change your inner code to String and add padding zeros when you pull the data from your Long in db.
You cannot because a long does not have a leading zero.
A string of characters like 0012345678 is not an integer, 12345678 is.
but there are two way in java to add leading zeroes
WAY 1: format() method
int number = 9;
String str = String.format("%04d", 9); // 0009
System.out.printf("original number %d, numeric string with padding : %s", 9, str);
WAY 2 : DecimalFormat
DecimalFormat df = new DecimalFormat("0000");
String c = df.format(9); // 0009
String a = df.format(99); // 0099
String b = df.format(999); // 0999
but in both case you get string instead of Long
for more reading
Try this one,
int number = 12345678;
String str = String.format("%10d", number);
System.out.println("original number %d, numeric string with padding : %s", number, str);

generate random String that must Contains alphabets, number and Special Character (6-10 digits)

I am generating a password which will have 6 to 10 digit.
This is my code which gives me random password of 6-10 digit,
val AB = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:<=>?#_!#%&()*+,-.~";
val rnd = new Random();
def randomPassword(): String = {
val len = rnd.nextInt(5) + 5
val sb = new StringBuilder(len);
for (i <- 0 to len)
sb.append(AB.charAt(rnd.nextInt(AB.length())));
return sb.toString();
}
It works fine but the problem is that sometimes it gives all numbers or alphabets.
I want the combination of alphabets and number and special character every time. any suggestion?
Here is a more idiomatic solution to the problem which provides a better API.
object password {
import scala.util.Random
import scala.collection.immutable.Stream
private def gen = Random.alphanumeric
def get(len: Int): String = {
def build(acc: String, s: Stream[Char]): String = {
if (s.isEmpty) acc
else build(acc + s.head, s.tail)
}
build("", gen take len)
}
}
Lets generate some passwords
1 to 25 foreach { _ => println(password get 8) }
You will see something like
YBk2UrOV
GD4eLexS
l8yxAkp9
ooQnaRpd
NgHAruB8
pMXpi4ad
Note: this solution can go a couple of optimization rounds. E.g. #tailrec, StringBuilder.
def randomPassword(): String = {
val len = rnd.nextInt(5) + 5
val sb = new StringBuilder(len);
for (i <- 0 to len)
sb.append(AB.charAt(rnd.nextInt(AB.length())));
if(sb.toString is allString or allNum){
return randomPassword();
}
return sb.toString();
}
The simple solution imho would be (pseudo code)
generate password
if no alphabet;
if not max length;
add an alphabet
else
change last letter with an alphabet
if no digit;
if not max length;
add an digit
else
change first letter with an digit
if no special;
if not max length;
add an special
else
change second letter with an special
This never reduce entropy unless you already have a max length password.
Generate a random password of all letters first, then replace some of the letters with numbers/special characters as you desire.
(By the way, I'm not familiar with Scala, so I'm going to use Java's syntax, as I wouldn't know whether I'm typing something valid otherwise. My apologies.)
// Split source string into letters, numbers, and specials
String AB = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
String numbers = "0123456789";
String specials = ":<=>?#_!#%&()*+,-.~";
String randomPassword() {
StringBuilder sb = new StringBuilder();
int len = rnd.nextInt(5) + 5;
// Generate password with letters first. This part is the same as the original code.
for (int i = 0; i <= len; i++) {
sb.append(AB.charAt(rnd.nextInt(AB.length())));
}
// Generate an index to replace with a number
int numberIndex = rnd.nextInt(len);
// Generate an index to replace with a special character
int specialIndex;
do {
specialIndex = rnd.nextInt(len);
} while (specialIndex == numberIndex);
// Replace one letter with a number
sb.setCharAt(numberIndex, numbers.charAt(rnd.nextInt(numbers.length())));
// Replace one letter (or the number if you're unlucky) with a special character
sb.setCharAt(specialIndex, specials.charAt(rnd.nextInt(specials.length())));
}
It's a start, and has a flaw (only one number + special character), but it is easily fixable. This solution is also more efficient than generating entirely new passwords if one does not satisfy your criteria, and you're guaranteed to get a password that works when the method returns.
Using immutable data structures is more idiomatic to scala. The following code works.
protected def nextChar(): Char = Random.nextPrintableChar()
def randomString(length: Int = 10): String = {
(0 until length).map(_ => nextChar()).mkString
}
edit:
To ensure there's always a number, special character, and alphabet in string, i would generate each category of letters separately then randomly concatenate them in a functional way or simply with Random.shuffle(characterList).mkString =D.
You could do apply the principle of the while loop.
Store the appended password into a variable.
Use a while loop to check if it doesn't contain a number and/or symbol, if it doesn't, regenerate the password again and store it into the variable.
When the while loop breaks automatically, return the variable.
You can try this one, it works for me.
$length = 45;
$chars = array_merge(range(0,9), range('a','z'), range('A','Z'));
shuffle($chars);
$password = implode(array_slice($chars, 0, $length));
echo "This is the password: ".$password;
An example of output:
This is the password: wmU7KaZoOCIf4qn2tz5E06jiQgHvhR9dyBxrFYAePcDWk

How to generate a random numeric string + random char string and combine?

What I'm trying to do is to generate a random string of numbers E.G 2645237 and one char in a string in the range of A-Z E.G. W and combine the two strings to make 2645237W. I can generate a random number no problem. What I'm stuck on is: 1. Generating a random Char as a string. 2. Combining the two strings to create one string. To be clear what it's for is a school assignment to achieve some extra credit in my marking. Like always I'm not looking for the full answer. Some pseudo-code or a working example would be fine but I'd like the final "A-HA!" moment to be my own doing. A final parameter. This end result (the one string) would need to be a generated 50 times differently (I can do this) and then used as a sort of password. (Meant to replicate a PPS number, the added char is the bit that has my whole class stumped).
I'm not looking to cheat my way to a coded answer, just stuck on this problem (We've all been there)
You can generate a random character simply by doing 'a' (or 'A' for upper case) and then generating a random number from 0 to 25 and adding that to it. i.e. 'a'+3 is 'd'. Note the use of a single quote character to say this is a char literal as opposed to the double quote for a String literal.
That random character can then be appended to the string. StringBuilder would do it for you easily, I'm not sure off hand what the String + operator will do with it.
Try,
Random rn = new Random();
int range = 9999999 - 1000000 + 1;
int randomNum = rn.nextInt(range) + 1000000; // For 7 digit number
System.out.println(randomNum);
Random rc = new Random();
char c = (char)(rc.nextInt(26) + 'A');
System.out.println(c);
String str = randomNum+""+c;
System.out.println(str);
str prints like 1757217Y
To generate the letter and append on your number sequence:
String msg1 = "random number sequence";
Random gen = new Random();
char c = (char) (65 + gen.nextInt(26));
StringBuilder sb = new StringBuilder();
sb.append(msg1);
sb.append(c);
String result = sb.toString();
System.out.println(result);
By the way, 65 is the ascii code of the letter 'A' and gen.nextInt(26) generates a number between 0 and 25, ie, we have a range between 65 and 90 which are the letters' A'-'Z' in ascii table

How to convert hex strings to byte values in Java

I have a String array.
I want to convert it to byte array.
I use the Java program.
For example:
String str[] = {"aa", "55"};
convert to:
byte new[] = {(byte)0xaa, (byte)0x55};
What can I do?
String str = "Your string";
byte[] array = str.getBytes();
Looking at the sample I guess you mean that a string array is actually an array of HEX representation of bytes, don't you?
If yes, then for each string item I would do the following:
check that a string consists only of 2 characters
these chars are in '0'..'9' or 'a'..'f' interval (take their case into account
as well)
convert each character to a corresponding number, subtracting code value of '0' or 'a'
build a byte value, where first char is higher bits and second char is lower ones. E.g.
int byteVal = (firstCharNumber << 4) | secondCharNumber;
Convert string to Byte-Array:
byte[] theByteArray = stringToConvert.getBytes();
Convert String to Byte:
String str = "aa";
byte b = Byte.valueOf(str);
You can try something similar to this :
String s = "65";
byte value = Byte.valueOf(s);
Use the Byte.ValueOf() method for all the elements in the String array to convert them into Byte values.
A long way to go :). I am not aware of methods to get rid of long for statements
ArrayList<Byte> bList = new ArrayList<Byte>();
for(String ss : str) {
byte[] bArr = ss.getBytes();
for(Byte b : bArr) {
bList.add(b);
}
}
//if you still need an array
byte[] bArr = new byte[bList.size()];
for(int i=0; i<bList.size(); i++) {
bArr[i] = bList.get(i);
}
Since there was no answer for hex string to single byte conversion, here is mine:
private static byte hexStringToByte(String data) {
return (byte) ((Character.digit(data.charAt(0), 16) << 4)
| Character.digit(data.charAt(1), 16));
}
Sample usage:
hexStringToByte("aa"); // 170
hexStringToByte("ff"); // 255
hexStringToByte("10"); // 16
Or you can also try the Integer.parseInt(String number, int radix) imo, is way better than others.
// first parameter is a number represented in string
// second is the radix or the base number system to be use
Integer.parseInt("de", 16); // 222
Integer.parseInt("ad", 16); // 173
Integer.parseInt("c9", 16); // 201
String source = "testString";
byte[] byteArray = source.getBytes(encoding);
You can foreach and do the same with all the strings in the array.
The simplest way (using Apache Common Codec):
byte[] bytes = Hex.decodeHex(str.toCharArray());
String str[] = {"aa", "55"};
byte b[] = new byte[str.length];
for (int i = 0; i < str.length; i++) {
b[i] = (byte) Integer.parseInt(str[i], 16);
}
Integer.parseInt(string, radix) converts a string into an integer, the radix paramter specifies the numeral system.
Use a radix of 16 if the string represents a hexadecimal number.
Use a radix of 2 if the string represents a binary number.
Use a radix of 10 (or omit the radix paramter) if the string represents a decimal number.
For further details check the Java docs: https://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#parseInt(java.lang.String,%20int)
Here, if you are converting string into byte[].There is a utility code :
String[] str = result.replaceAll("\\[", "").replaceAll("\\]","").split(", ");
byte[] dataCopy = new byte[str.length] ;
int i=0;
for(String s:str ) {
dataCopy[i]=Byte.valueOf(s);
i++;
}
return dataCopy;

Categories

Resources