im trying to write a class where it would take a text file,reverse its contents and write it back. The way i want to do it is to write the lines in a String[] array,reverse the lines and then write the text back to the text file. Problem is, when I start writing to the String array, it writes off only nulls and i know the text file is not empty. Im using a copy of the BufferedReader to read the lines. I can't seem to understand where am i wrong. When I initialize the String array textFile like down in the code, i have no problems reversing, but when i use the
String[] textFile = new String[getNumberOfLines ()];
method, it doesnt work.
public void reverse() throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(WORK_FOLDER_LOCATION + FILE_NAME));
String[] textFile = new String[3];
try {
for (int i = 0; i < textFile.length; i++) {
textFile[i] = reader.readLine();
textFile[i] = reverseLine(textFile[i]);
}
} catch (IOException e) {
throw new IOException("There was a problem while operating with the reader.");
} finally {
reader.close();
}
writeReverseText(textFile);
}
private int getNumberOfLines(BufferedReader reader) throws IOException {
BufferedReader linesReader = reader;
int counter = 0;
try {
while (linesReader.readLine() != null) {
counter++;
}
linesReader.close();
} catch (IOException e) {
throw new IOException("There was a problem while counting the lines");
}
return counter;
}
private String reverseLine(String string) {
StringBuilder reversedString = new StringBuilder(string).reverse();
System.out.println(reversedString);
return reversedString.toString();
}
private void writeReverseText(String[] textFile) throws IOException {
BufferedWriter writer = new BufferedWriter(new FileWriter(WORK_FOLDER_LOCATION + FILE_NAME));
for (int i = 0; i < textFile.length; i++) {
writer.append(textFile[i]);
writer.append(System.lineSeparator());
}
writer.close();
}
EDIT I managed to solve the issue but changing the getNumberOfLines() method:
private int getNumberOfLines() throws IOException {
BufferedReader linesReader = new BufferedReader(new FileReader(WORK_FOLDER_LOCATION + FILE_NAME));
Hope this helps to the others, i would love to know why the previous code didn't work.
Your getNumberOfLines() method will read all the data from the BufferedReader - so unless you start reading the file again, there's nothing to read, and the very first call to readLine() will return null.
However, instead of doing this, you'd be better off just reading the file once, and populating a List<String>. For example:
List<String> lines = new ArrayList<>();
String line;
while ((line = reader.readLine()) != null) {
lines.add(reverseLine(line));
}
Related
I typed 3 names in the file, and I wanted to write a code to count how many times each name was repeated (Example: Alex was repeated in the file 3 times..and so on). The code I wrote only counted each name once, and this is wrong because the names were repeated more than once. Can you help me with the part that could be the cause of this problem?
public class MainClass {
public static void readFile() throws IOException {
//File file;
FileWriter writer=null;
String name, line;
List <String> list = new ArrayList <>();
int countM = 0, countAl = 0, countAh = 0;
try
{
File file = new File("\\Users\\Admin\\Desktop\\namesList.txt");
Scanner scan = new Scanner(file);
while(scan.hasNextLine()) {
line = scan.nextLine();
list.add(line);
}
for (int i=0; i<list.size(); i++)
{
name=list.get(i);
if (name.equals("Ali"))
{
countAl= +1;
}
if (name.equals("Ahmed"))
{
countAh= +1;
}
if (name.equals("Muhammad"))
{
countM = +1;
}
}
Collections.sort(list);
writer = new FileWriter("\\Users\\Admin\\Desktop\\newNameList");
for(int i=0; i<list.size(); i++)
{
name = list.get(i);
writer.write(name +"\n");
}
writer.close();
System.out.println("How many times is the name (Ali) in the file? " + countAl);
System.out.println("How many times is the name (Ahmed) in the file? " + countAh);
System.out.println("How many times is the name (Muhammad) in the file? " + countM);
}
catch(IOException e) {
System.out.println(e.toString());
}
}
public static void main(String[] args) throws IOException {
readFile();
}
}
You an do this much simpler:
//Open a reader, this is autoclosed so you don't need to worry about closing it
try (BufferedReader reader = new BufferedReader(new FileReader("path to file"))) {
//Create a map to hold the counts
Map<String, Integer> nameCountMap = new HashMap<>();
//read all of the names, this assumes 1 name per line
for (String name = reader.readLine(); name != null; name = reader.readLine()) {
//merge the value into the count map
nameCountMap.merge(name, 1, (o, n) -> o+n);
}
//Print out the map
System.out.println(nameCountMap);
} catch (IOException e) {
e.printStackTrace();
}
try:
for (int i=0; i<list.size(); i++)
{
name=list.get(i);
if (name.equals("Ali"))
{
countAl += 1;
}
if (name.equals("Ahmed"))
{
countAh += 1;
}
if (name.equals("Muhammad"))
{
countM += 1;
}
}
This works with me.
+= is not same =+
You need to process each line bearing in mind that the file may be very large in some cases. Better safe than sorry. You need to consider a solution that does not take up so much resources.
Streaming Through the File
I'm going to use a java.util.Scanner to run through the contents of the file and retrieve lines serially, one by one:
FileInputStream inputStream = null;
Scanner sc = null;
try {
inputStream = new FileInputStream(file_path);
sc = new Scanner(inputStream, "UTF-8");
while (sc.hasNextLine()) {
String line = sc.nextLine();
// System.out.println(line);
}
// note that Scanner suppresses exceptions
if (sc.ioException() != null) {
throw sc.ioException();
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (sc != null) {
sc.close();
}
}
This solution will iterate through all the lines in the file – allowing for processing of each line – without keeping references to them – and in conclusion, without keeping them in memory:
Streaming With Apache Commons IO
The same can be achieved using the Commons IO library as well, by using the custom LineIterator provided by the library:
LineIterator it = FileUtils.lineIterator(your_file, "UTF-8");
try {
while (it.hasNext()) {
String line = it.nextLine();
// do something with line
}
} finally {
LineIterator.closeQuietly(it);
}
Since the entire file is not fully in memory – this will also result in pretty conservative memory consumption numbers.
BufferedReader
try (BufferedReader br = Files.newBufferedReader(Paths.get("file_name"), StandardCharsets.UTF_8)) {
for (String line = null; (line = br.readLine()) != null;) {
// Do something with the line
}
}
ByteBuffer
try (SeekableByteChannel ch = Files.newByteChannel(Paths.get("test.txt"))) {
ByteBuffer bb = ByteBuffer.allocateDirect(1000);
for(;;) {
StringBuilder line = new StringBuilder();
int n = ch.read(bb);
// Do something with the line
}
}
The above examples will process lines in a large file without iteratively, without exhausting the available memory – which proves quite useful when working with these large files.
public class FileSplitter2 {
public static void main(String[] args) throws IOException {
String filepath = "D:\\temp\\test.txt";
BufferedReader reader = new BufferedReader(new FileReader(filepath));
String strLine;
boolean isFirst = true;
String strGroupByColumnName = "city";
int positionOgHeader = 0;
FileWriter objFileWriter;
Map<String, FileWriter> groupByMap = new HashMap<String, FileWriter>();
while ((strLine = reader.readLine()) != null) {
String[] splitted = strLine.split(",");
if (isFirst) {
isFirst = false;
for (int i = 0; i < splitted.length; i++) {
if (splitted[i].equalsIgnoreCase(strGroupByColumnName)) {
positionOgHeader = i;
break;
}
}
}
String strKey = splitted[positionOgHeader];
if (!groupByMap.containsKey(strKey)) {
groupByMap.put(strKey, new FileWriter("D:/TestExample/" + strKey + ".txt"));
}
FileWriter fileWriter = groupByMap.get(strKey);
fileWriter.write(strLine);
}
for (Map.Entry<String,FileWriter> entry : groupByMap.entrySet()) {
entry.getKey();
}
}
}
This is my code. I am not getting a proper result. The file contains 10 columns, and the 5th column is 'city'. There are 10 different cities in a file. I need to split each city a separate file.
You are not calling close on all the FileWriter and hence the data may not get flushed to the file.
See FileWriter is not writing in to a file
At the end of the processing,
groupByMap.values().forEach(fileWriter -> {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace(); //Add appropriate error handling
}
});
There is a bug in your code. You need to move the statements after the if (isFirst) block into the else block. Else, it will create a city.txt file too.
I'm facing a problem, can someone tell me how to void this? It throws up an "java.io.IOException: Stream closed". I know where my mistake is but I dont know how to fix it. BufferedReader closes from the first function and I dont know how to reset it within the second one. Function should format text from one text file to another with tabs. Thank you
import java.io.*;
public class TestClass {
private void prosekStudentKRS(FileReader fr) throws IOException{
BufferedReader reader = null;
int j = 0, vksum = 0;
try{
reader = new BufferedReader(fr);
reader.readLine();
String line;
while((line = reader.readLine()) != null) {
int sum = 0;
j++;
String[] niza = line.split(",");
for(int i = 1; i < niza.length; i ++) {
sum+=Integer.parseInt(niza[i]);
}
vksum += Integer.parseInt(niza[1]);
System.out.printf("Student %d ima prosek %.2f\n", j, (float) sum / 3);
}
System.out.println("Prosek po KRS: " + vksum / (double) j);
} catch (Exception e){
e.printStackTrace();
} finally {
if(reader != null) {
reader.close();
}
}
}
private void TSV(FileReader fr, FileWriter fw) throws IOException {
BufferedReader reader = null;
BufferedWriter writer = null;
StringBuilder sb = null;
try {
reader = new BufferedReader(fr);
writer = new BufferedWriter(fw);
String line;
while ((line = reader.readLine()) != null) {
String[] niza = line.split(",");
sb = new StringBuilder();
for(int i = 0; i < niza.length; i ++) {
sb.append(niza[i] + "\t");
}
writer.write(sb.toString());
writer.newLine();
writer.flush();
}
} finally {
if (reader != null)
reader.close();
if(writer != null) {
writer.flush();
writer.close();
}
}
}
public static void main(String[] args) throws IOException{
FileReader fr = new FileReader("C:\\Users\\pc\\IdeaProjects\\LabOS01\\rezultaticsv.txt");
FileWriter fw = new FileWriter("C:\\Users\\pc\\IdeaProjects\\LabOS01\\rezultatitsv.txt");
TestClass filetest = new TestClass();
filetest.prosekStudentKRS(fr);
filetest.TSV(fr, fw);
}
}
Either create two distinct FileReader objects and pass a different to each method.
Otherwise you can also create a BufferedReader from the FileReader before invoking the methods, pass it to the first method, reset it with the reset() method and pass it to the other method.
As alternative if the file is not too big, you could store in a List<String> each line read rather than reading again the file.
It would be more efficient.
I have been making a little program that needs to read a list of golf courses that could be changeing and needs to be called when ever. Here is the code:
public class Courses {
public String[] courselist;
public void loadCourses() throws IOException{
int count = 0;
int counter = 0;
File f = new File("src//courses//courses.txt");
BufferedReader reader = new BufferedReader(new FileReader(f));
while(count<1){
String s = reader.readLine();
if(s.equalsIgnoreCase("*stop*")){
reader.close();
count = 5;
}else{
courselist[counter] = s;
counter++;
}
s = "";
}
}
}
And now this is what is in the txt file.
RiverChase
Steward Peninsula
Lake Park
Coyote Ridge
*stop*
Now when ever i start to run the program because i call the method instantly it gives me a throw exeption and it is because of the array. And i need to stay and array because i use it in a JComboBox. If you can help or fix the problem. Most likely im just doing it wrong, im a noob. Just help. Thanks in advance.
I know all the file reader and stuff works because it prints out to the system correct, i just need help writing it to the array repetedly.
You should initialize your array before using it
public static final MAX_SIZE = 100;
public String[] courselist = new String[MAX_SIZE];
Change your code to assign a new array during loadCourses(), and add a call to loadCourses() to your constructor:
public class Courses {
public String[] courselist;
public Courses() throws IOException { // <-- Added constructor
loadCourses(); // <-- Added call to loadCourses
}
public void loadCourses() throws IOException {
int count = 0;
int counter = 0;
File f = new File("src//courses//courses.txt");
BufferedReader reader = new BufferedReader(new FileReader(f));
List<String> courses = new ArrayList<String>(); // <-- A List can grow
while(true){
String s = reader.readLine();
if (s.equalsIgnoreCase("*stop*")){
break;
}
courses.add(s);
}
courseList = courses.toArray(new String[0]); // <-- assign it here
}
}
This ensures that when you create an instance, it starts out life with the array initialised. Not only will you not get an error, but the data will always be correct (unlike other answers that simply create an empty (ie useless) array.
Note that this code will work with any number of course names in the file (not just 5).
You'd better create a List that is easier to manipulate and convert it as an array at the end of the process :
List<String> list = new ArrayList<String>();
String [] array = list.toArray(new String [] {});
Here is a possible implementation of the loading using a List :
public static String [] loadCourses() throws IOException {
File f = new File("src//courses.txt");
BufferedReader reader = new BufferedReader(new FileReader(f));
List<String> courses = new ArrayList<String>();
while (true){
String s = reader.readLine();
if (s == null || s.trim().equalsIgnoreCase("*stop*")){
break;
} else{
courses.add(s);
}
}
return courses.toArray(new String [] {});
}
Also why use a stop keyword ? You could simply stop the process when you reach the end of the file (when s is null).
Here some example, without using the *stop*:
public class ReadFile {
public static void main(String[] args) {
BufferedReader reader = null;
List<String> coursesList = new ArrayList<>();
String[] courses;
try {
File file = new File("courses.txt");
reader = new BufferedReader(new FileReader(file));
String readLine;
do {
readLine = reader.readLine();
if(readLine == null)
break;
coursesList.add(readLine);
} while (true);
} catch (IOException ex) {
Logger.getLogger(ReadFile.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
reader.close();
} catch (IOException ex) {
Logger.getLogger(ReadFile.class.getName()).log(Level.SEVERE, null, ex);
}
}
courses = coursesList.toArray(new String[coursesList.size()]);
for(int i = 0; i < courses.length; i++) {
System.out.println(courses[i]);
}
}
}
I am trying to read a text file in java using FileReader and BufferedReader classes. Following an online tutorial I made two classes, one called ReadFile and one FileData.
Then I tried to extract a small part of the text file (i.e. between lines "ENTITIES" and "ENDSEC"). Finally l would like to tell the program to find a specific line between the above-mentioned and store it as an Xvalue, which I could use later.
I am really struggling to figure out how to do the last part...any help would be very much apprciated!
//FileData Class
package textfiles;
import java.io.IOException;
public class FileData {
public static void main (String[] args) throws IOException {
String file_name = "C:/Point.txt";
try {
ReadFile file = new ReadFile (file_name);
String[] aryLines = file.OpenFile();
int i;
for ( i=0; i < aryLines.length; i++ ) {
System.out.println( aryLines[ i ] ) ;
}
}
catch (IOException e) {
System.out.println(e.getMessage() );
}
}
}
// ReadFile Class
package textfiles;
import java.io.IOException;
import java.io.FileReader;
import java.io.BufferedReader;
import java.lang.String;
public class ReadFile {
private String path;
public ReadFile (String file_path) {
path = file_path;
}
public String[] OpenFile() throws IOException {
FileReader fr = new FileReader (path);
BufferedReader textReader = new BufferedReader (fr);
int numberOfLines = readLines();
String[] textData = new String[numberOfLines];
String nextline = "";
int i;
// String Xvalue;
for (i=0; i < numberOfLines; i++) {
String oneline = textReader.readLine();
int j = 0;
if (oneline.equals("ENTITIES")) {
nextline = oneline;
System.out.println(oneline);
while (!nextline.equals("ENDSEC")) {
nextline = textReader.readLine();
textData[j] = nextline;
// xvalue = ..........
j = j + 1;
i = i+1;
}
}
//textData[i] = textReader.readLine();
}
textReader.close( );
return textData;
}
int readLines() throws IOException {
FileReader file_to_read = new FileReader (path);
BufferedReader bf = new BufferedReader (file_to_read);
String aLine;
int numberOfLines = 0;
while (( aLine = bf.readLine()) != null ) {
numberOfLines ++;
}
bf.close ();
return numberOfLines;
}
}
I don't know what line you are specifically looking for but here are a few methods you might want to use to do such operation:
private static String START_LINE = "ENTITIES";
private static String END_LINE = "ENDSEC";
public static List<String> getSpecificLines(Srting filename) throws IOException{
List<String> specificLines = new LinkedList<String>();
Scanner sc = null;
try {
boolean foundStartLine = false;
boolean foundEndLine = false;
sc = new Scanner(new BufferedReader(new FileReader(filename)));
while (!foundEndLine && sc.hasNext()) {
String line = sc.nextLine();
foundStartLine = foundStartLine || line.equals(START_LINE);
foundEndLine = foundEndLine || line.equals(END_LINE);
if(foundStartLine && !foundEndLine){
specificLines.add(line);
}
}
} finally {
if (sc != null) {
sc.close();
}
}
return specificLines;
}
public static String getSpecificLine(List<String> specificLines){
for(String line : specificLines){
if(isSpecific(line)){
return line;
}
}
return null;
}
public static boolean isSpecific(String line){
// What makes the String special??
}
When I get it right you want to store every line between ENTITIES and ENDSEC?
If yes you could simply define a StringBuffer and append everything which is in between these to keywords.
// This could you would put outside the while loop
StringBuffer xValues = new StringBuffer();
// This would be in the while loop and you append all the lines in the buffer
xValues.append(nextline);
If you want to store more specific data in between these to keywords then you probably need to work with Regular Expressions and get out the data you need and put it into a designed DataStructure (A class you've defined by our own).
And btw. I think you could read the file much easier with the following code:
BufferedReader reader = new BufferedReader(new
InputStreamReader(this.getClass().getResourceAsStream(filename)));
try {
while ((line = reader.readLine()) != null) {
if(line.equals("ENTITIES") {
...
}
} (IOException e) {
System.out.println("IO Exception. Couldn't Read the file!");
}
Then you don't have to read first how many lines the file has. You just start reading till the end :).
EDIT:
I still don't know if I understand that right. So if ENTITIES POINT 10 1333.888 20 333.5555 ENDSEC is one line then you could work with the split(" ") Method.
Let me explain with an example:
String line = "";
String[] parts = line.split(" ");
float xValue = parts[2]; // would store 10
float yValue = parts[3]; // would store 1333.888
float zValue = parts[4]; // would store 20
float ... = parts[5]; // would store 333.5555
EDIT2:
Or is every point (x, y, ..) on another line?!
So the file content is like that:
ENTITIES POINT
10
1333.888 // <-- you want this one as xValue
20
333.5555 // <-- and this one as yvalue?
ENDSEC
BufferedReader reader = new BufferedReader(new
InputStreamReader(this.getClass().getResourceAsStream(filename)));
try {
while ((line = reader.readLine()) != null) {
if(line.equals("ENTITIES") {
// read next line
line = reader.readLine();
if(line.equals("10") {
// read next line to get the value
line = reader.readLine(); // read next line to get the value
float xValue = Float.parseFloat(line);
}
line = reader.readLine();
if(line.equals("20") {
// read next line to get the value
line = reader.readLine();
float yValue = Float.parseFloaT(line);
}
}
} (IOException e) {
System.out.println("IO Exception. Couldn't Read the file!");
}
If you have several ENTITIES in the file you need to create a class which stores the xValue, yValue or you could use the Point class. Then you would create an ArrayList of these Points and just append them..