Using BufferedReader - java

I am doing a method involving BufferedReader and I to have use it as an input argument, can someone tell me how to use it as an input argument but initialize it outside the method?
Other thing is, how do I get the buffer to read special characterS? (eg: ยด, ~)
public static List<Pacote<Pair<String, Double>>> create(
BufferedReader fileReader, int capacidadePacotes)
throws IOException {
List retorno = new ArrayList <> (6);
String s;
while ((s=fileReader.readLine())!=null){
retorno.add(parseItem(s));
}
return retorno;
}
It basically reads a file and sends it to another function that treats the text and creates objects based on that, I'm just not clear on the whole using BufferedReader as an input argument, have just used it inside the method before so I'm unclear on how to initialize it properly, probably a dumb question but I would like to know how to do it properly

You can initialize the BufferedReader object as follows if you are trying to read a file.
public static void main(String[]args) {
BufferedReader rdr = new BufferedReader(new FileReader("filepath"));
int capacidadePacotes = 10;
create(rdr, capacidadePacotes);
}
//urcode for create
The buffered reader can read line by line using the readLine() method. If you read null that means you reached the end of the file. A more readable way to use the buffered reader would be the following:
String s = rdr.readLine();
while(s != null) { //while u didn't reach the end of the file
//your code
s = rdr.readLine();
}

If you want to initialize it "outside" the method, why not hand it over like that:
create(new BufferedReader(reader, 3));
Or how exactly do you want it to have instantiated? For the instantiation, you need a Reader, which can be handed over. If you want to create a Reader from a file, the answer is also in the following link.
How to read special characters with a BufferedReader:
Read special characters in java with BufferedReader

Related

JAVA: How to parse log file till specific line is found like a tail command in linux?

I want to parse the log file till specific line is found in the log file like a tail command.
I am using bufferreader and want to do something like this-
Code-
BufferedReader br = new BufferedReader(new
FileReader("/file1.txt"));
String line;
boolean keepReading = true;
while (br.readLine()!= null) {
line= br.readLine();
if(line.equals("string found"))
{
break;
}
else
{
//some stuff
}}
I just want to wait for particular string, till then I just want to continue the loop but the condition is, may be the specific string is yet to come and I want to wait for it?
String comparisons should be done with the equals(String) method. Strings are immutable objects, meaning each string is a separate object. The equals(String) method compares the content of the strings.
In Java you check string equality by :
if(line.equals("string found")){
}

Save huge amount of Strings in file during program execution in Java

In my program the main logic is to construct Strings in different methods and then to save them in a specific order in a file. But my memory consumption is very high, so I wonder how to save less strings in memory. So I will try to simplify the program for the ease of reading here. My small String Generating methods do like:
Then my main logic is something like:
BufferedWriter bw = new BufferedWriter(fw);
for(int i=1;i<1_000_000_000;i++){
bw.write(processMethod(i));
}
bw.close();
where the processMethod is a method that calls methods like generateTag m times, makes String using StringBuilder and then saves to BufferedWriter .
public static String generateTag(final String tagName, final String name, final String value) {
StringBuilder attribute = new StringBuilder();
attribute.append("<tag:");
attribute.append(tagName);
attribute.append(" name=\"");
attribute.append(name);
attribute.append("\">");
attribute.append(value);
attribute.append("</tag:");
attribute.append(tagName);
attribute.append(">");
return attribute.toString();
}
So when I start the processMethod executes 1_000_000_000 times and then m times is called generateTag like methods. I have 1_000_000_000 * m strings in the memory. How can I easily remove their creation? I think something like:
public static String generateTag(final String tagName, final String name, final String value, final BufferedWriter bf) {
....
bf.write(someBuilder.toString());
..
}
But passing BufferedWriter around is not a good I think.
Can you suggest me some less String created description.
If indeed your program merely calls methods one after the other and those methods generate strings and those strings are written to the file in the order they are generated, then it's simpler to write directly to the file using the main BufferedWriter:
try (BufferedWriter bw = new BufferedWriter(fw);) {
for(int i=1;i<1_000_000_000;i++){
processMethod(i, bw);
}
}
(Note that I used try-with-resources to automatically close the buffered writer).
And then when processMethod calls generateTag, it passes the buffered writer to it:
public void processMethod(int i, BufferedWriter bw) {
...
generateTag(...,bw);
...
}
And generateTag is going to be:
public static void generateTag(final String tagName, final String name, final String value, final BufferedWriter bw) {
bw.write("<tag:");
bw.write(tagName);
bw.write(" name=\"");
bw.write(name);
bw.write("\">");
bw.write(value);
bw.write("</tag:");
bw.write(tagName);
bw.write(">");
}
Since BufferedWriter is buffered, it means that there is disk access not every time you call write, but every time the buffer is filled up. So this won't cost you in disk access speed. But it will save you all that memory.
Of course, if you don't write the results serially, or the result of one method depends on the result of the other, then you need to modify this, but still, you should write as soon as you have the next piece of String ready.
One thing you may consider is to not saving them in memory, and instead write them as soon as possible...
many XML api like jdom, dom and dom4j abet the harmful habits of building tree model in memory, whereas in reality, it is far more efficient to dump the byte out into output buffer asap...
You could rewrite your method to include an output stream variable and flush out all the bytes out with the output stream.
Use the Appendable abstraction to ensure the generateTag (and likewise processMethod, if you wish) have no dependency to BufferedWriter. In fact, we can even pass a StringBuilder to do the same as before, a feature, which we can use to provide an appropriate overload:
public static CharSequence generateTag(
final String tagName, final String name, final String value) {
StringBuilder attribute=new StringBuilder(80);
try { generateTag(tagName, name, value, attribute); }
catch (IOException ex) { throw new AssertionError(ex); }
return attribute;
}
public static void generateTag(
final String tagName, final String name, final String value, Appendable attribute)
throws IOException {
attribute.append("<tag:");
attribute.append(tagName);
attribute.append(" name=\"");
attribute.append(name);
attribute.append("\">");
attribute.append(value);
attribute.append("</tag:");
attribute.append(tagName);
attribute.append(">");
}
Note that the overload returns CharSequence rather than String to be able to omit the final StringBuilder.toString() copying step. Unfortunately, calling append(CharSequence)on the BufferedWriter with it would not pay off, given the current implementation. Still there are APIs allowing to use CharSequence directly.

BufferedReader returns null, even though the stream it's reading from is at pos 0

I am trying to pass data from a program MainProgram to another program TestProgram which I invoke using Reflection. For this, i re-route Standard.in to a ByteArrayOutputStream containing the data I want to transmit. TestProgram then reads from Standard.in using a BufferedReader and readLine(). I execute the whole thing several times in a for-loop. The problem is this: The first time, everything works fine, from the second time on, TestProgram reads null from System.in. Java Documentation states that the BufferedReader will return null, if the end of stream is reached. But there is definitely data in the stream and the pos of my ByteArrayOutputStream is also 0. Why could the BufferedReader think that suddenly System.in is empty or at the end of stream?
Here is the code that's manipulating the streams and invoking the method:
for(int i = 0; i < numberOfCases; i++) {
Byte[] paramBytes = getCurrentParamBytes();
InputStream inputStream = new BufferedInputStream(new ByteArrayInputStream(paramBytes));
System.setIn(inputStream);
String[] params = null;
testProgram.invoke(null, (Object) params);
}
Here is the code that's reading from System.in:
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String current = in.readLine();
I have assured myself of the state of System.in using the debugging mode of Eclipse and everything is fine there. The fact that it only reads null starting with the second invocation of the TestProgram's main method is also very puzzling to me. Especially, because all values I have checked are exactly the same as they were the first time (except for the data in the stream, of course).
Sadly, I cannot change the use of the BufferedReader because TestProgram is not my class and has to be used as-is.
Any help would be greatly appreciated.
The problem is likely in the fact that BufferedReader created once, on first invocation. BufferedReader uses instance of InputStream that you provided on first iteration of a loop. On second, third, etc invocations it still uses this stream and doesn't read from updated System.in. I see 2 possible solutions if you can't modify source code of TestProgram.
Create new instance of TestProgram on each iteration instead of reusing old. It might help to "refresh" inner BufferedReader if it is stored as class variable, not static.
if you can't create new instance of TestProgram because it has state or BufferedReader stored in static variable you can try following: use special kind of InputStream that allows you to concatenate several InputStreams on fly. Check ConcatInputStream.
Example of second approach:
ConcatInputStream concat = new ConcatInputStream();
System.setIn(concat);
for(int i = 0; i < numberOfCases; i++) {
Byte[] paramBytes = getCurrentParamBytes();
InputStream inputStream = new BufferedInputStream(new ByteArrayInputStream(paramBytes));
concat.addInputStream(inputStream);
String[] params = null;
testProgram.invoke(null, (Object) params);
}
I'm not sure it will work because I don't know what is behaviour of BufferedReader if it sees end of stream on first invocation and then, on second invocation, stream suddenly not empty any more (because we've added new stream to concat). But hopefully it will work.
There are also third approach: you can decompile TestProgram using e.g. JD and find where instance of BufferedReader is stored. And then you can set it to null between iterations using reflections. But it's very error prone.

Picking up from where I left off when reading a file in Java

I am trying to read info from a file and create objects out of that information. Every 6 or so lines of the file is a different unit, meaning that the first set of lines are relevant to object A, the next set to object B, and so on.
I can read from the file and create my object just fine--for the first set. My problem is that I don't know how to get the reader to pick up from the spot it left off at when creating the next object...
(Note: the read() method which creates the file is part of the new object being created, not in a main() or anything like that). Here are the relevant bits of code:
The driver:
public class CSD{
public static void main (String[] argv){
Vector V=new Vector(10);
CoS jon=new CoS();
jon.display();
}//end main
}
which calls CoS, whose constructor is:
public CoS(){
try{
String fileName=getFileName();
FileReader freader=new FileReader(fileName);
BufferedReader inputFile=new BufferedReader(freader);
this.read(inputFile);
setDegree(major);
setStatus(credits);
} catch(FileNotFoundException ex){
}//end catch
}
Which calls both read() and getFileName():
public void read(BufferedReader inputFile){
try{
int n;
super.read(inputFile);
String str=inputFile.readLine();
if (str!=null){
n=Integer.parseInt(str);
setCredits(n);
str=inputFile.readLine();
setMajor(str);
}//end if
}catch(IOException ex){}
}//end method
public String getFileName() {
Scanner scan = new Scanner(System.in);
String filename;
System.out.print("Enter the file name and path ==> ");
filename = scan.nextLine();
System.out.println("");
return filename;
}
Thanks in advance, guys!
Why not use ObjectInputStream and ObjectOutputStream? Or any kind of real serialization?
javadoc: http://docs.oracle.com/javase/6/docs/api/java/io/ObjectOutputStream.html
example code: http://www.javadb.com/writing-objects-to-file-with-objectoutputstream
Basically, since you write your objects to a file and want to take care of the lines where they are located, I'll suggest a few other serialization alternatives.
One is the Object * Stream - you create a ObjectStream on a File and just write objects thru it. Later when you read, you read the objects in the reverse order you wrote them and they will come back just as you wrote them.
Another is to implement Serializable. Remember that transient keyword? Use it on fields you do not want to save to the file.
And then there's the raw "by hand" approach where you save only the things you want to save and reconstruct the objects later by passing these initialization values to their constructor. Kinda like people suggested that you make the file line a argument to the ctor :)
EDIT:
guess writing with Object*Streams requires you to implement Serializable or Externalizable.
but if the example code isn't clear enough, ask :)

replace a string segment from input stream

I am trying to receive a huge text file as an inputstream and want to convert a string segment with another string. I am strictly confused how to do it, it works well if I convert whole inputstream as a string which I don't want as some of the contents are lost. can anyone please help how to do it??
e.g.
if I have a file which has the contents "This is the test string which needs to be modified". I want to accept this string as input stream and want to modify the contents to "This is the test string which is modified" , ( by replacing 'needs to be' with is).
public static void main(String[] args) {
String string = "This is the test string which needs to be modified";
InputStream inpstr = new ByteArrayInputStream(string.getBytes());
//Code to do
}
In this I want the output as: This is the test string which is modified
Thanking you in advance.
If the text to be changed will always fit in one logical line, as I stated in comment, I'd go with simple Line Reading (if applyable) using something like:
public class InputReader {
public static void main(String[] args) throws IOException
{
String string = "This is the test string which needs to be modified";
InputStream inpstr = new ByteArrayInputStream(string.getBytes());
BufferedReader rdr = new BufferedReader(new InputStreamReader(inpstr));
String buf = null;
while ((buf = rdr.readLine()) != null) {
// Apply regex on buf
// build output
}
}
}
However I've always like to use inheritance so I'd define this somewhere:
class MyReader extends BufferedReader {
public MyReader(Reader in)
{
super(in);
}
#Override
public String readLine() throws IOException {
String lBuf = super.readLine();
// Perform matching & subst on read string
return lBuf;
}
}
And use MyReader in place of standard BufferedReader keeping the substitution hidden inside the readLine method.
Pros: substitution logic is in a specified Reader, code is pretty standard.
Cons: it hides the substitution logic to the caller (sometimes this is also a pro, still it depends on usage case)
HTH
May be I understood you wrong, but I think you should build a stack machine. I mean you can use a small string stack to collect text and check condition of replacement.
If just collected stack already is not matched to your condition, just flush stack to output and collect it again.
If your stack is similar with condition, carry on collecting it.
If your stack is matched your condition, make a modification and flush modified stack to output.

Categories