Making sure no two random lines are the same. - java

The following code works great for picking random lines from a file. How do I make sure that no two lines occurs since random may repeat the same line again.
BufferedReader reader = new BufferedReader(new FileReader(file));
List<String> lines = new ArrayList<String>();
String line = reader.readLine();
while( line != null ) {
lines.add(line);
line = reader.readLine();
}
Random r = new Random();
int i = 0;
while(i < 4){
System.out.println(lines.get(r.nextInt(lines.size())));
i++;
}

Simple: Use a Set to keep track of which lines you've already used. Here, I added a check to make sure there is actually enough lines in the file to avoid an infinite loop.
// Number of lines to print
final int PRINT_COUNT = 4;
// Check to make sure there are actually 4 lines in the file
if(lines.size() < PRINT_COUNT)
throw new IllegalStateException("Too few lines in file. Total lines="+lines.size());
// Declare a set to record which lines were selected
Set<Integer> chosen = new HashSet<>();
Random r = new Random();
for(int i = 0; i < PRINT_COUNT;) {
int nextInt = r.nextInt(lines.size());
if(!chosen.contains(nextInt)){
chosen.add(nextInt);
System.out.println(lines.get(nextInt));
i++;
}
}
Note: As a general rule, you want to reduce the scope of variables. For this reason, I converted your while-loop to a for-loop and only increment i when a unique line number is found.

Related

FileInputStream read multiple lines inside while loop due to if condition

Actually this is my code :
inputStream = new FileInputStream(file);
sc = new Scanner(inputStream, "UTF-8");
while (sc.hasNextLine()) {
String line = sc.nextLine();
if(line.contains("blablbal") {
// **take the next five line and put them inside string or something**
}
}
Is it possible to take the next five lines and put them inside string object?
And if there is another occurrence of the condition within these 5 lines how to treat that case?
Any idea?
Definitely you can. Actually the only thing you have to do is to invoke a method doWhatYouWantToDoInCaseOfYourDesire
Do you want to read 5 lines below the given? ok - just create a method that contains a check for a your's condition, contains a counter inside and loop inthere.
But the question is what are you going to do if there is another occurence of your condition within these 5 lines?
I believe it's not enough description for this case
Try with below code:-
String[] lines = new String[20];
//if you want to store more lines increase the size of the array
int j = 0;
//manage below while loop condition j < 20 based on array size and change the
//number from 20 to that number. For example if array size 50 make j < 50
while (sc.hasNextLine() && j < 20) {
String line = sc.nextLine();
if(line.contains("blablbal") {
int i = 0;
while(sc.hasNextLine() && i < 5){
line = sc.nextLine();
if(line.contains("blablbal") {
continue;
}
lines[j++] = line;
i++;
if ( j >= 20 )//change this according to the size of array as well
break;
}
}

Reading from a file in java and save the int numbers from the txt in array

I am really new in java and I am trying to improve by exercising at home. I have this problem with my program, I can't save the int numbers from the txt file that I am reading in an array so I can work on it.
My new code
i is out-of-scope in the print statement.
It will only be available in the for block. Whereas your print statement is outside the for loop.
It should be surrounded by a {} block to make it available for more than 1 statement.
for(int i =0; i < array.length; i++){
array[i] = in.nextInt();
System.out.println(array[i]);}
You are doing:
int []array=new int[num];
which creates an array of length 1, since you do
num = in.nextInt();
You could for example use a List<Integer> intList = new ArrayList<Integer>() then you can add your ints to the list in your loop.
Use BufferReader to read the txt
BufferedReader br = new BufferedReader(new FileReader("/home/input.txt"));
Then all you need to do is iterate through using br.readLine() and assign it to an array as below:
while ((sCurrentLine = br.readLine()) != null) {
array[i]= Integer.parseInt(sCurrentLine);
i++;
}
for(int j=0;j<array.length;j++){
System.out.println(array[j]);
}

Data from file not reading into array

I'm trying to read a 2D array into a file. On compiling, it says that readFile, the Scanner variable may be uninitialized (which I know is because the initialization is in the try catch blocks). When I set readFile to null, however, it manages to count the number of lines but skips everything else.
Do I need to close and remake the scanner and file stuff for the actual reading in of the data? Or is there another error that I'm missing somewhere?
Also, I'm aware that the code for the actual reading in of the 2d array isn't done in the code sample below, but I'm trying to make sure it reads in correctly before I do anything else.
//2D table example I'm trying to read in
0 1 1 0
1 0 0 0
1 0 0 1
0 0 1 0
boolean[][] relationTable;
Scanner keyboard = new Scanner(System.in);
String fileName;
File relationFile;
Scanner readFile;
boolean error = false;
System.out.print("Please enter the name of the table file: ");
do{
fileName = keyboard.next();
try
{
relationFile = new File(fileName);
readFile = new Scanner(relationFile);
error = false;
}
catch(FileNotFoundException fnfe)
{
System.out.println("File was not found. Please enter a new file name:");
error = true;
}
}while (error == true);
//finds number of lines correctly
int count = 0;
while (readFile.hasNextLine())
{
count++;
readFile.nextLine(); //notes the error here when not initialized
}
System.out.println(count); //using the example table above it prints out 4
relationTable = new boolean[count][count];
int i = 0, j = 0, temp = 0;
//doesn't appear to do this section at all.
String[] lines= new String[count];
while (readFile.hasNextLine())
{
lines[i] = readFile.nextLine();
System.out.println(lines[i]);
i++;
}
// finds number of lines correctly
int count = 0;
List<String> lines = new ArrayList<String>();// use arrayList instead of arrays if you dont know the number of lines like we have here.
while (readFile.hasNextLine()) {
count++;
lines.add(readFile.nextLine()); // notes the error here when not
// initialized
}
System.out.println(count); // using the example table above it prints
// out 4
relationTable = new boolean[count][count];
int i = 0, j = 0, temp = 0;
your mistake here is that you were looping using readFile.hasNextLine() but the file was already read and readFile.hasNextLine() always returned false
// here is a loop that works even though its not needed, we could have added the print statement in the loop above.
for (int x = 0; x < count; x++) {
System.out.println(lines.get(x));
}
The problem is that you're already gone through all the lines in the file.
while (readFile.hasNextLine())
{
count++;
readFile.nextLine(); //notes the error here when not initialized
}
After this point, your readFile object has not more lines left. So when you reach
String[] lines= new String[count];
while (readFile.hasNextLine())
{
lines[i] = readFile.nextLine();
System.out.println(lines[i]);
i++;
}
There are not lines left. So in order to solve your problem you have to read the file again before the second while.
relationFile = new File(fileName);
readFile = new Scanner(relationFile);

Reading from a text file into an array - getting "nulls"

I'm reading from a file and copying that into an array. My file has five lines of text, a sentence each. I get my output "Array size is 5" but nothing after that. If I do add a print line of the array, it gives me 5 nulls...
Can someone help explain what I did wrong? Thanks!
public static int buildArray() throws Exception
{
System.out.println("BuildArray is starting ");
java.io.File textFile; // declares a variable of type File
textFile = new java.io.File ("textFile.txt"); //reserves the memory
Scanner input = null;
try
{
input = new Scanner(textFile);
}
catch (Exception ex)
{
System.out.println("Exception in method");
System.exit(0);
}
int arraySize = 0;
while(input.hasNextLine())
{
arraySize = arraySize + 1;
if (input.nextLine() == null)
break;
}
System.out.println("Array size is " + arraySize);
// Move the lines into the array
String[] linesInRAM = new String[arraySize];// reserve the memory
int count = 0;
if (input.hasNextLine())
{
while(count < arraySize)
{
System.out.println("test");
linesInRAM[count] = input.nextLine();
System.out.println(linesInRAM[count]);
count = count + 1;
}
}
In this code
int count = 0;
if (input.hasNextLine())
The above hasNextLine will always be false as you have already read all the way through the file.
Either reset the scanner to the beginning of the file, or use a dynamic list e.g. ArrayList to add the elements to.
My Java is a bit rusty, but the basic gist of my answer is that you should create a new Scanner object so that it reads from the beginning of the file again. This is the easiest way to "reset" to the beginning.
Your code is currently not working because when you call input.nextLine() you're actually incrementing the scanner, and thus at the end of that first while() loop input is sitting at the end of the file, so when you call input.nextLine() again it returns null.
Scanner newScanner = new Scanner(textFile);
Then in the bottom of your code, your loop should look like this instead:
if (newScanner.hasNextLine())
{
while(count < arraySize)
{
System.out.println("test");
linesInRAM[count] = newScanner.nextLine();
System.out.println(linesInRAM[count]);
count = count + 1;
}
}

A Good Method to read files in Java

I Really would appreciate it if someone can help me with this. I am trying to do external sorting and I am stuck on the part of merging. I get how I should merge it just not sure what function to use.
Right now I am trying to read in the first words of multiple small text files and store them in a string array of the size of the amount of files. So basically I will have a string array of the first word of each file. Then I determine which one is the smallest alphabetically wise and write that to a new file, after that I would read the next word of the file of that smallest word. This word would be placed in the position of the smallest word that got outputted in string array and compare it to the rest of the first word from the other file. This will keep repeating till all words are sorted.
The main problem I am running into is the fact that I was using scanner and after the first run of comparing it cant switch the smallest word with the next word in the file because scanner don't keep a point of what it has read. I know readline do but since my files are all words separated by only a white space I can't use readline. Can someone please guide me to a sufficient reading function that can't help me solve this problem.
for (int i = 0; i<B;i++)
{
try
{
BufferedReader ins = new BufferedReader(new FileReader(Run-"+ i + ".txt"));
Scanner scanner2 = new Scanner(ins);
temp3[i] = scanner2.next();
System.out.println(temp3[i]);
}
catch(IOException e)
{
}
}
for(int i=0;i<N;i++)
{
String smallest = temp3[0];
int smallestfile = 0;
for(j=0;j<B;j++)
{
int comparisonResult = smallest.compareTo(temp3[j]);
if(comparisonResult>0)
{
smallest = temp3[j];
smallestfile = j;
}
}
BufferedReader ins = new BufferedReader(new FileReader("C:/Run-"+ smallestfile + ".txt"));
Scanner scanner2 = new Scanner(ins);
if(scanner2.hasNext())
{
temp3[smallestfile]=scanner2.next();
}
}
}
catch(Exception e)
{
}
If the files are small enough read the entire file to memory, and use String.split() to separate the strings in arrays and do your magic.
If the the files are bigger, keep then open and read each byte until you find and space, then do it for all the files, compare the strings, do your magic and repeat until all the files reach the end.
EDIT :
how to read the files with BufferedReader
how to split the lines with String.split()
String line = readeOneLineFromTheCurrentFile();
String[] words = line.split(" ");
As for temporarily sorting/storing the words, use a PriorityQueue (not an array). Sorry, I'm too busy watching baseball to add more.
I'm not sure, if I understood you right, but a Scanner does keep the position in a file. You need just as many of them as there are files
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class so {
// returns the index of the smallest word
// returns -1 if there are no more words
private static int smallest(String[] words) {
int min = -1;
for (int i = 0; i < words.length; ++i)
if (words[i] != null) {
if (min == -1 || words[i].compareTo(words[min]) < 0)
min = i;
}
return min;
}
public static void main(String[] args) throws FileNotFoundException {
// open all files
Scanner[] files = new Scanner[args.length];
for (int i = 0; i < args.length; ++i) {
File f = new File(args[i]);
files[i] = new Scanner(f);
}
// initialize first words
String[] first = new String[args.length];
for (int i = 0; i < args.length; ++i)
first[i] = files[i].next();
// compare words and read following words from scanners
int min = smallest(first);
while (min >= 0) {
System.out.println(first[min]);
if (files[min].hasNext()) {
first[min] = files[min].next();
} else {
first[min] = null;
files[min].close();
files[min] = null;
}
min = smallest(first);
}
}
}
Tested with
a.txt: a d g j
b.txt: b e h k m
c.txt: c f i
Update:
In your example, you open and close the file inside the outer for loop. When you reopen a file the next time, it starts at the beginning of the file, of course.
To prevent this, you must keep the file open and move the scanner2 variable and its initialization in front of the outer for loop. You also need multiple Scanner variables, i.e. an array, to keep multiple files open simultaneously.

Categories