I am writing a program that should create a file and then generate a unique id , read the file and if any duplicates are present in it generate a new id and repeat the check.
As of now I am able to create the id and write into the file. But my issue is I' m not able to check if any duplicates are present in the file.
Here is the code which I tried:
public class Main {
public static void main(String a[]) throws IOException {
File file = new File("text.txt");
file.createNewFile();
FileWriter filewriter = new FileWriter(file.getAbsoluteFile(), true);
filewriter.write("\r\n");
BufferedWriter bw = new BufferedWriter(filewriter);
String alphanumeric = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
// randomInteger = random.nextInt();
sb.append(alphanumeric.charAt(random.nextInt(alphanumeric.length())));
}
System.out.println("\n Random Alphanumeric in Java: " + sb.toString());
// reading data from file
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String string;
while((string = br.readLine()) != null) {
if(string.equals(sb.toString())) {
for (int i = 0; i < 10; i++) {
// randomInteger = random.nextInt();
sb.append(alphanumeric.charAt(random.nextInt(alphanumeric.length())));
}
bw.write((sb.toString()));
System.out.println("new value :" + sb.toString());
}
else{
System.out.println("existing value :" +sb.toString());
}
}
System.out.println(sb.toString());
} catch (FileNotFoundException fnfe) {
System.out.println("File not found!!");
}
}
}
There are several things wrong here
1:
if(string.equals(sb.toString())) {
for (int i = 0; i < 10; i++) {
// randomInteger = random.nextInt();
sb.append(alphanumeric.charAt(random.nextInt(alphanumeric.length())));
}
bw.write((sb.toString()));
System.out.println("new value :" + sb.toString());
}
This adds to the existing id as sb is never reset to empty.
2:
What you are doing now is:
generate id
for each line L do
if L equals id
append to ID
write id
else
some output
end for
What you should be doing:
while not inserted
generate id
for each line L do
if L equals id
found = true
break // exit for each
end for
if found
continue //restart while loop
insert into file // we only get here if it was not found
inserted = true
end while
For better performance first read all the IDs into a list and use it to check for existing ids instead of reading the file every time.
Related
I have the following code which counts and displays the number of times each word occurs in the whole text document.
try {
List<String> list = new ArrayList<String>();
int totalWords = 0;
int uniqueWords = 0;
File fr = new File("filename.txt");
Scanner sc = new Scanner(fr);
while (sc.hasNext()) {
String words = sc.next();
String[] space = words.split(" ");
for (int i = 0; i < space.length; i++) {
list.add(space[i]);
}
totalWords++;
}
System.out.println("Words with their frequency..");
Set<String> uniqueSet = new HashSet<String>(list);
for (String word : uniqueSet) {
System.out.println(word + ": " + Collections.frequency(list,word));
}
} catch (Exception e) {
System.out.println("File not found");
}
Is it possible to modify this code to make it so it only counts each occurrence once per line rather than in the entire document?
One can read the contents per line and then apply logic per line to count the words:
File fr = new File("filename.txt");
FileReader fileReader = new FileReader(file);
BufferedReader br = new BufferedReader(fileReader);
// Read the line in the file
String line = null;
while ((line = br.readLine()) != null) {
//Code to count the occurrences of the words
}
Yes. The Set data structure is very similar to the ArrayList, but with the key difference of having no duplicates.
So, just use a set instead.
In your while loop:
while (sc.hasNext()) {
String words = sc.next();
String[] space = words.split(" ");
//convert space arraylist -> set
Set<String> set = new HashSet<String>(Arrays.asList(space));
for (int i = 0; i < set.length; i++) {
list.add(set[i]);
}
totalWords++;
}
Rest of the code should remain the same.
BufferedReader inputStream = null;
String fileLine;
int employeeCount = 1;
String[] years = new String[2];
//Employee[] employees = new Employee[employeeCount + 1];
List<Employee> employees = new ArrayList<>();
File myFile = new File("src/project1/data.txt");
//System.out.println("Attempting to read from file in: "+ myFile.getCanonicalPath());
try {
FileInputStream fstream = new FileInputStream(myFile);
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
while ((strLine = br.readLine()) != null) {
String[] data = strLine.split(" ");
//while ( int i < employees.length ) {
for (int i=1; i < employees.size(); i++ ) {
if (data[1].equals("Executive")) {
employees.add( new Executive(data[0],data[1],data[2], Integer.parseInt(data[3]), Integer.parseInt(data[4])) );
} else if (data[1].equals("Salesman")) {
employees.add( new Salesman(data[0],data[1],data[2], Integer.parseInt(data[3]), Integer.parseInt(data[4])) );
} else {
employees.add( new Employee(data[0],data[1],data[2], Integer.parseInt(data[3])) );
}
//System.out.println(employees[i].toString());
System.out.println(i +" " + employeeCount);
employeeCount++;
}
}
for (int y=1; y < employees.size(); y++ ) {
System.out.println(employees.get(y).getName());
}
//System.out.println(employees.toString());
} catch (IOException io) {
System.out.println("File IO exception" + io.getMessage());
}
EmployeeCount is incrementing as expected, but i is always 1 - what am I missing here? textfile is read in line by line using a while loop - for loop checks if second piece of data matches a string and creates object base on match. Am I making sense here?
The for loop is not incrementing because the condition is false after the first iteration at:
for (int i=1; i < employees.length; i++ ) {
that is, employees.length is 2 since employeeCount was one at this line (I must assume that since the code is incomplete):
Employee[] employees = new Employee[employeeCount + 1];
This line creates an array with two positions since employeeCount + 1 was 2. The size is not automatically adjusted as employeeCount is incremented...
I suggest using a List instead of an array, since the List is expanded as needed:
List<Employee> employees = new ArrayList<>();
...
employees.add(new Employee(...));
I need to read a text file into a 2D array, I can read files into the program perfectly fine (see my code below) however I cannot get my head around how to read them into a 2D array. The array the function is reading into is a global array hence why it's not in the function.
Also I won't know the amount of rows the array has at first (currently set at 300 as it won't be over this) and I know this could cause a problem, I've seen some people suggest using ArrayLists however I have to have a 2D array so I was also wondering if there was a way to change an ArrayList to a 2D array and if this would be more effective?
public static String readMaze(String fileName) {
String line = null;
try {
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
for (int i = 0; i < mazeNew.length; i++) {
for (int j = 0; j < mazeNew[i].length; j++) {
// mazeNew[i][j] = ; - this is where I think something needs to be added
}
}
}
bufferedReader.close();
}
catch (FileNotFoundException ex) {
System.out.println("Unable to open file: " + fileName);
}
catch (IOException ex) {
System.out.println("Error reading file: " + fileName);
}
return fileName;
}
example text file:
11 4
5 6
4 6
0 5
3 5
8 7
1 4
There's a few options here, but generally you'll want to use the Java Scanner class as it's designed for exactly this kind of thing. Alternatively, use an existing structured data format (like JSON or XML) and an existing parser to go with it - the advantage being you can make use of a vast amount of tools and libraries which deal with those formats and don't have to re-invent anything.
However, following through with the scanner approach, it would be like so:
public static ArrayList<int[]> readMaze(String fileName) {
// Number of ints per line:
int width=2;
// This will be the output - a list of rows, each with 'width' entries:
ArrayList<int[]> results=new ArrayList<int[]>();
String line = null;
try {
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
Scanner mazeRunner = new Scanner(bufferedReader);
// While we've got another line..
while (mazeRunner.hasNextLine()) {
// Setup current row:
int[] row = new int[width];
// For each number..
for (int i = 0; i < width; i++) {
// Read the number and add it to the current row:
row[i] = mazeRunner.nextInt();
}
// Add the row to the results:
results.add(row);
// Go to the next line (optional, but helps deal with erroneous input files):
if ( mazeRunner.hasNextLine() ) {
// Go to the next line:
mazeRunner.nextLine();
}
}
mazeRunner.close();
}
catch (FileNotFoundException ex) {
System.out.println("Unable to open file: " + fileName);
}
catch (IOException ex) {
System.out.println("Error reading file: " + fileName);
}
return results;
}
If you have fixed no. of columns you can use this, but make sure input file must follow the same no of coulmns.
FileReader fileReader = new FileReader(fileName);
Scanner sc = new Scanner(fileReader);
int row=0, col=0;
while ((sc.hasNext()) != null) {
if(col < colSize){ //colSize is size of column
mazeNew[row][col]= sc.nextInt();
}
else{
col=0;
row++;
}
}
Below is the core logic, you would probably also like to to handle some errors, such as how many elements is a line split into, are there empty lines, etc.
List<String[]> list = new ArrayList<>();
Pattern pattern = Pattern.compile("\\s+");
while ((line = bufferedReader.readLine()) != null) {
list.add(pattern.split(line, -1));
}
String[][] mazeNew = list.toArray(new String[0][0]);
Something like this would work
it wont only read 2d text files .. it should work fine with any dimensions
public class Utile{
public static ArrayList<int[]> readMaze(String path){
ArrayList<int[]> result = new ArrayList<>();
try{
Scanner sc = new Scanner(new File(path));
String[] temp;
String line;
while(sc.hasNextLine()){
line = sc.nextLine();
if (line.length() != 0){ //if the line is empty it will cause NumberFormatException
temp = line.split(" ");
int[] val = new int[temp.length];
for(int i = 0;i < temp.length;i++){
val[i] = Integer.pareseInt(temp[i]);
}
result.add(val);
}
}
sc.close();
}catch(Exception e){
e.printStackTrace(); //just log it for now
}
return result;
}
}
I am not a java expert, but in PHP I would do it with explode(). But I found an example how to do the same in java using string.split(). The result is the same ... an 2D Array of the content. If possible you should try to add an delimiter to the rows inside that text document. But you could split the rows on the space character either.
Example:
String foo = "This,that,other";
String[] split = foo.split(",");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < split.length; i++) {
sb.append(split[i]);
if (i != split.length - 1) {
sb.append(" ");
}
}
String joined = sb.toString();
Just at it says in the title, I can save something inside the rtf file sometimes(my save function is a working progress). Im using a mac, and i cant save as a txt. I do not know if this is normal or not and I having troubles with it since I dont know why but I get an arrayoutofbounds error when I try to use the line Player p = new Player(splitLine[0], splitLine[1], splitLine[2]);
Here is my read and write code.
final String FILE_PATH = "/Users/macbookair/Desktop/comp sci ia/TypingPractice/Player records.rtf";
BufferedReader reader;
PrintWriter writer;
Player[] readRecords() {
// This is called by AppLogic.load() which runs when the AppLogic is
// instantiated.
// The array of Person objects that we create from the load file
// This holds the current line from the load file
String nextLine;
// This is a two-element array that holds name/surname once it has
// been split at the # sign
String[] splitLine = new String[4];
for(int i=0; i< splitLine.length;i++){
splitLine[i] = "0";
}
// This is just a counter of how many lines I've read in
int count = 0;
try {
reader = new BufferedReader(new FileReader(FILE_PATH));
// Get the first line
nextLine = reader.readLine();
// Loop until we've been through every line in the file
while (nextLine != null) {
// Split the current line at the # sign
splitLine = nextLine.split("#");
Player p = new Player(splitLine[0], splitLine[1], splitLine[2]);
// Put it in the array
playerArray[count] = p;
// Increment the counter
count = count + 1;
// Get the next line
nextLine = reader.readLine();
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
void writeRecords(Player[] p) {
try {
writer = new PrintWriter(new FileWriter(FILE_PATHPhrase));
// Loop through each Person in the Person array
for (int i = 0; i < p.length; i++) {
// Write the name, then a # sign, then the surname
writer.println(p[i].getWPM() + "#" + p[i].getMistakes() + "#" + p[i].getTime());
}
} catch (Exception e) {
e.printStackTrace();
}
writer.close();
}
I am making an app that keeps username and scores from a game in a txt file. The concept is that when it writes a new username and score to the txt file it should open the .txt file, read it and then make a clone of it adding a new uername and score entry in the txt file.
I am thinking of making this with 2 object arrays. The first is the one that is read in and the new will be the one is writen which will have one more entry.
So if player[i] is readen player[i+1] should be writen with new entry.
I am giving u the code below!
private Player[] myplayer=null;
private Player[] mynewplayer=null;
//open Players.txt
int i;
int n;
String filename="players.txt";
try
{
FileReader fp=new FileReader(filename);
BufferedReader bf=new BufferedReader(fp);
n=Integer.parseInt(bf.readLine());
myplayer=new Player[n];
int x=n+1;
mynewplayer=new Player[x];
for(i=0;i<n;i++)
{
String s=bf.readLine();
String user="",score="";
user=s.substring(0,s.indexOf(","));
s=s.substring(s.indexOf(",")+1);
score=s;
myplayer[i]=new Player(user,Double.parseDouble(score));
for(i=0;i<n;i++)
{
mynewplayer[i]= myplayer[i];
}
mynewplayer[x]=new Player(Username,Double.parseDouble(score));
}
bf.close();
fp.close();
}catch(IOException e)
{
System.out.println("Exception was "+e.getMessage());
}
//----------------------------------WRITE mytxt!-------------
n=myplayer.length;
try
{
filename="players.txt";
FileWriter fp=new FileWriter(filename);
fp.write(""+n+"\n");
for(i=0;i<n+1;i++)
fp.write(""+mynewplayer[i]+"\n");
fp.close();
}catch(IOException e)
{
System.out.println("Exception was "+e.getMessage());
}
//----------------------------------WRITE mytxt!-----------
//Get on Message
String s="";
for(i=0;i<mynewplayer.length;i++)
s=s+mynewplayer[i]+"\n";
JOptionPane.showMessageDialog(null,"Players are \n "+s);
Problem is that when it's written, it returns null for mynewplayer.
I suppose the mynewplayer doesnt really take the entries of the "myplayer" but neither writes the new username.
Compile doesnt show any errors. Just writes NULL to the textfile.
Ask me if u want further info on the code writen!
Thanks in advance!
Here is an edited version of your code, with some improvements and there should be a comment around code that I changed, explaining what I did.
Player[] myPlayer = null; // first word uncapitalized, every
Player[] myNewPlayer = null; // other word begins with a capital
//open Players.txt
int i, n; // combine the variables into 1 line
String filename = "players.txt";
try {
FileReader fp = new FileReader(filename);
BufferedReader bf = new BufferedReader(fp);
n = Integer.parseInt(bf.readLine());
// not needed
//myPlayer = new Player[n];
// NOT NEEDED int x = n + 1;
myNewPlayer = new Player[n + 1];
for (i = 0; i < n; i++) {
String s = bf.readLine();
String user, score; // combine variables, doesnt need to initalize them
String[] items = s.split(","); // Splits the line into array elements on every delimiter -> ,
//user = s.substring(0, s.indexOf(","));
//s = s.substring(s.indexOf(",") + 1);
//score = s;
user = items[0];
score = items[1];
// this line below isnt actually needed
//myPlayer[i] = new Player(user, Double.parseDouble(score));
// Create a new player clone, dont copy the previous one
myNewPlayer[i] = new Player(user, Double.parseDouble(score));
}
// We've read all the variables from the text file, now we create the last one
// Since myNewPlayer is (n+1) size, the range of the array is
// 0 to n
// the last index will be n New Score Variable
myNewPlayer[n] = new Player("Username variable", Double.parseDouble("22"));
bf.close();
fp.close();
} catch (IOException e) {
System.out.println("Exception was " + e.getMessage());
}
//----------------------------------WRITE mytxt!-------------
// This is called a ternary operator
// it is a 1 line if statement
// the format is like so
// booleanLogic ? trueAnswer Execution : falseAnswer Execution;
// if () { true }else { false }
n = myNewPlayer != null ? myNewPlayer.length : 0;
// CHANGED HERE - was using the first array rather than second
// dont need the 1st array
try {
filename = "players.txt";
FileWriter fp = new FileWriter(filename);
// Dont need "" before the items
fp.write(n + "\n");
for (i = 0; i < n; i++) {
fp.write(myNewPlayer[i] + "\n");
}
fp.close();
} catch (IOException e) {
System.out.println("Exception was " + e.getMessage());
}
//----------------------------------WRITE mytxt!-----------
//Get on Message
String s = "";
for (i = 0; i < myNewPlayer.length; i++) {
// s += ""; is like doing s = s + "";
s += myNewPlayer[i] + "\n";
}
JOptionPane.showMessageDialog(null, "Players are \n " + s);
I believe that your problem is this:
for(i=0;i<n;i++)
{
String s=bf.readLine();
String user="",score="";
user=s.substring(0,s.indexOf(","));
s=s.substring(s.indexOf(",")+1);
score=s;
myplayer[i]=new Player(user,Double.parseDouble(score));
for(i=0;i<n;i++)
{
mynewplayer[i]= myplayer[i];
}
mynewplayer[x]=new Player(Username,Double.parseDouble(score));
}
You have nested loops, which is fine, but they use the same counter (the variable i ).
So what is happening is the first line of the file is read, and then added to myplayer[0]. However, instead of just also adding it to mynewplayer[0], you start another loop on i. This loop:
for(i=0;i<n;i++)
{
mynewplayer[i]= myplayer[i];
}
is going to copy the first player into mynewplayer[0]...and then null into every other entry (since myplayer only has the firsdt element filled.
The problem is that after that loop completes, i will equal n, so when you get back to the top of the outer loop, the check $i
Perhaps what you should do is this:
for(i=0;i<n;i++)
{
String s=bf.readLine();
String user="",score="";
user=s.substring(0,s.indexOf(","));
s=s.substring(s.indexOf(",")+1);
score=s;
myplayer[i]=new Player(user,Double.parseDouble(score));
mynewplayer[i]= new Player(user,Double.parseDouble(score));
}
mynewplayer[x]=new Player(<the new username>,Double.parseDouble(<the new score>));