Read a file and convert it to an array (Java) - java

So I have a collection of phrases that are separated by newlines and I would like to populate an array with these phrases. This is what I have so far:
Scanner s;
s = new Scanner(new BufferedReader(new FileReader("Phrases.txt")));
for(i = 0; i < array.length;i++)
{
s.nextLine() = array[i];
}
Is there a fast and simple way to just populate an array with phrases separated by newlines?

The assignment should be reverse: -
array[i] = s.nextLine();
And, I think you should fill your array based on the input received from the file. Here you are receving input based on the length of your pre-declared array. I mean, since you are using an array, your size is fixed. So you can only populate it with a fixed number of phrases.
A better way would be to use an ArrayList.
List<String> phrases = new ArrayList<String>();
Now, you can populate your arraylist, based on the phrases you get from your file. You don't need to pre-define the size. It increases in size dynamically.
And to add phrases, you would do: -
phrases.add(s.nextLine());
With a while loop to read till EOF.
while (s.hasNextLine()) {
phrases.add(s.nextLine());
}

Since you don't know how many phrases you're likely to have (I suspect), I would populate an ArrayList<String> and convert it to an array using ArrayList.toArray() once you're done. I'd perhaps keep it as a Java collection, however, for greater flexibility.

You have the assignment operation inverted (array[i] should be set to s.nextLine(), not the other way around. Also, it would be best to modify the for loop to terminate when no more lines exist:
for(i = 0; i < array.length && s.hasNextLine() ;i++) {
array[i] = s.nextLine()
}

It can be done with a 1 liner with apache commons and specifically FileUtils.readLines()
FileUtils.readLines(myFile).toArray(new String[0]);

Don't waste your time with Scanner. BufferedReader is just fine. Try this:
BufferedReader br = new BufferedReader(new FileReader("Phrases.txt")));
LinkedList<String> phrases = new LinkedList<String>();
while(br.ready()) {
phrases.add(br.readLine());
}
String[] phraseArray = phrases.toArray(new String[0]);
By the way it's important to use LinkedList not ArrayList if the file is large. That way you only create one array at the end. Otherwise you will have a lot of large array creation and wasted memory.

you are doing it wrong. it has to be
for(i = 0; i < array.length;i++)
{
array[i]=s.nextLine();
}
array[i] = value; // the value would be assigned into the array at index i.
However, a better option would be to use a List implementing classes such as ArrayList which gives you an advantage of dynamic size.
List<String> list = new ArrayList<>();
list.add(s.nextLine(());

Related

Problems changing from Enhanced for loop to normal for loop

I am extracting data from a csv format to java. I have written some code for it.
Reader reader = Files.newBufferedReader(Paths.get(FilePath));
CSVReader csvReader = new CSVReaderBuilder(reader).build();
List<String[]> records = csvReader.readAll();
for(String[] record : records) {
System.out.println(record[0]); // Note : Each record has two strings in it separated by delimiter ";"
String[] parts = record[0].split(";"); //So I am splitting here
System.out.println(parts[0]); //First part
System.out.println(parts[1]); //Second part
}
My main aim is to store the parts after splitting each String from an array of Strings i.e., from "records". The console gives the output as how I expected. But I don't want to print on console but store it in two different ArrayLists.
Hence I tried to change the for loop to a normal for loop as follows:
ArrayList<List<String>> separatedTime = new ArrayList<List<String>>();
ArrayList<List<String>> separatedValues = new ArrayList<List<String>>();
String[] Array = new String[records.size()];
for(int i = 0; i < records.size(); i++) {
Array[i] = (records[i]); //Error : Type of expression must be an array type. But it is resolved to List<String[]>
String[] parts = Array[i].split(";");
separatedTime.add(parts[0]); //Error : The method add(List<String>) in the type ArrayList<List<String>> is not applicable for the arguments (String)
separatedValues.add(parts[1]);
}
But this doesnot work. I cannot figure out why is it not working
1) if it is changed from enhanced for loop to normal for loop. If I am wrong, how can I change to normal for loop?
2) After splitting with delimiter in normal for loop, why am I not able to store in Array List
I know I somewhere, somehow stepped into wrong. But unable to find out how can I rectify
Got it!! I solved using the following :
String[] Array = null;
for(int i=0; i<records.size();i++)
{
Array = (records.get(i));
String[] parts = Array[0].split(";");
separatedTime.add(parts[0]);
separatedValues.add(parts[1]);
}
Everything is solved.. Thank you all for your time

How do i declare custom generated strings inside a while loop?

What I'm trying to do is to declare a certain amount of strings according to the amount of tokens a scanner scans in a single input, then have these strings equal the next input. This is what I'm trying:
int numberOfTokens = 0;
boolean mainLoop = true;
Scanner input = new Scanner(System.in);
while(mainLoop == true)
{
while(input.hasNext())
{
String int(+ numberOfTokens) = input.next(); (this doesn't work)
numberOfTokens += 1;
}
}
I hope I made it clear of what I am trying to do. I tried using String arrays, but they won't work for what i'm trying to do.
Thanks.
You can do:
String[] myStringArray = new String[abc];
where abc is an integer you get from user
and then
myStringArray[index] = input.next();
and index must be a valid number between 0 and abc
If you don't know in advance how many strings you will need to store then an array is a poor choice of data structure, at least during the input phase. Use a List instead -- these keep the elements in order, yet expand as needed to accommodate new elements. They are convenient to work with overall, but if you ultimately must get the strings in array form (e.g. because some external API requires that form) then it is easy to obtain the corresponding array.
For example:
List<String> tokens = new ArrayList<>();
while (input.hasNext()) {
tokens.add(input.next());
// a List keeps track of its own length
}
If you later wanted the array then you could do
String[] tokenArray = tokens.toArray(new String[0]);
The number of tokens recorded in the List is available at any time as tokens.size(), or after you convert to an array, as tokenArray.length.
In any event, you cannot create new variables at runtime in Java.
Instead of string variables, you should declare one variable like this before the while loop.
List<String> tokens = new ArrayList<>();
while (input.hasNext()) {
tokens.add(input.next());
}
You can then operate on the tokens, like this:
int n = tokens.size();
for (String token : tokens) {
System.out.println(token);
}

Store a text lines in an array in java

I have some texts which contain some lines. There is a word in every line. I should copy the text and then paste it to the Eclipse Console Output window and finally store each line in an array.
I don't know how many lines does each text have. How could I do this?
I know if I want to store some strings to an array I should do like bellow, but I don't want to do by this method:
String[] Lines = {"line1", "line2", ....};
If you don't know how many lines you will have you could use a generic list.
List<String> lines = new ArrayList<String>();
This will resize dynamically as you add values to it.
You could also use arrays and do the resizing yourself, which is what the ArrayList does behind the scenes, it's just that it adds complexity to your code.
You can not change an array size after you initialize it. If you change your previous data will be lost. You can use ArrayList to add items dynamically. For example;
ArrayList<String> list = new ArrayList<>();
//read your file here and print it. After that;
list.add(line); // I assumed you get lines to a variable called line
If you are using JDk 7+ you could easily do this by
List<String> list = Files.readAllLines(new File("test.txt").toPath());
But if you still want to use array convert that list to array like
List<String> list = Files.readAllLines(new File("test.txt").toPath());
String[] str = list.toArray(new String[list.size()]);
Or if you dont have a file and copy pasting to console try this
List<String> lines = new ArrayList<String>();
Scanner s = new Scanner(System.in);
while(s.hasNextLine()){
String line = s.nextLine();
if(line.length() > 0) {
lines.add(s.nextLine());
} else {
break;
}
}
System.out.println(lines);

Continuous input gathering until conditions met?

I am trying to understand gathering user input and looping until conditions.
I want to loop a scanner until user inputs 0, however, I need each inputted integer to be stored so it can be accessed for later use. The hard part is, I can't use an array.
simply you can do something like
List mylist = new ArrayList(); //in java. other wise you can create array[size]
int input = 1;
while(input!=0)
{
/* input number from user here */
if(input!=0)
mylist.add(input);
}
Here is an easy way to loop user input until 0 is entered.
Scanner console = new Scanner(System.in);
boolean loop = true;
String input;
while(loop) {
input = console.nextLine();
//Add input to a data structure
if (input.equals("0")) {
loop = false;
}
}
As far as adding the user input to a data structure, you said you can't use an Array. How about a List or a Set. Even a Stack or a Queue would work. Have you looked at using any of these data structures?
Here is a basic example using a List:
List<String> aList = new ArrayList<String>();
aList.add(input);
And this is how you might use a Stack:
Stack<String> stk = new Stack<String>();
stk.push(input);
Perhaps the most efficient way would be to use a HashSet:
Set<String> set = new HashSet<String>();
set.add(input);
Using arrays here would be little tricky since you don't know the numbe of elements user is going to enter. You can always write the code to create a new array with bigger capacity once user has exhaused initial capacity and copy over existing input elements but using List would be much easier.
Scanner scanner = new Scanner(System.in);
List<Integer> input = new ArrayList<>();
int nextInt = Integer.MIN_VALUE;
while((nextInt = scanner.nextInt()) != 0){
input.add(nextInt);
}
See this question if you really want to use arrays. Answer explains on creating new arrays and copying over elements. Java dynamic array sizes?

Fastest method for reading file data in Arrays (Java)

Take a look at the following link:
http://snippetsofjosh.wordpress.com/tag/advantages-and-disadvantages-of-arraylist/
This one of the reasons why I always prefer to use Arrays instead of (Array)Lists.
Still, this got me thinking about memory management and speed.
Hence I arrived at the following question:
What is the best way to store data from a file when you don't know the size of the file (/number of entries) (where best is defined as 'the least amount of computation time')
Below, I will present 3 different methods and I would like to know which one of them is best and why. For the clarity of the question, let's assume I must end up with an Array. Also, let's assume every line from our .txt file only has one entry (/one string). Also, for limiting the scope of the questions, I will limit this question to Java only.
Let's say we want to retrieve the following info from a file called words.txt:
Hello
I
am
a
test
file
Method 1 - Double and dangerous
File read = new File("words.txt");
Scanner in = new Scanner(read);
int counter = 0;
while (in.hasNextLine())
{
in.nextLine();
counter++;
}
String[] data = new String[counter];
in = new Scanner(read);
int i = 0;
while (in.hasNextLine())
{
data[i] = in.nextLine();
i++;
}
Method 2 - Clear but redundant
File read = new File("words.txt");
Scanner in = new Scanner(read);
ArrayList<String> temporary = new ArrayList<String>();
while (in.hasNextLine())
{
temporary.add(in.nextLine());
}
String[] data = new String[temporary.size()];
for (int i = 0; i < temporary.size(); i++)
{
data[i] = temporary.get(i);
}
Method 3 - Short but rigid
File read = new File("words.txt");
FileReader reader = new FileReader(read);
String content = null;
char[] chars = new char[(int) read.length()];
reader.read(chars);
content = new String(chars);
String[] data = content.split(System.getProperty("line.separator"));
reader.close();
If you have an alternative way (which is even better) then please supply it below.
Also, feel free to adjust my code where necessary.
Answer:
The fastest method for storing data in an array is the following method:
File read = new File("words.txt");
Scanner in = new Scanner(read);
ArrayList<String> temporary = new ArrayList<String>();
while (in.hasNextLine()) {
temporary.add(in.nextLine());
}
String[] data = temporary.toArray(new String[temporary.size()]);
And for Java 7+:
Path loc = Paths.get(URI.create("file:///Users/joe/FileTest.txt"));
List<String> lines = Files.readAllLines(loc, Charset.defaultCharset());
String[] array = lines.toArray(new String[lines.size()]);
I assume that best means faster here.
I would use method 2, but create the array with the methods provided by the Collection interface:
String[] array = temporary.toArray(new String[temporary.size()]);
Or even simpler (Java 7+):
List<String> lines = Files.readAllLines(file, charset);
String[] array = lines.toArray(new String[lines.size()]);
Other methods:
method 1 does two passes and it is very unlikely that reading a file is more efficient than resizing an arraylist
I am not sure if method 3 is faster or not
Update:
for the sake of completeness, I have run a microbenchmark with the modified method2 as above and including an additional method (method4) that reads all bytes at once, creates a string and split on new lines. The results (in mn microseconds):
Benchmark Mean
method1 126.178
method2 59.679
method3 76.622
method4 75.293
Edit:
with a larger 3MB file: LesMiserables.txt, the results are consistent:
Benchmark Mean
method1 608649.322
method2 34167.101
method3 63410.496
method4 65552.79
A very good comparison with all the source code is given here java_tip_how_read_files_quickly
Summary:
For the best Java read performance, there are four things to remember:
Minimize I/O operations by reading an array at a time, not a byte at a time. An 8Kbyte array is a good size.
Minimize method calls by
getting data an array at a time, not a byte at a time. Use array
indexing to get at bytes in the array.
Minimize thread synchronization locks if you don't need thread safety. Either make
fewer method calls to a thread-safe class, or use a non-thread-safe
class like FileChannel and MappedByteBuffer.
Minimize data copying
between the JVM/OS, internal buffers, and application arrays. Use
FileChannel with memory mapping, or a direct or wrapped array
ByteBuffer.
Hope that helps.
EDIT
I would do sth like that:
File read = new File("words.txt");
Scanner in = new Scanner(read);
List<String> temporary = new LinkedList<String>();
while (in.hasNextLine()) {
temporary.add(in.nextLine());
}
String[] data = temporary.toArray(new String[temporary.size()]);
The main difference is reading data only once (as opposed to other 2 methods) and addition in linkedlist is very cheap + no extra operation on lines needed (like splitting) - don't use arraylist here
If you are reading data from a file, the bottleneck will be the file reading (IO) stage. The time spent processing it will be insignificant in almost all cases. So do what is correct and safe. First you make it right; then you make it fast.
If you don't know the size of the file you must have some kind of dynamically expanding data structure. Which is what ArrayList is. Code you write yourself is unlikely to be more eficient or correct than such an important part of the Java API. So just use ArrayList: option 2.
I would use guava
File file = new File("words.txt");
List<String> lines = Files.readLines(file, Charset.defaultCharset());
// If it really has to be an array:
String[] array = lines.toArray(new String[0]);
List<String> lines = Files.readAllLines(yourFile, charset);
String[] arr = lines.toArray(new String[lines.size()]);

Categories

Resources