Is it possible to put a string array into buffered Reader? - java

I'm working on a project at the moment which requires me to set up a distributed network simulator, I had it working with taking output from a file and parsing through each line with a buffered reader as you can see below but I want to now use a predefined array and make my bufferedReader take input from that instead I've looked up a few solutions online to help me put this array into the buffered Reader but non seem to have worked.
I'm getting no errors when running and terminating the code but just seems to be stuck in an endless loop at some point and I presume it's the new buffered reader segment using the array instead. The idea behind this was to make the process simpler than re-writing many segments to fit around the array parsing and instead find a simpler way by having the array in the buffered Reader but as this is proving difficult I may have to resort to changing. I have tested if the array is being initialised correctly and that's not the problem so it's one less thing to take into consideration.
**Previous code:**
private void parseFile(String fileName) throws IOException {
System.out.println("Parsing Array");
Path path = Paths.get(fileName);
try (BufferedReader br = Files.newBufferedReader(path)) {
String line = null;
line = br.readLine(); // Skip first line
while ((line = br.readLine()) != null) {
parseLine(line);
}
} catch (IOException x) {
System.err.format("IOException: %s%n", x);
}
}
The recommendation online was to use an input stream with the buffered reader for it but that didn't seem to work at all as it over wrote the array, any recommendations on what I can use for the buffered reader segment would be grand.
The Array method above is just a void creating the array which is called before the method so the array should be initialised I presume, If anyone can look over and potentially let me know where I'm going wrong and problems that would be amazing if not I appreciate your time to read this anyway, Thanks for your time.
New Code Attempt:
//Creating array to parse.
private void createArray(){
myStringArray[0] = "Node_id Neighbours";
myStringArray[1] = "1 2 10";
myStringArray[2] = "2 3 1";
myStringArray[3] = "3 4 2";
myStringArray[4] = "4 5 3";
myStringArray[5] = "5 6 4";
myStringArray[6] = "6 7 5";
myStringArray[7] = "7 8 6";
myStringArray[8] = "8 9 7";
myStringArray[9] = "9 10 8";
myStringArray[10] = "10 1 9";
myStringArray[11] = "ELECT 1 2 3 4 5 6 7 8 9";
}
private void parseArray() throws IOException {
//InputStreamReader isr = new InputStreamReader(System.in);
System.out.println("Parsing Array");
// try (BufferedReader br = Files.newBufferedReader(path))
try (BufferedReader br = new BufferedReader(isr)) {
for(int i=0;i<12;i++)
{
String line = null;
line = br.readLine(); // Skip first line
while ((myStringArray[i] = br.readLine()) != null) {
parseLine(line);
}
}
} catch (IOException x) {
System.err.format("IOException: %s%n", x);
}
}
Answer: You cannot do this with buffered reader. I fixed it like this if this is any use to anyone. Thanks a lot to #L.Spillner for the explanation and answer.
code fix:
private void parseArray() throws IOException {
System.out.println("Parsing Array");
for(int i=1;i<12;i++) //First row ignored.
{
String line = null;
line = myStringArray[i];
//Begin parsing process of each entity.
parseLine(line);
}
}

Let's kick it off with a precise answer to the Question.
You cannot put anything into a BufferedReader directly. Especially when it's some kind of data structure like an array.
The BufferedReader's purpose is to handle I/O Operations, input operations to be more precise. According to the javadoc the BufferedReader takes a Reader as an argument. Reader is an abstract class which contains 'tools' to handle character InputStreams.
The way the BufferedReader's readLine() method works is: Any character arriving on the InputStream gets stored in a buffer until a \n (new line/linefeed) or \r (carriage retun) arrives. When one of these two special characters show up the buffer gets interpreted as a String and is returned to the call.

Answer is you can't. Thanks for the feedback though guys and got it working through just looping through the array and assigning each item to line.

Related

assigning properties to strings in text file

Hopefully my explanation does me some justice. I am pretty new to java. I have a text file that looks like this
Java
The Java Tutorials
http://docs.oracle.com/javase/tutorial/
Python
Tutorialspoint Java tutorials
http://www.tutorialspoint.com/python/
Perl
Tutorialspoint Perl tutorials
http://www.tutorialspoint.com/perl/
I have properties for language name, website description, and website url. Right now, I just want to list the information from the text file exactly how it looks, but I need to assign those properties to them.
The problem I am getting is "index 1 is out of bounds for length 1"
try {
BufferedReader in = new BufferedReader(new FileReader("Tutorials.txt"));
while (in.readLine() != null) {
TutorialWebsite tw = new TutorialWebsite();
str = in.readLine();
String[] fields = str.split("\\r?\\n");
tw.setProgramLanguage(fields[0]);
tw.setWebDescription(fields[1]);
tw.setWebURL(fields[2]);
System.out.println(tw);
}
} catch (IOException e) {
e.printStackTrace();
}
I wanted to test something so i removed the new lines and put commas instead and made it str.split(",") which printed it out just fine, but im sure i would get points taken off it i changed the format.
readline returns a "string containing the contents of the line, not including any line-termination characters", so why are you trying to split each line on "\\r?\\n"?
Where is str declared? Why are you reading two lines for each iteration of the loop, and ignoring the first one?
I suggest you start from
String str;
while ((str = in.readLine()) != null) {
System.out.println(str);
}
and work from there.
The first readline gets the language, the second gets the description, and the third gets the url, and then the pattern repeats. There is nothing to stop you using readline three times for each iteration of the while loop.
you can read all the file in a String like this
// try with resources, to make sure BufferedReader is closed safely
try (BufferedReader in = new BufferedReader(new FileReader("Tutorials.txt"))) {
//str will hold all the file contents
StringBuilder str = new StringBuilder();
String line;
while ((line = in.readLine()) != null) {
str.append(line);
str.append("\n");
} catch (IOException e) {
e.printStackTrace();
}
Later you can split the string with
String[] fields = str.toString().split("[\\n\\r]+");
Why not try it like this.
allocate a List to hold the TutorialWebsite instances.
use try with resources to open the file, read the lines, and trim any white space.
put the lines in an array
then iterate over the array, filling in the class instance
the print the list.
The loop ensures the array length is a multiple of nFields, discarding any remainder. So if your total lines are not divisible by nFields you will not read the remainder of the file. You would still have to adjust the setters if additional fields were added.
int nFields = 3;
List<TutorialWebsite> list = new ArrayList<>();
try (BufferedReader in = new BufferedReader(new FileReader("tutorials.txt"))) {
String[] lines = in.lines().map(String::trim).toArray(String[]::new);
for (int i = 0; i < (lines.length/nFields)*nFields; i+=nFields) {
TutorialWebsite tw = new TutorialWebsite();
tw.setProgramLanguage(lines[i]);
tw.setWebDescription(lines[i+1]);
tw.setWebURL(lines[i+2]);
list.add(tw);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
list.forEach(System.out::println);
A improvement would be to use a constructor and pass the strings to that when each instance is created.
And remember the file name as specified is relative to the directory in which the program is run.

Returning the number of lines in a .txt file

This is my debut question here, so I will try to be as clear as I can.
I have a sentences.txt file like this:
Galatasaray beat Juventus 1-0 last night.
I'm going to go wherever you never can find me.
Papaya is such a delicious thing to eat!
Damn lecturer never gives more than 70.
What's in your mind?
As obvious there are 5 sentences, and my objective is to write a listSize method that returns the number of sentences listed here.
public int listSize()
{
// the code is supposed to be here.
return sentence_total;}
All help is appreciated.
To read a file and count its lines, use a java.io.LineNumberReader, plugged on top of a FileReader. Call readLine() on it until it returns null, then getLineNumber() to know the last line number, and you're done !
Alternatively (Java 7+), you can use the NIO2 Files class to fully read the file at once into a List<String>, then return the size of that list.
BTW, I don't understand why your method takes that int as a parameter, it it's supposed to be the value to compute and return ?
Using LineNumberReader:
LineNumberReader reader = new LineNumberReader(new FileReader(new File("sentences.txt")));
reader.skip(Long.MAX_VALUE);
System.out.println(reader.getLineNumber() + 1); // +1 because line index starts at 0
reader.close();
use the following code to get number of lines in that file..
try {
File file = new File("filePath");
BufferedReader reader = new BufferedReader(new FileReader(file));
String line;
int totalLines = 0;
while((line = reader.readLine()) != null) {
totalLines++;
}
reader.close();
System.out.println(totalLines);
} catch (Exception ex) {
ex.printStackTrace(System.err);
}
You could do:
Path file = Paths.getPath("route/to/myFile.txt");
int numLines = Files.readAllLlines(file).size();
If you want to limit them or process them lazily:
Path file = Paths.getPath("route/to/myFile.txt");
int numLines = Files.llines(file).limit(maxLines).collect(Collectors.counting...);

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());
}
}
}
}

what is the efficent way to process larges text files?

I have two files:
1- with 1400000 line or record --- 14 MB
2- with 16000000 -- 170 MB
I want to find if each record or line in file 1 is also in file 2 or not
I develop a java app that do the following: Read file line by line and pass each line to a method that loop in file 2
Here is my code:
public boolean hasIDin(String bioid) throws Exception {
BufferedReader br = new BufferedReader(new FileReader("C://AllIDs.txt"));
long bid = Long.parseLong(bioid);
String thisLine;
while((thisLine = br.readLine( )) != null)
{
if (Long.parseLong(thisLine) == bid)
return true;
}
return false;
}
public void getMBD() throws Exception{
BufferedReader br = new BufferedReader(new FileReader("C://DIDs.txt"));
OutputStream os = new FileOutputStream("C://MBD.txt");
PrintWriter pr = new PrintWriter(os);
String thisLine;
int count=1;
while ((thisLine = br.readLine( )) != null){
String bioid = thisLine;
System.out.println(count);
if(! hasIDin(bioid))
pr.println(bioid);
count++;
}
pr.close();
}
When I run it seems it will take more 1944.44444444444 hours to complete as every line processing takes 5 sec. That is about three months!
Is there any ideas to make it done in a much much more less time.
Thanks in advance.
Why don't you;
read all the lines in file2 into a set. Set is fine, but TLongHashSet would be more efficient.
for each line in the second file see if it is in the set.
Here is a tuned implementation which prints the following and uses < 64 MB.
Generating 1400000 ids to /tmp/DID.txt
Generating 16000000 ids to /tmp/AllIDs.txt
Reading ids in /tmp/DID.txt
Reading ids in /tmp/AllIDs.txt
Took 8794 ms to find 294330 valid ids
Code
public static void main(String... args) throws IOException {
generateFile("/tmp/DID.txt", 1400000);
generateFile("/tmp/AllIDs.txt", 16000000);
long start = System.currentTimeMillis();
TLongHashSet did = readLongs("/tmp/DID.txt");
TLongHashSet validIDS = readLongsUnion("/tmp/AllIDs.txt",did);
long time = System.currentTimeMillis() - start;
System.out.println("Took "+ time+" ms to find "+ validIDS.size()+" valid ids");
}
private static TLongHashSet readLongs(String filename) throws IOException {
System.out.println("Reading ids in "+filename);
BufferedReader br = new BufferedReader(new FileReader(filename), 128*1024);
TLongHashSet ids = new TLongHashSet();
for(String line; (line = br.readLine())!=null;)
ids.add(Long.parseLong(line));
br.close();
return ids;
}
private static TLongHashSet readLongsUnion(String filename, TLongHashSet validSet) throws IOException {
System.out.println("Reading ids in "+filename);
BufferedReader br = new BufferedReader(new FileReader(filename), 128*1024);
TLongHashSet ids = new TLongHashSet();
for(String line; (line = br.readLine())!=null;) {
long val = Long.parseLong(line);
if (validSet.contains(val))
ids.add(val);
}
br.close();
return ids;
}
private static void generateFile(String filename, int number) throws IOException {
System.out.println("Generating "+number+" ids to "+filename);
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(filename), 128*1024));
Random rand = new Random();
for(int i=0;i<number;i++)
pw.println(rand.nextInt(1<<26));
pw.close();
}
170Mb + 14Mb is not so huge files.
My suggestion is to load the smallest one file into java.util.Map, parse the biggest one line-by-line (record-by-record) file and check if the current line present in this Map.
P.S. The question looks like something trivial in terms of RDBMS - maybe it's worth to use any?
You can't do an O(N^2) when each iteration is so long, that's completely unacceptable.
If you have enough RAM, you simply parse file 1, create a map of all numbers, then parse file 2 and check your map.
If you don't have enough RAM, parse file 1, create a map and store it to a file, then parse file 2 and read the map. The key is to make the map as easy to parse as possible - make it a binary format, maybe with a binary tree or something where you can quickly skip around and search. (EDIT: I have to add Michael Borgwardt's Grace Hash Join link, which shows an even better way: http://en.wikipedia.org/wiki/Hash_join#Grace_hash_join)
If there is a limit to the size of your files, option 1 is easier to implement - unless you're dealing with huuuuuuuge files (I'm talking lots of GB), you definitely want to do that.
Usually, memory-mapping is the most efficient way to read large files. You'll need to use java.nio.MappedByteBuffer and java.io.RandomAccessFile.
But your search algorithm is the real problem. Building some sort of index or hash table is what you need.

Java: How to read a text file

I want to read a text file containing space separated values. Values are integers.
How can I read it and put it in an array list?
Here is an example of contents of the text file:
1 62 4 55 5 6 77
I want to have it in an arraylist as [1, 62, 4, 55, 5, 6, 77]. How can I do it in Java?
You can use Files#readAllLines() to get all lines of a text file into a List<String>.
for (String line : Files.readAllLines(Paths.get("/path/to/file.txt"))) {
// ...
}
Tutorial: Basic I/O > File I/O > Reading, Writing and Creating text files
You can use String#split() to split a String in parts based on a regular expression.
for (String part : line.split("\\s+")) {
// ...
}
Tutorial: Numbers and Strings > Strings > Manipulating Characters in a String
You can use Integer#valueOf() to convert a String into an Integer.
Integer i = Integer.valueOf(part);
Tutorial: Numbers and Strings > Strings > Converting between Numbers and Strings
You can use List#add() to add an element to a List.
numbers.add(i);
Tutorial: Interfaces > The List Interface
So, in a nutshell (assuming that the file doesn't have empty lines nor trailing/leading whitespace).
List<Integer> numbers = new ArrayList<>();
for (String line : Files.readAllLines(Paths.get("/path/to/file.txt"))) {
for (String part : line.split("\\s+")) {
Integer i = Integer.valueOf(part);
numbers.add(i);
}
}
If you happen to be at Java 8 already, then you can even use Stream API for this, starting with Files#lines().
List<Integer> numbers = Files.lines(Paths.get("/path/to/test.txt"))
.map(line -> line.split("\\s+")).flatMap(Arrays::stream)
.map(Integer::valueOf)
.collect(Collectors.toList());
Tutorial: Processing data with Java 8 streams
Java 1.5 introduced the Scanner class for handling input from file and streams.
It is used for getting integers from a file and would look something like this:
List<Integer> integers = new ArrayList<Integer>();
Scanner fileScanner = new Scanner(new File("c:\\file.txt"));
while (fileScanner.hasNextInt()){
integers.add(fileScanner.nextInt());
}
Check the API though. There are many more options for dealing with different types of input sources, differing delimiters, and differing data types.
This example code shows you how to read file in Java.
import java.io.*;
/**
* This example code shows you how to read file in Java
*
* IN MY CASE RAILWAY IS MY TEXT FILE WHICH I WANT TO DISPLAY YOU CHANGE WITH YOUR OWN
*/
public class ReadFileExample
{
public static void main(String[] args)
{
System.out.println("Reading File from Java code");
//Name of the file
String fileName="RAILWAY.txt";
try{
//Create object of FileReader
FileReader inputFile = new FileReader(fileName);
//Instantiate the BufferedReader Class
BufferedReader bufferReader = new BufferedReader(inputFile);
//Variable to hold the one line data
String line;
// Read file line by line and print on the console
while ((line = bufferReader.readLine()) != null) {
System.out.println(line);
}
//Close the buffer reader
bufferReader.close();
}catch(Exception e){
System.out.println("Error while reading file line by line:" + e.getMessage());
}
}
}
Look at this example, and try to do your own:
import java.io.*;
public class ReadFile {
public static void main(String[] args){
String string = "";
String file = "textFile.txt";
// Reading
try{
InputStream ips = new FileInputStream(file);
InputStreamReader ipsr = new InputStreamReader(ips);
BufferedReader br = new BufferedReader(ipsr);
String line;
while ((line = br.readLine()) != null){
System.out.println(line);
string += line + "\n";
}
br.close();
}
catch (Exception e){
System.out.println(e.toString());
}
// Writing
try {
FileWriter fw = new FileWriter (file);
BufferedWriter bw = new BufferedWriter (fw);
PrintWriter fileOut = new PrintWriter (bw);
fileOut.println (string+"\n test of read and write !!");
fileOut.close();
System.out.println("the file " + file + " is created!");
}
catch (Exception e){
System.out.println(e.toString());
}
}
}
Just for fun, here's what I'd probably do in a real project, where I'm already using all my favourite libraries (in this case Guava, formerly known as Google Collections).
String text = Files.toString(new File("textfile.txt"), Charsets.UTF_8);
List<Integer> list = Lists.newArrayList();
for (String s : text.split("\\s")) {
list.add(Integer.valueOf(s));
}
Benefit: Not much own code to maintain (contrast with e.g. this). Edit: Although it is worth noting that in this case tschaible's Scanner solution doesn't have any more code!
Drawback: you obviously may not want to add new library dependencies just for this. (Then again, you'd be silly not to make use of Guava in your projects. ;-)
Use Apache Commons (IO and Lang) for simple/common things like this.
Imports:
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;
Code:
String contents = FileUtils.readFileToString(new File("path/to/your/file.txt"));
String[] array = ArrayUtils.toArray(contents.split(" "));
Done.
Using Java 7 to read files with NIO.2
Import these packages:
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
This is the process to read a file:
Path file = Paths.get("C:\\Java\\file.txt");
if(Files.exists(file) && Files.isReadable(file)) {
try {
// File reader
BufferedReader reader = Files.newBufferedReader(file, Charset.defaultCharset());
String line;
// read each line
while((line = reader.readLine()) != null) {
System.out.println(line);
// tokenize each number
StringTokenizer tokenizer = new StringTokenizer(line, " ");
while (tokenizer.hasMoreElements()) {
// parse each integer in file
int element = Integer.parseInt(tokenizer.nextToken());
}
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
To read all lines of a file at once:
Path file = Paths.get("C:\\Java\\file.txt");
List<String> lines = Files.readAllLines(file, StandardCharsets.UTF_8);
All the answers so far given involve reading the file line by line, taking the line in as a String, and then processing the String.
There is no question that this is the easiest approach to understand, and if the file is fairly short (say, tens of thousands of lines), it'll also be acceptable in terms of efficiency. But if the file is long, it's a very inefficient way to do it, for two reasons:
Every character gets processed twice, once in constructing the String, and once in processing it.
The garbage collector will not be your friend if there are lots of lines in the file. You're constructing a new String for each line, and then throwing it away when you move to the next line. The garbage collector will eventually have to dispose of all these String objects that you don't want any more. Someone's got to clean up after you.
If you care about speed, you are much better off reading a block of data and then processing it byte by byte rather than line by line. Every time you come to the end of a number, you add it to the List you're building.
It will come out something like this:
private List<Integer> readIntegers(File file) throws IOException {
List<Integer> result = new ArrayList<>();
RandomAccessFile raf = new RandomAccessFile(file, "r");
byte buf[] = new byte[16 * 1024];
final FileChannel ch = raf.getChannel();
int fileLength = (int) ch.size();
final MappedByteBuffer mb = ch.map(FileChannel.MapMode.READ_ONLY, 0,
fileLength);
int acc = 0;
while (mb.hasRemaining()) {
int len = Math.min(mb.remaining(), buf.length);
mb.get(buf, 0, len);
for (int i = 0; i < len; i++)
if ((buf[i] >= 48) && (buf[i] <= 57))
acc = acc * 10 + buf[i] - 48;
else {
result.add(acc);
acc = 0;
}
}
ch.close();
raf.close();
return result;
}
The code above assumes that this is ASCII (though it could be easily tweaked for other encodings), and that anything that isn't a digit (in particular, a space or a newline) represents a boundary between digits. It also assumes that the file ends with a non-digit (in practice, that the last line ends with a newline), though, again, it could be tweaked to deal with the case where it doesn't.
It's much, much faster than any of the String-based approaches also given as answers to this question. There is a detailed investigation of a very similar issue in this question. You'll see there that there's the possibility of improving it still further if you want to go down the multi-threaded line.
read the file and then do whatever you want
java8
Files.lines(Paths.get("c://lines.txt")).collect(Collectors.toList());

Categories