how to take 10000 character string input in java - java

I need to take a 10000 character string as input from user in a program in java. But when i use the normal way it gives NZEC error in ideone and spoj. How can i take such a string as an input ?
import java.io.*;
class st
{
public static void main(String args[])throws IOException
{
String a;
BufferedReader g=new BufferedReader(new InputStreamReader(System.in));
a=g.readLine();
}
}

BufferedReader uses a buffer that is large enough "for most purposes". 10000 characters is probably too large. Since you're using readLine, the reader is scanning characters read, looking for an end of line. After its internal buffer is full, and it still hasn't found an end of line, it throws an exception.
You could try setting the size of the buffer when you create the BufferedReader:
BufferedReader g=new BufferedReader(new InputStreamReader(System.in), 10002);
Or you could use use
BufferedReader.read(char[] cbuf, int off, int len)
instead. That would give you an array of char, and you'd need to convert it back to a String.

Just read until the buffer is full.
byte[] buffer = new byte[10000];
DataInputStream dis = new DataInputStream(System.in);
dis.readFully(buffer);
// Once you get here, the buffer is filled with the input of stdin.
String str = new String(buffer);

Take a look at Runtime Error (NZEC) in simple code to understand possible reasons for the error message.
I suggest you wrap the readLine() in a try/catch block and print the error message / stack trace.

Related

Buffering from a file

I need to read from a file that contain 9000 words, what is the best way to read from this file and what is the difference between bufferingreader aND regular scanner.. or is there other good class to use?
Thanks
If you are doing "efficient" reading, there is no benefit to buffering. If, on the other hand, you are doing "inefficient" reading, then having a buffer will improve performance.
What do I mean by "efficient" reading? Efficient reading means reading bytes off of the InputStream / Reader as fast as they appear. Imagine you wanted to load a whole text file to display in an IDE or other editor. "inefficient" reading is when you are reading information off of the stream piecemeal - ie Scanner.nextDouble() is inefficient reading, as it reads in a few bytes (until the double's digits end), then transforms the number from text to binary. In this case, having a buffer improves performance, as the next call to nextDouble() will read out of the buffer (memory) instead of disk
If you have any questions on this, please ask
Open the file using an input stream. Then read its content to a string using this code:
public static void main(String args[]) throws IOException {
FileInputStream in = null;
in = new FileInputStream("input.txt");
String text = inputStreamToString(is);
}
// Reads an InputStream and converts it to a String.
public String inputStreamToString(InputStream stream) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while((length = stream.read(buffer)) != -1)
byteArrayOutputStream.write(buffer,0,length);
return byteArrayOutputStream.toString("UTF-8");
}
Check this answer for comparisons between buffered readers:
Read/convert an InputStream to a String
I normally use Scanners when I want to read a file line by line, or based on a delimiter. For example:
try {
Scanner fileScanner = new Scanner(System.in);
File file = new File("file.txt");
fileScanner = new Scanner(file);
while (fileScanner.hasNextLine()) {
String line = fileScanner.nextLine();
System.out.println(line);
}
fileScanner.close();
} catch (Exception ex) {
ex.printStackTrace();
}
To scan based on a delimiter, you can use something similar to this:
fileScanner.userDelimiter("\\s"); // \s matches any whitespace
while(fileScanner.hasNext()){
//do something with scanned data
String word = fileScanner.next();
//Double num = fileScanner.nextDouble();
}

BufferedReader#readLine() hangs even though a line has been read

Updated Question (to be more clear):
Is there a way to design the InputStream below such that BufferedReader#readLine() will return after reading the new line character?
In the example below, readLine() hangs forever even though the reader has read a new line because (presumably) it is waiting for the buffer to fill up. Ideally, readLine() would return after reading the new line character.
I know something like what I want is possible, because when you read from System.in using BufferedReader#readLine(), it does not wait for the buffer to fill up before returning.
import java.io.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class Example {
private static final class MyInputStream extends InputStream {
public final BlockingQueue<String> lines = new LinkedBlockingQueue<>();
private InputStream current = null;
#Override
public int read() throws IOException {
try {
if(current == null || current.available() == 0)
current = new ByteArrayInputStream(lines.take().getBytes("UTF-8"));
return current.read();
}
catch(InterruptedException ex) {
return -1;
}
}
}
public static void main(String[] args) throws Exception {
MyInputStream myin = new MyInputStream();
myin.lines.offer("a line\n");
BufferedReader in = new BufferedReader(new InputStreamReader(myin));
System.out.println(in.readLine());
}
}
Also, if there is a better way to send a string to an InputStream, I'm open to suggestions.
Accepted Solution:
Based on a suggestion from Sotirios Delimanolis in one of the comments on his solution, I'm just going to used a PipedInputStream instead. I've coupled it to a PipedOutputStream, and BufferedReader#readLine() returns immediately as long as I call PipedOutputStream#flush() after sending a string that contains a new line character.
After updated question, the only way to get the BufferedReader to stop reading after the new line character is to set the buffer size to 1, which completely removes the need for a BufferedReader.
You'll have to write your own implementation.
A BufferedReader reads more bytes than required. In your case, that means it will read further than the new line character. For example, with the Oracle JVM, it will attempt to read 8192 bytes. Through your inheritance hierarchy, this
System.out.println(in.readLine());
will attempt to invoke your read() method 8192 times.
The first 6 calls will return a value, one for each of the characters in your String's byte array. The next one, will see
if(current == null || current.available() == 0)
current = new ByteArrayInputStream(lines.take().getBytes("UTF-8"));
and current.available() will return 0 since the ByteArrayInputStream has been fully consumed. It will then attempt to take from the BlockingQueue and block indefinitely.
Also, if there is a better way to send a string to an InputStream, I'm open to suggestions.
Well, instead of an InputStream you can try a BufferedReader, with something that looks like this:
public int read(String directory) throws Exception{
String line = "";
File file = new File(directory);
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
do{
lines.add(br.readLine());
while(br.readLine() != null);
br.close();
return Integer.parseInt(line);
}

readLine of BufferedReader does not change file pointer

My app reads text file line by line and record offset of each line until the end of file. offset returns changed value when readLine is first executed. But it does not change any more after that. What is wrong with my code? I use RandomAccessFile instead of FileInputStream because seek() is faster than skip() when file is big.
String buffer;
long offset;
RandomAccessFile raf = new RandomAccessFile("data.txt", "r");
FileInputStream is = new FileInputStream(raf.getFD());
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while (true) {
offset = raf.getFilePointer(); // offset remains the same after 1st readLine. why?
if ((buffer = br.readLine()) == null) // buffer has correct value.
return;
………………………………
}
Because BufferedReader is buffered. So it reads the data into it's buffer the first time and then just keeps it there until it needs more buffered data.
If you want to use a smaller buffer for testing purposes, try new BufferedReader(new InputStreamReader(is), 1000); or something. Your pointer should now increment by 1000 occasionally.
If you want your counter to work properly, you can do one of two things. Either you can count the characters you are receiving and then do some converting to byte lengths which you can use to make your own counter or you can use a FileReader with no buffering which will increment the counter the way you expect.
Update: It seems FileReader does something behind the scenes. I'd use something like new CountingInputStream(new BufferedInputStream(new FileInputStream(raf.getFD())) loop through the data in byte form, manually identify line endings while dumping the bytes into a String. Not the prettiest way, but the only way I can think of given Reader's internal buffering. I think CountingInputStream is provided by Apache freely and it contains a count method or something like that.

Java - printing lines from buffered reader

I'm writing an InputStream that supplies lines from a file in constant intervals. I used BufferedReader before, but ran into buffering issues with it (wasn't getting anything until the entire file was read), and speed isn't an issue anyways (the intervals are something like every second, or every half second - along those lines). Is there a class with a readLine method like in BufferedReader, except unbuffered?
(Edit: I just checked - my class seems to work, apparently the problem was with the output)
Here's the code where I used the stream (OnlineDataSimulator). I already checked, the stream does exactly what I want, so apparently I'm doing something wrong with the output. (The actual problem is, I want output to occur every X milliseconds - X being the second parameter to OnlineDataSimulator. What happens when I run this code is, that I first get an X*lines wait and then the entire output at once instead.)
System.out.println("Testing:");
PrintStream fout = new PrintStream(new FileOutputStream("testfile"));
for(int i=0; i<20; ++i) {
fout.println(i);
}
fout.close();
BufferedReader fin = new BufferedReader(new InputStreamReader(
new OnlineDataSimulator("testfile",250)));
String line;
while((line=fin.readLine())!= null){
System.out.println(line);
System.out.flush();
}
fin.close();
(new File("testfile")).delete();
Try it this way.... This worked for me..
File f = new File("path");
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr);
String s = null;
while ((s=br.readLine())!=null)
{
System.out.println(s);
}
No, there is no other non-buffered option.
A solution would be to write your own Reader which has a InputStreamReader as an underlying stream and in the readLine() method you should call read() of the underlying input stream reader until "\n" is found. Aggregate all these and return them as a string.
If you don't want to have a real buffer but want to use the functionality of BufferedReader you could initialize it with buffer size 1. As you commented that speed isn't an issue maybe is the most reliable solution.
new BufferedReader(reader, 1)
public BufferedReader(Reader in, int sz)
and you can check the readLine() method source code here, in case you want to implement your own.

Bufferedreader explanation?

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.in(Standard input stream)- gets the input from keyboard in bytes
InputStreamReader: Converts the bytes into Unicode characters/ converts the standard input into reader object to be used with BufferedReader
Finally BufferedReader: Used to read from character input stream(Input stream reader)
String c = br.ReadLine(); -- a method used to read characters from input stream and put them in the string in one go not byte by byte.
Is everything above right ? Please correct if anything wrong !
Nearly there, but this:
String c = br.readLine(); -- a method used to read characters from input stream and put them in the string in one go not byte by byte.
It reads characters from the input reader (BufferedReader doesn't know about streams) and returns a whole line in one go, not character by character. Think of it in layers, and "above" the InputStreamReader layer, the concept of "bytes" doesn't exist any more.
Also, note that you can read blocks of characters with a Reader without reading a line: read(char[], int, int) - the point of readLine() is that it will do the line ending detection for you.
(As noted in comments, it's also readLine, not ReadLine :)
What is the purpose of BufferedReader, explanation?
Bufferedreader is a java class, the following is the hierarchy of this class.
java.lang.Object ==> java.io.Reader ==> java.io.BufferedReader
Also, BufferedReader provides an efficient way to read content. Very Simple..
Let's have a look at the following example to understand.
import java.io.BufferedReader;
import java.io.FileReader;
public class Main {
public static void main(String[] args) {
BufferedReader contentReader = null;
int total = 0; // variable total hold the number that we will add
//Create instance of class BufferedReader
//FileReader is built in class that takes care of the details of reading content from a file
//BufferedReader is something that adds some buffering on top of that to make reading fom a file more efficient.
try{
contentReader = new BufferedReader(new FileReader("c:\\Numbers.txt"));
String line = null;
while((line = contentReader.readLine()) != null)
total += Integer.valueOf(line);
System.out.println("Total: " + total);
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
finally{
try{
if(contentReader != null)
contentReader.close();
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
}
}

Categories