Generate Any Random Number of Any Length in Java

How to generate fixed length random number without conflict?

From a comment, it seems that you are generating group codes for your own application.

For the purposes and scale of your app, 5-character codes may be appropriate. But there are several points you should know:

  • Random number generators are not designed to generate unique numbers. You can generate a random code as you're doing now, but you should check that code for uniqueness (e.g., check it against a table that stores group codes already generated) before you treat that code as unique.
  • If users are expected to type in a group code, you should include a way to check whether a group code is valid, to avoid users accidentally joining a different group than intended. This is often done by adding a so-called "checksum digit" to the end of the group code. See also this answer.
  • It seems that you're trying to generate codes that should be hard to guess. In that case, Math.random() is far from suitable (as is java.util.Random) — especially because the group codes are so short. Use a secure random generator instead, such as java.security.SecureRandom (fortunately for you, its security issues were addressed in Android 4.4, which, as I can tell from a comment of yours, is the minimum Android version your application supports; see also this question). Also, if possible, make group codes longer, such as 8 or 12 characters long.

For more information, see Unique Random Identifiers.


Also, there is another concern. There is a serious security issue if the 5-character group code is the only thing that grants access to that group. Ideally, there should be other forms of authorization, such as allowing only logged-in users or certain logged-in users—

  • to access the group via that group code, or
  • to accept invitations to join the group via that group code (e.g., in Google Classroom, the PERMISSION_DENIED error code can be raised when a user tries to accept an invitation to join a class).

Random Number generator in a range and then print length of the sequence

Consider using a while-loop:

import java.util.Random;

class Sequence {
public static void main(String[] args) {
Random r = new Random();
int count = 0;
int num = -1;
System.out.println("The sequence is:");
while (num != 0) {
num = r.nextInt(10);
System.out.print(num + " ");
count++;
}
System.out.printf("%nThe length of the sequence is: %d%n", count);
}
}

Example Output:

The sequence is:
3 9 3 9 4 0
The length of the sequence is: 6

Alternatively if you need to store the sequence in a collection:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

class Sequence {
public static void main(String[] args) {
Random r = new Random();
List<Integer> result = new ArrayList<>();
int num = -1;
while (num != 0) {
num = r.nextInt(10);
result.add(num);
}
System.out.printf("The sequence is: %s%n", result);
System.out.printf("The length of the sequence is: %d%n", result.size());
}
}

Problem to generate random unique numbers from fixed population length

You should generate the random numbers beforehand, so you are certain they are not repeated.

An easy way of doing this is to obtain a list of integers and then shuffle it.

For example:

// Obtain a list of integers from 0 to the size of population - 1
final List<Integer> integers = Stream.iterate(0, n -> n + 1)
.limit(population)
.collect(Collectors.toList());
// integers will have have [0, 1, 2, .... n]

// Then shuffle them
Collections.shuffle(integers);
// integers will have have something like [3, 66, 44, .... n] randomly

Check https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#shuffle-java.util.List-java.util.Random-

Generate a random integer with a specified number of digits Java

private long generateRandomNumber(int n) {
long min = (long) Math.pow(10, n - 1);
return ThreadLocalRandom.current().nextLong(min, min * 10);
}

nextLong produces random numbers between lower bound inclusive and upper bound exclusive so calling it with parameters (1_000, 10_000) for example results in numbers 1000 to 9999.
Old Random did not get those nice new features unfortunately. But there is basically no reason to continue to use it anyways.

Simple export and import of a SQLite database on Android

I use this code in the SQLiteOpenHelper in one of my applications to import a database file.

EDIT: I pasted my FileUtils.copyFile() method into the question.

SQLiteOpenHelper

public static String DB_FILEPATH = "/data/data/{package_name}/databases/database.db";

/**
* Copies the database file at the specified location over the current
* internal application database.
* */
public boolean importDatabase(String dbPath) throws IOException {

// Close the SQLiteOpenHelper so it will commit the created empty
// database to internal storage.
close();
File newDb = new File(dbPath);
File oldDb = new File(DB_FILEPATH);
if (newDb.exists()) {
FileUtils.copyFile(new FileInputStream(newDb), new FileOutputStream(oldDb));
// Access the copied database so SQLiteHelper will cache it and mark
// it as created.
getWritableDatabase().close();
return true;
}
return false;
}

FileUtils

public class FileUtils {
/**
* Creates the specified <code>toFile</code> as a byte for byte copy of the
* <code>fromFile</code>. If <code>toFile</code> already exists, then it
* will be replaced with a copy of <code>fromFile</code>. The name and path
* of <code>toFile</code> will be that of <code>toFile</code>.<br/>
* <br/>
* <i> Note: <code>fromFile</code> and <code>toFile</code> will be closed by
* this function.</i>
*
* @param fromFile
* - FileInputStream for the file to copy from.
* @param toFile
* - FileInputStream for the file to copy to.
*/
public static void copyFile(FileInputStream fromFile, FileOutputStream toFile) throws IOException {
FileChannel fromChannel = null;
FileChannel toChannel = null;
try {
fromChannel = fromFile.getChannel();
toChannel = toFile.getChannel();
fromChannel.transferTo(0, fromChannel.size(), toChannel);
} finally {
try {
if (fromChannel != null) {
fromChannel.close();
}
} finally {
if (toChannel != null) {
toChannel.close();
}
}
}
}
}

Don't forget to delete the old database file if necessary.

Export and import SQLite database

FileNotFoundException is likely due to the directory teste not existing, perhaps due to permissions.

Using :-

private void backupDatabase () throws IOException {
String inFileName = "/data/data/com.gnd.example/databases/dados.db";
File dbFile = new File (inFileName);
FileInputStream fis = new FileInputStream (dbFile);

String outFileName = Environment.getExternalStorageDirectory () + "/ example / backup / data.db";
//<<<<<<<<<<< CODE ADDED >>>>>>>>>>
File os = new File(outFileName);
if (!os.getParentFile().exists()) {
os.getParentFile().mkdirs();
}
//<<<<<<<<<< END Of ADDED CODE >>>>>>>>>>
OutputStream output = new FileOutputStream(os); //<<<<<<<<<< CHANGED
byte [] buffer = new byte [1024];
int length;
while ((length = fis.read (buffer))> 0) {
output.write (buffer, 0, length);
}
output.flush ();
output.close ();
fis.close ();
}

will create the directories if they do not exist (assuming permissions are correct)

Working Example :-

The following is a working app

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="aso.so56843045backup">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
  • Note the <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> (for earlier devices)

ExternalStoragePermissions.java

class ExternalStoragePermissions {

public int API_VERSION = Build.VERSION.SDK_INT;
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {

//Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
public static final String THISCLASS = ExternalStoragePermissions.class.getSimpleName();
private static final String LOGTAG = "SW_ESP";

public ExternalStoragePermissions() {}
// Note call this method
public static void verifyStoragePermissions(Activity activity) {
int permission = ActivityCompat.checkSelfPermission(
activity,
Manifest.permission.WRITE_EXTERNAL_STORAGE);

if(permission != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
activity,
PERMISSIONS_STORAGE,
REQUEST_EXTERNAL_STORAGE
);
}
}
}
  • If permissions not given then the directories cannot be created resulting in FileNotFoundException.

DBHelper.java

public class DBHelper extends SQLiteOpenHelper {

public static final String DBNAME = "dados.db";
public static final int DBVERSION = 1;

public DBHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
this.getWritableDatabase();
}

@Override
public void onCreate(SQLiteDatabase db) {

}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}
}
  • A Very basic empty database (exception android_metadata table), enough to check backup.

MainActivity.java

public class MainActivity extends AppCompatActivity {

DBHelper mDBHlpr;
Button mBackup;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBackup = this.findViewById(R.id.backup);
mBackup.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDBHlpr.close();
try {
backupDatabase();
} catch (IOException e) {
e.printStackTrace();
}
}
});
ExternalStoragePermissions.verifyStoragePermissions(this);
mDBHlpr = new DBHelper(this);
}

private void backupDatabase () throws IOException {
FileInputStream fis = new FileInputStream (this.getDatabasePath("dados.db").getPath());
String outFileName = Environment.getExternalStorageDirectory () + "/example/backup/" + String.valueOf(System.currentTimeMillis()) + "data.db";
Log.d("OSFILEPATH",outFileName);
File os = new File(outFileName);
if (!os.getParentFile().exists()) {
os.getParentFile().mkdirs();
}
OutputStream output = new FileOutputStream(os);
byte [] buffer = new byte [1024];
int length;
while ((length = fis.read (buffer))> 0) {
output.write (buffer, 0, length);
}
output.flush ();
output.close ();
fis.close ();
}
}

Notes

  • When first run after install permission will be requested for later devices (click allow).

  • Backup has been named with a timestamp so multiple backups can exist.

  • Database is closed, (this should cope with Android Pie+ wehere default is WAL mode, the close should empty (commit the changes) the -wal and -shm files, thus negating the need to backup the additional files).

Result

enter image description here



Related Topics



Leave a reply



Submit