buffered reader input into char array - java

I want to take an input from a txt file and put all the characters to the array so I can perform on it some regex functions. But when I try to read the array with a single loop to check it, nothing appears. What is wrong here?
import java.io.BufferedReader;
import java.io.FileReader;
public class Main
{
public static void main(String[] args)
{
try
{
Task2.doTask2();
}catch(Exception e){};
}
}
class Task2
{
public static void doTask2() throws Exception
{
FileReader fr = new FileReader("F:\\Filip\\TextTask2.txt");
BufferedReader br = new BufferedReader(fr);
char[] sentence = null;
int i;
int j = 0;
while((i = br.read()) != -1)
{
sentence[j] = (char)i;
j++;
}
for(int g = 0; g < sentence.length; g++)
{
System.out.print(sentence[g]);
}
br.close();
fr.close();
}
}

You can read a file simply using File.readAllBytes. Then it's not necessary to create separate readers.
String text = new String(
Files.readAllBytes(Paths.get("F:\\Filip\\TextTask2.txt"))
);
In the original snippet, the file reading function is throwing a NullPointerException because sentence was initialized to null and then dereferenced: sentence[j] = (char)i;
The exception was swallowed by the calling function and not printed, which is why you're not seeing it when you run the program: }catch(Exception e){};
Instead of swallowing the exception declare the calling function as throwing the appropriate checked exception. That way you'll see the stack trace when you run it: public static void main(String[] args) throws IOException {

You are using wrong index , use "g" instead of "i" here.:
System.out.println(sentence[g]);
Also, the best and simplest way to do this is:
package io;
import java.nio.file.*;;
public class ReadTextAsString
{
public static String readFileAsString(String fileName)throws Exception
{
return new String(Files.readAllBytes(Paths.get(fileName)));
}
public static void main(String[] args) throws Exception
{
String data = readFileAsString("F:\\Filip\\TextTask2.txt");
System.out.println(data); //or iterate through data if you want to print each character.
}
}

Related

Java OutputStream that incrementally processes text

I want to incrementally process the text written to an OutputStream as it is written.
For example, suppose we have this program:
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
public class Streaming {
// Writes file, incrementally, to OutputStream.
static void dump(File file, OutputStream out) throws IOException {
// Implementation omitted
}
static int sum = 0;
public static void main(String[] args) throws IOException {
Charset charSet = Charset.defaultCharset(); // Interpret the file as having this encoding.
dump(new File("file.txt"), new OutputStream() {
#Override
public void write(int b) throws IOException {
// Add b to bytes already read,
// Determine if we have reached the end of the token (using
// the default encoding),
// And parse the token and add it to `sum`
}
});
System.out.println("Sum: " + sum);
}
}
Suppose file.txt is a text file containing a space-delimited list of ints. In this program, I wish to find the sum of the ints in file.txt, accumulating the sum in the sum variable. I would like to avoid building up a String that is millions of characters long.
I'm interested in a way that I can accomplish this using the dump function, which writes the contents of a file to an output stream. I'm not interested in reading the file in another way (e.g. creating a Scanner for file.txt and repeatedly calling nextInt on the scanner). I'm imposing this restriction because I'm using a library that has an API similar to dump, where the client must provide an OutputStream, and the library subsequently writes a lot of text to the output stream.
How can I implement the write method to correctly perform the steps as outlined? I would like to avoid doing the tokenization by hand, since utilities like Scanner are already capable of doing tokenization, and I want to be able to handle any encoding of text (as specified by charSet). However, I can't use Scanner directly, because there's no way of checking (in a non-blocking way) if a token is available:
public static void main(String[] args) throws IOException {
Charset charSet = Charset.defaultCharset();
PipedInputStream in = new PipedInputStream();
try (Scanner sc = new Scanner(in, charSet)) {
dump(new File("file.txt"), new PipedOutputStream(in) {
#Override
public void write(byte[] b, int off, int len) throws IOException {
super.write(b, off, len);
// This will loop infinitely, because `hasNextInt`
// will block if there is no int token currently available.
if (sc.hasNextInt()) {
sum += sc.nextInt();
}
}
});
}
System.out.println("Sum: " + sum);
System.out.println(charSet);
}
Is there a non-blocking utility that can perform the tokenization for me as data is written to the output stream?
If I understand your question correctly, FilterOutputStream is what you want to subclass. DigestOutputStream extends FilterOutputStream and does something somewhat similar to what you want to do: it monitors the bytes as they come through and passes them to a different class for processing.
One solution that comes to mind is for the FilterOutputStream to pass the bytes to a PipedOutputStream, connected to a PipedInputStream which a different thread reads in order to create your sum:
PipedOutputStream sumSink = new PipedOutputStream();
Callable<Long> sumCalculator = new Callable<Long>() {
#Override
public Long call()
throws IOException {
long sum = 0;
PipedInputStream source = new PipedInputStream(sumSink);
try (Scanner scanner = new Scanner(source, charSet)) {
while (scanner.hasNextInt()) {
sum += scanner.nextInt();
}
}
return sum;
}
};
Future<Long> sumTask = ForkJoinPool.commonPool().submit(sumCalculator);
OutputStream dest = getTrueDestinationOutputStream();
dest = new FilterOutputStream(dest) {
#Override
public void write(int b)
throws IOException {
super.write(b);
sumSink.write(b);
}
#Override
public void write(byte[] b)
throws IOException {
super.write(b);
sumSink.write(b);
}
#Override
public void write(byte[] b,
int offset,
int len)
throws IOException {
super.write(b, offset, len);
sumSink.write(b, offset, len);
}
#Override
public void flush()
throws IOException {
super.flush();
sumSink.flush();
}
#Override
public void close()
throws IOException {
super.close();
sumSink.close();
}
};
dump(file, dest);
long sum = sumTask.get();
As "idiomatic" approach, you might want a FilterOutputStream:
These streams sit on top of an already existing output stream (the underlying output stream) which it uses as its basic sink of data, but possibly transforming the data along the way or providing additional functionality.
At least to me, it sounds something like what you describe.
It is a concrete class (unlike OutputStream), so the absolute minimum you can get away with is to provide your constructor and an implementation for the single-byte write() (which is going to be invoked by the default implementations of other write() methods):
public class SumOutputStream extends FilterOutputStream {
public int sum = 0;
public SumOutputStream(OutputStream os) {
super(os);
}
private int num = 0;
public void write(int b) throws IOException {
if (b >= '0' && b <= '9') {
sum -= num;
num = num * 10 + b - '0';
sum += num;
} else {
num = 0;
}
out.write(b);
}
public static void main(String[] args) throws IOException {
try (SumOutputStream sos = new SumOutputStream(new FileOutputStream("test.txt"))) {
sos.write("123 456 78".getBytes());
System.out.println(sos.sum);
sos.write('9');
System.out.println(sos.sum);
}
}
}
This will sum whatever numbers are passing, keeping sum up to date all the time even with partial results (that is what separating the 9 is supposed to show).
Based off #tevemadar's answer. Reads in strings and tries to parse them to ints. If that fails, then you know the number is done and is then added to the sum. The only problem is that my method doesn't add the last number if it occupies the last two bytes. To solve this, you could add a single line method: if(!currNumber.isEmpty()) sum += Integer.parseInt(currNumber); that you can call once the file finishes.
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Objects;
class SumOutputStream extends FilterOutputStream {
public int sum = 0;
String currNumber = "";
String lastChar = "";
public SumOutputStream(OutputStream os){
super(os);
}
public void write(byte b[], int off, int len) throws IOException {
Objects.checkFromIndexSize(off, len, b.length);
for (int i = 0 ; i < len ; i++) {
try {
if(!lastChar.isEmpty()) {
Integer.parseInt(lastChar);
currNumber += lastChar;
}
} catch(NumberFormatException e) {
if(!currNumber.isEmpty()) sum += Integer.parseInt(currNumber);
currNumber = "";
} catch(NullPointerException e) {
e.printStackTrace();
}
write(b[off + i]);
lastChar = new String(b);
}
}
}

Printing a returning value

I've just started with Java, and so far been only playing around solving problems online, where you're not supposed to write the whole functional of a program, but only adjust a few lines of code to the already organized code.
However, I'm still struggling to organize my code in a compiling program in IntelliJ Idea, getting confused at,e.g. how methods invocations must be properly written.
Here's what I'm getting stuck with: an example from codingbat.com:
- Given a string, return a new string made of every other char starting with the first, so "Hello" yields "Hlo".
I've come up with a solution online, but now I wanna run it in Idea, with main method, with Scanner/BufferedReader input from console etc. Looks like I'm missing something...
import java.util.Scanner;
public class Bat
{
public static void main (String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();
printString();
}
public String stringBits(String str) {
String result = "";
for (int i = 0; i<str.length();i += 2) {
result += str.substring(i, i+1);
}
return result;
}
public static void printString () {
System.out.println(result);
}
}
I ask your help to solve it out. What to do to make it:
Read a word from a console;
create a new string;
print it out.
Two alternatives:
make stringBits static
create an instance of the class Bat and invoke the member method
First solution - easy, not much to change
import java.util.Scanner;
public class Bat {
public static void main (String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();
printString(stringBits(str));
}
public static String stringBits(String str) {
String result = "";
for (int i = 0; i < str.length();i += 2) {
result += str.substring(i, i + 1);
}
return result;
}
public static void printString (String string) {
System.out.println(string);
}
}
Second solution - a bit more advances
import java.util.Scanner;
public class Bat {
private String string;
public Bat(String string) {
this.string = string;
}
public static void main (String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();
Bat bat = new Bat(str);
bat.printStringBits();
}
private String stringBits() {
String result = "";
for (int i = 0; i < string.length(); i += 2) {
result += string.substring(i, i + 1);
}
return result;
}
public void printStringBits() {
System.out.println(stringBits());
}
}
Your result variable is only accessible from within the "stringBits" method. Since the method returns a string you can do the following to print it:
System.out.println(stringBits(string)); //Call in main method in place of printString();
Edited: My code wasn't a working example. Note that stringBits has to be a static method in order to work.

How do I read and process a file in a separate method and call it in the main method in Java?

I have this code i'm working on to compute the ARI of a given text read from the a .txt file. This code works perfectly but I want to put in fewer things in my main method. How is it able to put my try and catch block in a new method and then call it to my main method instead of having everything mashed together? I have tried some few ways but i'm not getting the usual output.
Here is my main class:
public class MyClass {
public static void main(String[] args){
String EachSentence;
int wordCount;
List<Sentence> sentences = new ArrayList<>();
List<Integer> EachWordCount = new ArrayList<>();
List<Integer> EachLetterCounted= new ArrayList<>();
try{
File file = new File("a2b.txt");
Scanner scanner = new Scanner(file);
scanner.useDelimiter("[.?!]");
int SentenceCount =0;
while(scanner.hasNext()){
SentenceCount++;
EachSentence = scanner.next();
EachSentence = EachSentence.replaceAll("\\r?\\n", " ");
EachSentence = EachSentence.trim();
if (sentences.add(new Sentence(EachSentence)) && sentences.size() > 1){
System.out.println("(" + SentenceCount + ") " + EachSentence);
}
StringTokenizer tokenizer = new StringTokenizer(EachSentence, " ");
wordCount = tokenizer.countTokens();
if(EachWordCount.add(wordCount)&& EachWordCount.size() > 1){
//I removed the element at position 0 so as to correlate with EachSentence then added the counts to the arrayList
//to prepare them for addition
EachWordCount.remove(0);
EachWordCount.add(wordCount);
}
int LetterCount=1;
for(int i=1; i<EachSentence.length(); i++){
char currentChar = EachSentence.charAt(i);
if(currentChar != ' '&& currentChar!='('&&currentChar!=')'&&currentChar!=','&& currentChar!='.'){
EachLetterCounted.add(LetterCount);
LetterCount++;
}
}
}
scanner.close();
}catch (IOException ex){
System.out.println(ex.getMessage());
}
//Computes the ARI of the total sentences
double lettersCounted = (double) lettersCounted(EachLetterCounted);
double wordsCounted = (double) sum(EachWordCount);
double sentencesCounted = (double) SentencesCounted(EachWordCount);
double AutomatedReadabilityIndex= 4.71*(lettersCounted/wordsCounted) + 0.5 * (wordsCounted/sentencesCounted) -21.43;
System.out.println("\nSummary statistics: ");
System.out.println("Letters: "+lettersCounted(EachLetterCounted));
System.out.println("Words: "+ sum(EachWordCount));
System.out.println("Sentences: " + SentencesCounted(EachWordCount));
DecimalFormat df = new DecimalFormat("#.##");
System.out.println("readability: "+ df.format(AutomatedReadabilityIndex));
}
contributions would be great!
Second time answering my question.(For anyone having the same problem) I achieved this by simply putting everything I had in the main method in a ...static void ReadFile() method and calling only `ReadFile in the main method. It may not be the best way but it was what I was looking for :)
public static void main(String[] args) {
ReadFile();
}
public static void ReadFile() {
//insert all what is in main method, the exceptions were handled
//here also. So there was no need for the throws IOException that
//should've followed.
}
OR
public static void main(String[] args) {
ReadFile(//insert name of file to be read here);
}
public static void ReadFile(String filename) {
//insert all what is in main method, the exceptions were handled
//here also. So there was no need for the throws IOException that
//should've followed.
}

using get and set methods to pass an array between two classes (java)

In my class ReadInput, i read a file containing integers separated by space one by one and put them into inputArray. I then want to use inputArray (and its size) in my class B and i'm attempting to do that with get and set methods but I guess i'm not using them correctly and can't pinpoint my error. Can anyone help? Thanks
import java.io.*;
import java.util.*;
public class ReadInput
{
String INPUT_FILE_NAME = "pages.dat"; // filename
private int [] inputArray;
private int size;
public ReadInput()
{
Scanner fileIn=null; //(Initialization keeps compiler happy)
try { // open file
fileIn = new Scanner(new FileInputStream(INPUT_FILE_NAME));
} catch (FileNotFoundException e) {
System.out.println("Input file "+INPUT_FILE_NAME+" not found. ");
System.exit(1);
}
while (fileIn.hasNextLine())
{
String word = fileIn.next();
size++;
}
inputArray = new int [size];
//test to see that it gives correct size
System.out.println(size);
fileIn.close(); // close file
try { // open file
fileIn = new Scanner(new FileInputStream(INPUT_FILE_NAME));
} catch (FileNotFoundException e) {
System.out.println("Input file "+INPUT_FILE_NAME+" not found. ");
System.exit(1);
}
int i=0;
while (fileIn.hasNextLine())
{
inputArray[i] = fileIn.nextInt();
i++;
}
fileIn.close();
}
public int [] getinputArray()
{
return inputArray;
}
public void setinputArray(int [] inputArray)
{
this.inputArray = inputArray;
}
public int getSize()
{
return size;
}
public void setsize(int size)
{
this.size = size;
}
}
public class B
{
ReadInput in = new ReadInput();
int [] inputs;
public B()
{
}
//this method does not work and gives an error
public void method()
{
System.out.println("in FIFO: " + in.getSize());
for(int j=0; j< inputs.length; j++)
System.out.print(inputs[j] + " ");
}
}
In B's constructor, you need to call in.initializeArrays() and in.getJobs().
Right now, in.getSize() is 0 since that's the default value of ReadInput.size. In addition, in.getInputArray() will be null since that is the default value of ReadInput.inputArray.
Alternatively, you could remove ReadInput.initializeArrays() and ReadInput.getJobs() and simply move the code into a zero-argument constructor for ReadInput, like so:
class ReadInput {
// previous fields: size, inputArray, etc.
public ReadInput() {
// code for setting size and populating inputArray from the file
}
// other methods: getJobs, etc.
}
If you do this, then you should be set. You're already calling ReadInput's constructor through your ReadInput in = new ReadInput(); line, so that line should then populate in's data.
In B's constructor, I don't see you calling
in.initializeArrays
or
setinputArray(int [] inputArray)
anywhere to actually set the array before getting the size.

Why does this code trigger an infinite loop?

I am writing some simple code to parse a file and return the number of lines but the little red box in eclipse won't go off so I assume I am triggering an infinite loop. Th Text file i am reading has only 10 lines...here's the code: What am I doing wrong?
import java.io.*;
import java.util.Scanner;
public class TestParse {
private int noLines = 0;
public static void main (String[]args) throws IOException {
Scanner defaultFR = new Scanner (new FileReader ("C:\\workspace\\Recommender\\src\\IMDBTop10.txt"));
TestParse demo = new TestParse();
demo.nLines (defaultFR);
int x = demo.getNoLines ();
System.out.println (x);
}
public TestParse() throws IOException
{
noLines = 0;
}
public void nLines (Scanner s) {
try {
while (s.hasNextLine ())
noLines++;
}
finally {
if (s!=null) s.close ();
}
}
public int getNoLines () {
return noLines;
}
}
You're not calling s.nextLine() in the while-loop:
should be:
while(s.hasNextLine()){
s.nextLine(); // <<<
noLines++;
}
You only check hasNextLine within your loop. This checks if another line is present but does not read it. Let it follow by nextLine and your code will work.
while(s.hasNextLine()){
s.nextLine();
noLines++;
}

Categories

Resources