Strange behavior reading files in Java [duplicate] - java

This question already has answers here:
BufferedReader is skipping every other line when reading my file in java
(3 answers)
Closed 4 months ago.
I'm trying to read nearly 120,000 lines from a file, put the data into a new record, and add this record to a list.
My problem is that I can't load all the data getting weird behavior.
In particular, using BufferedReader a first time I can count the rows and the result is correct, but when I try with a while loop to load the data into memory I see that the loop iterates about 60,000 times and the final list with the data contains only about 5000 objects.
I've also tried using other classes for loading data, but I always get the same problem.
I am currently using java 17 with spring and javafx.
Thank you.
I am attaching the latest version of my method:
public void getFixList(FixReadyCallback callback) {
List<Fix> fixList;
int firstCount = 0;
int whileCount = 0;
try {
File file = new File("src/main/resources/fligh_data/fix.dat");
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
String currentLine = null;
while (reader.readLine() != null) {
firstCount++;
}
fixList = new ArrayList<>(firstCount);
reader.close();
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
while ((currentLine = reader.readLine()) != null) {
whileCount++;
currentLine = reader.readLine();
if (currentLine.matches(
"[-]?[0-9]{2}\\.[0-9]{6}\\s+[-]?[0-9]{3}\\.[0-9]{6}\\s+[0-9A-Z]{2,5}")) {
String[] splitted = currentLine.split("\\s+");
String denomination = splitted[2];
double latitude = Double.parseDouble(splitted[0]);
double longitude = Double.parseDouble(splitted[1]);
Coordinates coordinates = new Coordinates(latitude, longitude);
fixList.add(new Fix(denomination, coordinates));
}
}
System.out.println("FIRST_COUNT -> " + firstCount);
System.out.println("WHILE_COUNT -> " + whileCount);
System.out.println("LIST_SIZE -> " + fixList.size());
reader.close();
callback.onReady(fixList);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
And the output of the terminal:
FIRST_COUNT -> 119724
WHILE_COUNT -> 59862
LIST_SIZE -> 5128

while ((currentLine = reader.readLine()) != null) {
whileCount++;
currentLine = reader.readLine();
...
}
This skips every other line in your file. currentLine is already the next line in the file, and then you overwrite it with the line after that. I think you only meant to read one line per loop.
It seems pretty clear that you should simply delete the last line I quoted:
while ((currentLine = reader.readLine()) != null) {
whileCount++;
...
}

Related

Java how to read a file line by line and change the specific part of the line [duplicate]

This question already has answers here:
Modify the content of a file using Java
(6 answers)
Closed 3 years ago.
I am new at java and teacher gave us a project homework. I have to implement read the file line by line, slice the lines at the comma and store the parts at a multidimensional array, change the specific part of the line (I want to change the amount).
The given file:
product1,type,amount
product2,type,amount
product3,type,amount
product4,type,amount
product5,type,amount
I tried this code but I couldn't change the specific part.
BufferedReader reader;
int j=0;
int i=0;
try {
reader = new BufferedReader(new FileReader("file.txt"));
String line = reader.readLine();
while (line != null) {
j++;
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
String total_length[][]=new String[j][3];
try {
reader = new BufferedReader(new FileReader("file.txt"));
String line = reader.readLine();
while (line != null) {
line = reader.readLine();
String[] item = line.split(",");
total_length[i][0]=item[0];
total_length[i][1]=item[0];
total_length[i][2]=item[0];
i++;
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
Thanks a lot!
First, you need to read the file. There are plenty of way to do it, one of them is:
BufferedReader s = new BufferedReader(new FileReader("filename"));
Which allows you to do s.readLine() to read it line by line.
You can use a while loop to read it until the end. Note that readLine will return null if you reach the end of the file.
Then, for each line, you want to split them with the coma. You can use the split method of Strings:
line.split(",");
Putting it all together, and using a try-catch for IOException, you get:
List<String[]> result = new ArrayList<>();
try (BufferedReader s = new BufferedReader(new FileReader("filename"))) {
String line;
while ((line = s.readLine()) != null) {
result.add(line.split(","));
}
} catch (IOException e) {
// Handle IOExceptions here
}
If you really need a two dimensional array at the end, you can do:
String[][] array = new String[0][0];
array = result.toArray(array);
You then have read the file in the format you wanted, you can now modify the data that you parsed.

Writing to File duplicating data the second time JAVA

I'm creating a program to remove doctors from an arrayList that is utilising a queue. This works the first time perfectly however, the second time it's duplicating the data inside the text file. How can I solve this?
/**
*
* #throws Exception
*/
public void writeArrayListToFile() throws Exception {
String path = "src/assignment1com327ccab/DoctorRecordsFile.txt";
OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(path));
BufferedWriter br = new BufferedWriter(os);
PrintWriter out = new PrintWriter(br);
DoctorNode temp; //create a temporary doctorNode object
temp = end; //temp is equal to the end of the queue
//try this while temp is not equal to null (queue is not empty)
StringBuilder doctor = new StringBuilder();
while (temp != null) {
{
doctor.append(temp.toStringFile());
doctor.append("\n");
//temp is equal to temp.getNext doctor to get the next doctor to count
temp = temp.getNext();
}
}
System.out.println("Finished list");
System.out.println("Doctors is : " + doctor.toString());
out.println(doctor.toString());
System.out.println("Done");
br.newLine();
br.close();
}
This is not 100% solution but I think it will give you the right directions. I don't want to do 100% work for you :)
In my comment I said
Read file content
Store it in variable
Remove file
Remove doctors from variable
Write variables to new file
So, to read file content we would use something file this (if it's txt file):
public static String read(File file) throws FileNotFoundException {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(file.getAbsoluteFile()));
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
line = br.readLine();
if (line != null) sb.append(System.lineSeparator());
}
String everything = sb.toString();
return everything;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
This method returns String as file content. We can store it in a variable like this:
String fileContent = MyClass.read(new File("path to file"));
Next step would be to remove our file. Since we have it in memory, and we don't want duplicate values...
file.delete();
Now we should remove our doctors from fileContent. It's basic String operations. I would recommend using method replace() or replaceAll().
And after the String manipulation, just write fileContent to our file again.
File file = new File("the same path");
file.createNewFile();
Writer out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(file, true), "UTF-8"));
out.write(fileContent);
out.flush();
out.close();

Split file into multiple files

I want to cut a text file.
I want to cut the file 50 lines by 50 lines.
For example, If the file is 1010 lines, I would recover 21 files.
I know how to count the number of files, the number of lines but as soon as I write, it's doesn't work.
I use the Camel Simple (Talend) but it's Java code.
private void ExtractOrderFromBAC02(ProducerTemplate producerTemplate, InputStream content, String endpoint, String fileName, HashMap<String, Object> headers){
ArrayList<String> list = new ArrayList<String>();
BufferedReader br = new BufferedReader(new InputStreamReader(content));
String line;
long numSplits = 50;
int sourcesize=0;
int nof=0;
int number = 800;
try {
while((line = br.readLine()) != null){
sourcesize++;
list.add(line);
}
System.out.println("Lines in the file: " + sourcesize);
double numberFiles = (sourcesize/numSplits);
int numberFiles1=(int)numberFiles;
if(sourcesize<=50) {
nof=1;
}
else {
nof=numberFiles1+1;
}
System.out.println("No. of files to be generated :"+nof);
for (int j=1;j<=nof;j++) {
number++;
String Filename = ""+ number;
System.out.println(Filename);
StringBuilder builder = new StringBuilder();
for (String value : list) {
builder.append("/n"+value);
}
producerTemplate.sendBodyAndHeader(endpoint, builder.toString(), "CamelFileName",Filename);
}
}
} catch (IOException e) {
e.printStackTrace();
}
finally{
try {
if(br != null)br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
For people who don't know Camel, this line is used to send the file:
producerTemplate.sendBodyAndHeader (endpoint, line.toString (), "CamelFileName" Filename);
endpoint ==> Destination (it's ok with another code)
line.toString () ==> Values
And then the file name (it's ok with another code)
you count the lines first
while((line = br.readLine()) != null){
sourcesize++; }
and then you're at the end of the file: you read nothing
for (int i=1;i<=numSplits;i++) {
while((line = br.readLine()) != null){
You have to seek back to the start of the file before reading again.
But that's a waste of time & power because you'll read the file twice
It's better to read the file once and for all, put it in a List<String> (resizable), and proceed with your split using the lines stored in memory.
EDIT: seems that you followed my advice and stumbled on the next issue. You should have maybe asked another question, well... this creates a buffer with all the lines.
for (String value : list) {
builder.append("/n"+value);
}
You have to use indexes on the list to build small files.
for (int k=0;k<numSplits;k++) {
builder.append("/n"+list[current_line++]);
current_line being the global line counter in your file. That way you create files of 50 different lines each time :)

JAVA - reading from a file and writing to another [duplicate]

This question already has answers here:
Reading and Writing to a .txt file in Java
(4 answers)
Closed 6 years ago.
This is my code, I can't make it work properly, it gets just the last line from 3 lines total from the first text file and capitalize only that, and I cant figure out why
import java.util.Scanner;
import java.io.*;
public class AllCapitals {
public static void main(String[] args) {
String readLine;
String inFilePath = "/home/file.txt";
String outFilePath = "/home/newFile.txt";
try (BufferedReader bufferedReader = new BufferedReader(new FileReader(inFilePath))) {
while ((readLine = bufferedReader.readLine()) != null) {
readLine.toUpperCase();
String upperC = readLine.toUpperCase();
System.out.println(upperC);
try (Writer writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(outFilePath), "utf-8"))) {
writer.write(upperC);
}
}
} catch (IOException e) {
System.out.println("Error.");
e.printStackTrace();
}
}
}
EDIT: Forgot to say the functionallity.
I need to read 3 lines from a normal text file that goes like that
Hello.
How are you ?
Good, thank you !
And the output should be in all CAPS, but I get only the last line "GOOD THANK YOU"
That's because you recreate the output file in each iteration while reading lines from the first.
Create the output file once before you start reading, for example:
try (BufferedReader bufferedReader = new BufferedReader(new FileReader(inFilePath));
Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFilePath), "utf-8"))
) {
while ((readLine = bufferedReader.readLine()) != null) {
String upperC = readLine.toUpperCase();
System.out.println(upperC);
writer.write(upperC);
writer.write(System.lineSeparator());
}
} catch (IOException e) {
System.out.println("Error.");
e.printStackTrace();
}
Some other improvements:
Removed a pointless line readLine.toUpperCase(); that did nothing
Add a linebreak for each line, otherwise all the uppercased content would be on the same line

Inserting a big text file into netbeans

try {
BufferedReader br = new BufferedReader(new FileReader("Help.txt"));
String helptext = br.readLine();
helpText.setText(helptext);
} catch (IOException e) {
System.out.println ("Error: " + e);
}
It only returns the first line of the text file and the text file is about 4 pages long.
"helptext" being a text area.I want the whole file with its spaces I made in the text area.
This will give only 1 line where in your file the first line whatever contain to get all the line you need get into the loop
StringBuffer sb = new StringBuffer();
String line = null;
while((line=br.readLine()) !=null){
sb.append(line);
}
helpText.setText(sb.toString());
You need to loop through the text file. You are only telling it to readline() one time.
EDIT: Fixed code to be exactly what user needed
EDIT 2: Added code to keep cursor at top
String line;
try {
BufferedReader br = new BufferedReader(new FileReader("<Location of text file>"));
while((line=br.readLine()) != null){
helpText.append(line);
//Add a new line for the next entry (If you would like)
helpText.append("\n");
}
//Set Cursor back to start
helpText.setCaretPosition(WIDTH);
}
catch (IOException e) {
System.out.println (e);
}
you have to read every line in a loop.
String line = br.readLine();
String helptext = "";
while(line != null) {
helptext = helptext + line;
line = br.readLine();
}
helpText.setText(helptext);

Categories