BufferReader.skip () performance - java

I can see vast difference in performance between below two programs.
import java.io.*;
import java.util.Date;
class SkipProg2 {
public static void main (String args[]) {
System.out.println (" File Reading "+ args.length);
System.out.println (" 1st Arg "+ args[0]);
System.out.println (" 2nd Arg "+ args[1]);
try {
FileInputStream fis = new FileInputStream(args[0]);
System.err.println("Time before skip : " + new Date());
Long off = Long.parseLong(args[1]);
fis.skip (off);
System.err.println("Time After skip : " + new Date());
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr );
} // end try
catch (IOException e) {
System.err.println("Error: " + e);
}
} // end main
}
And
import java.io.*;
import java.util.Date;
class SkipProg {
public static void main (String args[]) {
System.out.println (" File Reading "+ args.length);
System.out.println (" 1st Arg "+ args[0]);
System.out.println (" 2nd Arg "+ args[1]);
try {
FileInputStream fis = new FileInputStream(args[0]);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr );
System.err.println("Time before skip : " + new Date());
Long off = Long.parseLong(args[1]);
br.skip (off);
System.err.println("Time After skip : " + new Date());
} // end try
catch (IOException e) {
System.err.println("Error: " + e);
}
} // end main
}
One usage FileInputStream.skip () and another BufferReader.skip (). But, if offset value is bigger there vast different (For Ex. 8 Secs different for 2 GB)and in multithreaded application, the difference for the same code is huge (For 2 Gb offset there is around 15-20 mins delay). I cant replace BufferReader.skip () with FileInputStream.skip (), As one takes offset in terms of bytes and another in terms of chars. For unicode file, it is irreplaceable.
First question, whether my assumption is correct? what are suggestions?
Thanks In Advance.

The skip for bytes can skip that many bytes without reading them.
The skip for chars has to read all the chars/bytes up to that point to find where the Nth character is.
I am surprised it takes 15-20 mins to read 2 GB of text. I would have expected closer to 20 seconds. What sort of hardware do you have?
If you want random access in a text file, you need to maintain an index of line number to byte location (that way the time taken will bet the same)

Related

How to sort user input to text files in Java?

I have a program taking user input and setting students in a text file, I want to sort these students in separate text files using the grade average
import java.nio.file.*;
import java.io.*;
import static java.nio.file.StandardOpenOption.*;
import java.util.Scanner;
public class NewClass2
{
public static void main(String[] args)
{
String recOut = "";
String delimiter = ",";
Scanner input = new Scanner(System.in);
final int QUIT = 999;
NewClass1 student = new NewClass1();
try
{
System.out.println("Enter Student ID: ");
student.setStudentId(input.nextInt());
while(student.getStudentId() != QUIT)
{
System.out.println("Enter Student Last Name: ");
student.setLastName(input.next());
System.out.println("Enter Student First Name: ");
student.setFirstName(input.next());
System.out.println("Enter Student Grade Point: ");
student.setGradePoint(input.nextDouble());
if(student.getGradePoint()>=3.6)
{
Path fileOut = Paths.get("HonorsStudentList.txt");
OutputStream output = new BufferedOutputStream(Files.newOutputStream(fileOut, CREATE));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output));
recOut = student.getStudentId() + delimiter + student.getLastName() + delimiter + student.getFirstName() + delimiter + student.getGradePoint();
writer.write(recOut, 0,recOut.length());
writer.newLine();
writer.close();
}
if(student.getGradePoint()<3.6 && student.getGradePoint()>=2.0)
{
Path fileOut = Paths.get("GoodStandingStudentList.txt");
OutputStream output = new BufferedOutputStream(Files.newOutputStream(fileOut, CREATE));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output));
recOut = student.getStudentId() + delimiter + student.getLastName() + delimiter + student.getFirstName() + delimiter + student.getGradePoint();
writer.write(recOut, 0,recOut.length());
writer.newLine();
writer.close();
}
if(student.getGradePoint()<2.0)
{
Path fileOut = Paths.get("ProbationStudentList.txt");
OutputStream output = new BufferedOutputStream(Files.newOutputStream(fileOut, CREATE));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output));
recOut = student.getStudentId() + delimiter
+ student.getLastName() + delimiter
+ student.getFirstName() + delimiter
+ student.getGradePoint();
writer.write(recOut, 0,recOut.length());
writer.newLine();
writer.close();
}
System.out.println("Enter Student ID: ");
student.setStudentId(input.nextInt());
}
}
catch(Exception e)
{
System.out.println("<<Something bad happened!>>");
System.out.println(e.getMessage());
}
}
}
I've been experimenting with if statements but that's not working because I can't close the writer correctly causing it to only take in one line then stopping.
How do I do this correctly?
The problem is not with how you're closing the file but with how your opening the file. Every time you're opening the file you are creating a new file and writing one line, then closing it, which is overwriting the old file that existed before. What you want to do is create the file if it does not exist, but if it does exist append one line.
Simply change
Files.newOutputStream(fileOut, CREATE)
to
Files.newOutputStream(fileOut, CREATE, APPEND)
Alternatively, you could open/close the files outside the loop or use “try with resources” too.
Since these are only three files, it is probably the easiest to open all three writers at once at the start and keep them open until the end.
If you don't want to close the writers manually (ans at least java 7 or 8 i think), you can use a try-with-resources statement.
Btw you probably don't need to wrap the OutputStream in a BufferedOutputStream, since you already use a buffered writer.
Instead of writing each time in file why don't you try to make three lists(one for every grade range you need) and when you have no more students then write them to separate files.
Something like this:
List<Student> honorsStudent = new ArrayList<Student>();
List<Student> goodStandingStudent = new ArrayList<Student>();
List<Student> probationStudent = new ArrayList<Student>();
// ....
if (student.getGrade() >= 3.6) {
honorsStudent.add(student);
} else if (student.getGrade() >= 2) {
goodStandingStudent.add(student);
}
else {
probationStudent.add(student);
}
//while loop end
//write your files

Searching for a String in a .txt file and getting the row and column number in Java

I am currently stuck with a problem. I am supposed to write a programm that is able to search for a string in a .txt file given as argument. The programm must return the row and the column of the found string.
I am struggling to find a way to achieve that and have no idea how to go on. I would be very happy to hear from you.
Here is my attempt in tackling with my task:
- I thought about saving the content of a file via a buffered reader in a string array, but that does not seem to work since I cannot define the length of the array from the beginning
- I also thought about saving the content of the file via a buffered reader in a string and then split this string in characters. However I am not sure how I will be able to retreieve the rows in the original file then.
This is the non-functional code that I have at the moment:
public class StringSearch{
public static void main(String[] args){
if(args.length > 0){
BufferedReader br = null;
String text = null;
try{
br = new BufferedReader(new FileReader(args[0]));
// attempt of saving the content of the "argument" file in a string array and then in a string
String[] lines = new String[]; // I know this does not work like this
for( int i = 0; i < lines.length; i++){
lines[i] = br.readLine;
text = text + lines[i];
i++;
}
text.split("\r\n");
} catch (IOException ioe){
ioe.printStackTrace();
} finally{
if (br != null) {
try{
br.close();
}catch (IOException ioe){
ioe.printStackTrace();
}
}
}
}
}
}
You can do it as follows:
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
if (args.length != 2) {
System.out.println("The correct syntax to use this program is: java Main <filename.txt> <text-to-search>");
return;
}
Scanner scanner;
File file = new File(args[0]);
int rowCount = 1, index;
String line;
// Map to collect row and col info of the search string
Map<String, String> lineColMap = new HashMap<String, String>();
if (!file.exists()) {
System.out.println("The file, " + args[0] + " does not exist");
return;
}
try {
scanner = new Scanner(file);
while (scanner.hasNextLine()) {// Loop until the last line in the file
line = scanner.nextLine();// Read a line from the file
index = line.indexOf(args[1]);// Find if the string exists in the line
if (index != -1) {// If the string exists
// Put the row and col info of the search string into the map
lineColMap.put("Row: " + rowCount, "Column: " + index);
}
rowCount++;// Increase the row count
}
} catch (Exception e) {
System.out.println("Error occured while processing the file");
e.printStackTrace();
}
if (lineColMap.entrySet().size() > 0) {// If there is at least one entry collected into the map
System.out.println("'" + args[1] + "' exists in " + args[0] + " as follows:");
for (Map.Entry<String, String> entry : lineColMap.entrySet()) {
System.out.println(entry.getKey() + ", " + entry.getValue());
}
} else {
System.out.println("'" + args[1] + "' does not exist in " + args[0]);
}
}
}
A sample run: java Main input.txt of
'of' exists in input.txt as follows:
Row: 1, Column: 51
Row: 2, Column: 50
Row: 3, Column: 50
Row: 5, Column: 71
The content of input.txt is as follows:
Stack Overflow is a question and answer site for professional and enthusiast programmers.
It is a privately held website, the flagship site of the Stack Exchange Network, created in 2008 by Jeff Atwood and Joel Spolsky.
It features questions and answers on a wide range of topics in computer programming.
It was created to be a more open alternative to earlier question and answer sites such as Experts-Exchange.
The name for the website was chosen by voting in April 2008 by readers of Coding Horror, Atwood's popular programming blog.
The logic in the code is straight forward and I believe, you should be able to understand it in the first reading. Feel free to comment in case of any doubt.
Here's one approach -
Let's consider a counter which holds a counter for all the
readLine() method invocations - representing the "row" in the .txt
file. So, increment the counter after every readLine call in the
while loop.
Next, split the line on " " (space) to get an array of each word in the
line. Then, you could iterate over this array and match the word to
the search string. The position of array index at the time the match
was found will represent the "column".

For-loop not executing File writing commands

I have a program that is supposed to generate a file with a random integer name and append 200 characters of data to each file. I have already succeeded in being able to create a file:
BufferedOutputStream bos = new BufferedOutputStream(Files.newOutputStream(
new File("C:/Users/mirvine/Desktop/SPAM").toPath()));
And I have gotten it to write chars to the file:
bos.write((char)rand.nextInt(255));
But when I combine the two with a for loop, it doesn't work:
try {
while(true) {
int i = rand.nextInt();
File outputFile = new File("C:/Users/mirvine/Desktop/SPAM/"+ String.valueOf(i) +".txt");
bos = new BufferedOutputStream(Files.newOutputStream(outputFile.toPath()));
PrintWriter writer = new PrintWriter(bos);
for(int qu = 0; qu <= 2000; qu++) {
writer.write((char)rand.nextInt(255));
System.out.println("Total " + String.valueOf(qu) + " characters written to " + String.valueOf(i) + ".txt!");
}
System.out.println("File named \'" + String.valueOf(i) + ".txt\' created!");
}
} catch (Exception e) {e.printStackTrace(); return;}
I will get the output "Total: (number) characters written to (whatever).txt!" but it won't actually write the characters. However, if I make the loop infinite (by changing qu++ to qu--) it will write the characters, of course with only one file though. I even tried changing it to a while loop and it didn't work. Any ideas?
Consider changing the use of BufferedOutputStream and PrintWriter for FileWriter, which will take your file as an argument to the constructor.
Also, make sure you flush and close the stream after finishing with it.
You should use a BufferedWriter, it's more efficient, and don't forget to close it at the end. The infinite loop is useless.
int i = rand.nextInt();
File outputFile = new File("C:/Users/mirvine/Desktop/SPAM/"+ String.valueOf(i) +".txt");
FileOutputStream fos = new FileOutputStream(outputFile);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));  
for(int qu = 0; qu <= 2000; qu++)
{
bw.write((char)rand.nextInt(255));
System.out.println("Total " + String.valueOf(qu) + " characters written to " + String.valueOf(i) + ".txt!");
}
bw.close();

Write file using BufferedWriter in Java [duplicate]

This question already has answers here:
BufferedWriter not writing everything to its output file
(8 answers)
Closed 8 years ago.
I am doing a lab where we have to read in an external file, take some statistics on the data, and then create and write a new file with the stats. Everything in my program works except for writing the file, which I cannot understand why my method won't work.
BufferedWriter writer;
public void writeStats(int word, int numSent, int shortest, int longest, int average)
{
try
{
File file = new File("jefferson_stats.txt");
file.createNewFile();
writer = new BufferedWriter(new FileWriter(file));
writer.write("Number of words: " + word );
writer.newLine();
writer.write("Number of sentences: " + numSent );
writer.newLine();
writer.write("Shortest sentence: " + shortest + " words");
writer.newLine();
writer.write("Longest sentence: " + longest + " words");
writer.newLine();
writer.write("Average sentence: " + average + " words");
}
catch(FileNotFoundException e)
{
System.out.println("File Not Found");
System.exit( 1 );
}
catch(IOException e)
{
System.out.println("something messed up");
System.exit( 1 );
}
}
You have to flush and close your writer:
writer.flush();
writer.close();
You should always close opend resources explicitly or implicitly with Java 7 try-with-resources
try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
...
}
besides, there is a more convenient class to write text - java.io.PrintWriter
try (PrintWriter pw = new PrintWriter(file)) {
pw.println("Number of words: " + word);
...
}
You have to close your BufferedWriter using close():
writer.close();

Where and how to start implementing a Java program that searches a phrase example “red or green" in a text file,

I want to implementing a Java program that searches a phrase example “red or green, blue car, red and blue” in a text file, and returns a match even if it is not a complete match for the phrase, and if there is no even half match the program should return no match.
if I am searching "red car" and the the string line in the text file contains "red and blue" I want the program to return red which is half a match of what I was searching.
Any help is very much appreciated
This is what I have done so far, all this does is find the exact words
public class StringSearch
{
public static void main(String[] args)
{
String key = "red yellow";
String strLine;
try
{
FileInputStream fstream = new FileInputStream("C:\\textfile.txt");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
while ((strLine = br.readLine()) != null) {
if(key.equals(strLine))
{
System.out.println(" Match For " + strLine );
}
else
{
System.out.println( "No Match For " + key);
}
// Print the content on the console
}
//Close the input stream
in.close();
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
}
But what I want to find is if I am searching "red" and the first line of the string in the text file I am searching contains "red car was stollen" and the second line contains just "red". I want to return two matches the first one being 100% match the socond being 50% match.
First you need to define your problem better, and to do that think about how what you'd do if you were telling someone else, who interpreted things very literally, how to do it. How much of the input should they examine at one time? Should what they examine span lines? What precisely is a "half match"? What is the sequence of steps they should take?
This code might help You
import java.io.*;
public class searchfile {
public static void main(String args[]) {
try {
// Open the file c:\test.txt as a buffered reader
BufferedReader bf = new BufferedReader(new FileReader("c:\\test.txt"));
// Start a line count and declare a string to hold our current line.
int linecount = 0;
String line;
// Let the user know what we are searching for
System.out.println("Searching for " + args[0] + " in file...");
// Loop through each line, stashing the line into our line variable.
while (( line = bf.readLine()) != null)
{
// Increment the count and find the index of the word
linecount++;
int indexfound = line.indexOf(args[0]);
// If greater than -1, means we found the word
if (indexfound > -1) {
System.out.println("Word was found at position " + indexfound + " on line " + linecount);
}
}
// Close the file after done searching
bf.close();
}
catch (IOException e) {
System.out.println("IO Error Occurred: " + e.toString());
}
}
}
and run it as
c:\>java searchfile "bluecar"

Categories