I was trying to scan a file that has an array of doubles. I'm using the code below but it's only outputting 0.0 for every entry. Why is this and how can I fix it?
Scanner scanner = new Scanner("file.txt");
double[] array = new double[256 * 256];
for (int i = 0; i < array.length; i++) {
if (scanner.hasNextDouble()) {
array[i] = scanner.nextDouble();
}
}
System.out.println(array[0]);
An example of the file I'm scanning is
0.22131145 0.22131145 0.22131145 0.22841525 0.22841525 ...
The main issue is with the instantiation of the Scanner object. In this case you need to pass a File object into it, not just a string, and make sure you specify the correct file path. Refer to the official documentation for advice.
Secondly, you need to use a while-loop. An if-statement will execute only once, but you would want the Scanner to continue looking whilst there is info inside the file.
Thirdly, don't use an array for storing the values. It's too risky because you need to know the size of the array beforehand, meaning that you would need to loop twice, which would be inefficient, or you are hard coding, as you are doing here. If someone were to add or remove values from the file, you will get unexpected results. Rather use a dynamic data structure such as a List.
public static void main(String[] args) throws FileNotFoundException {
String filepath = "file.txt";
Scanner scanner = new Scanner(new File(filepath));
List<Double> list = new ArrayList<>();
while (scanner.hasNextDouble()) {
list.add(Double.valueOf(scanner.next()));
}
scanner.close();
System.out.println(list.get(0));
}
There are four problems with your code:
Blocker: Scanner expects a File object but you haven't used it in this way. You need to use the following syntax:
Scanner scanner = new Scanner(new File("file.txt"));
Performance: You can improve the performance of your program by including scanner.hasNextDouble() in the condition which checks the value of i, as shown below:
for (int i = 0; i < array.length && scanner.hasNextDouble(); i++) {
array[i] = scanner.nextDouble();
}
This will terminate the loop as soon as scanner.hasNextDouble() returns false; otherwise, the loop in your code will continue to run until i < array.length evaluates to false irrespective of the value returned by scanner.hasNextDouble().
Resource leak: You have not closed the Scanner object. Put the following line after the loop finishes:
scanner.close();
Missed functionality: You haven't printed the complete array. Your statement, System.out.println(array[0]) will print only the first element in the array. Change it as follows to print the complete array:
System.out.println(Arrays.toString(array));
Given below the code incorporating all the above-mentioned comments:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
Scanner scanner = new Scanner(new File("file.txt"));
double[] array = new double[256 * 256];
for (int i = 0; i < array.length && scanner.hasNextDouble(); i++) {
array[i] = scanner.nextDouble();
}
scanner.close();
System.out.println(Arrays.toString(array));
}
}
Memory utilization: You have used a fixed-sized array which is fine if the number of elements to be stored is equal to the size of the array. However, if it is not the case (i.e. if the number of elements to be stored can be less than or more than the specified size), you should use a Collection e.g. an ArrayList which is a kind of dynamic array. This will help you in many ways: (a) You will save memory if the number of elements to be stored is less than the specified size (b) You do not need to change your code in order to increase the size of the array when you need to store more elements than you have already specified (c) The Collection provides with a rich API to deal with elements. By leveraging this API, your code can be crisp, more performant, maitainable etc.
Given below the code incorporating the 5th point:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
Scanner scanner = new Scanner(new File("file.txt"));
List<Double> list = new ArrayList<>();
while (scanner.hasNextDouble()) {
list.add(scanner.nextDouble());
}
scanner.close();
System.out.println(list);
}
}
Related
I'm relatively new to Java, so I have to look up how to do things constantly. I'm working on a project that involves analyzing a number of familiar sorts such as heap sort, merge sort, etc. I wrote a bit of code to produce a variety of different arrays, each in their own .txt file. Here is a portion of the code:
import java.io.*;
import java.util.Arrays;
import java.util.Collections;
public class ArrayBuilder {
public static void main(String[] args) throws IOException {
for(int i = 2; i < 7; i++) {
int aLength = (int)Math.pow(10, i);
buildAscendingArray(aLength);
buildDescendingArray(aLength);
buildRandomArray(aLength);
}
}
public static void buildAscendingArray(int arrayLength) throws IOException {
File file = new File("arrays_" + arrayLength + "A.txt");
PrintWriter printWriter = new PrintWriter(file);
int[] array = new int[arrayLength];
for(int i = 0; i < array.length; i++) {
array[i] = i + 1;
}
printWriter.println(Arrays.toString(array));
printWriter.close();
}
I didn't include the random and descending methods as they are more or less the same so trying to save room. So...
I already have all the sorts coded, I'm just trying to figure out how to read in the integer arrays so I can run them through the different sorts. I'm also trying to factor adding in System.nanoTime() to clock the time it takes to run each sort so I can compare them given the various inputs. Not sure if this needs to be added into the method for each sort or whether it can be implemented in the call ie. System.nanoTime(heapsort(array))) ?
Ultimately I'm looking for some help on getting the .txt files into a usable array in order to pass it through each sort. I output all to text files in the first place to make sure the exact same array is run through each sort.
I'm somewhat familiar with Scanner, but have also read about FileRead and/or BufferedReader and possibly some other approaches. I'm just not experienced enough to know what would work best in this situation and the best way to implement it. Help would be much appreciated.
If you just need to save arrays to file storage and construct them back you can use serialization.
This class is just to give you an idea of how it would work.
public class ArrayReaderWriter {
public static void main(String[] args) throws Exception {
writeArray(20);
readArray(20);
}
public static void writeArray(int arrayLength) throws IOException {
File file = new File("arrays_" + arrayLength + "A.ser");
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file));
int[] array = new int[arrayLength];
for (int i = 0; i < array.length; i++) {
array[i] = i + 1;
}
os.writeObject(array);
}
public static void readArray(int arrayLength) throws IOException, ClassNotFoundException {
File file = new File("arrays_" + arrayLength + "A.ser");
ObjectInputStream is = new ObjectInputStream(new FileInputStream(file));
int[] array = (int[]) is.readObject();
// Printing here to verify
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
Note: I can understand saving the random array if you want to run the different sorts with the same array in different executions. But the ascending and descending arrays can always be constructed on every execution.
Regarding System.nanoTime()
See https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#nanoTime-- for a detailed explanation.
EDIT
If you have already generated the text files use #Antoniossss solution. You will only need to modify the delimiter as I mentioned in my comment since you are reading existing files.
Test
Scanner scanner = new Scanner("[1, 2, 3]");
scanner.useDelimiter("(\\s)*[\\[,\\]](\\s)*");
while(scanner.hasNextInt()) {
System.out.println(scanner.nextInt());
}
Output
1
2
3
Use some delimetered file format for such purposes and read it using scanner.
Lets say our delimeter is character is ;. Store your array like this
File file = new File("arrays_" + arrayLength + "A.txt");
PrintWriter printWriter = new PrintWriter(new BufferedWriter(new FileWriter(file)));
printWriter.print(1);
for(int i = 1; i < array.length; i++) {
printWriter.print(';'); // delimeter
printWriter.print(i+1);
}
printWriter.close();
To read it back, use Scanner in simillar way to the following code;
ArrayList<Integer> arr=new ArrayList<>();
Scanner scan=new Scanener(new File("yourfile));
scan.useDelimeter(';');
while(scan.hasNextInt()){
arr.add(scan.nextInt());
}
Should work just fine. You can always use a newline as a delimeter as well.
EDIT: If you dont need to have array storred in human readable form, you can use serialization just like #Shire Resident explained in his answer.
I have a text file like this;
7-Georgia
1-Andrew
6-John
8-Luke
9-Erica
3-Kim
2-Jude
5-Phil
4-Leo
The first column is id and second is name. How can I get these id's and names? So far I wrote this;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
public class Main {
#SuppressWarnings("resource")
public static void main(String[] args) throws FileNotFoundException {
// TODO Auto-generated method stub
#SuppressWarnings("unused")
Scanner fromFile = new Scanner(new File("id_name.txt"));
fromFile.useDelimiter("-");
while(fromFile.hasNext()){
String temp = fromFile.next();
System.out.println(temp);
}
while(fromFile.hasNext()){
String temp= fromFile.next();
int[] fileID;
fileID= new int[9];
for(int i=0; i<9; i++){
fileID[i]= Integer.parseInt(temp);
}
System.out.println(fileID);
}
}
}
But this doesn't get the id's. I'm not sure how to fix this, I'd be grateful if you help me.
You have two while loops in your code. Typically one while loop will go through every item until the condition is no longer true. I think you need to rework this to have a better "flow of control" which might mean using only one while loop (with sections to grab the number and then the name.
I imagine that you are looking for results from the second while loop, but by the time you get to it, the first while loop will have exhausted all of your data.
Finally, printing an array will print out the array reference identifier. If you want to actually print the contents of the array, you need a loop over the elements within the array, and you need to print out each array element explicitly.
As an alternative to the array printing technique above (which you should master), you can also use the Arrays.toString(<insert array here>) method call. However, in many cases it will give you a format that is not desired. That's why you need to know the above technique too.
Also, you have one hidden issue. You (in the second while loop) make the assumption that there are only nine inputs. Pay close attention to what you are writing. Every time you have to reach for a number, consider whether it is a "magic" number. Magic numbers are numbers that are in your code with no explanation or reason why they exist. They are indicators of errors in the code made by assumptions that probably won't last the test of time.
For example, you are using the number 9 because you have seen the input file. The next input file will probably not have nine entries in it, and your program will probably not work right if you gave it an input with eight entries, or an input with ten entries. Perhaps you should rewrite the loop to remove the magic number, by making the logic process while there is still (some) input.
Try this on for size
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
try {
Scanner fromFile = new Scanner(new File("id_name.txt"));
} catch (FileNotFoundException e) {
System.err.println("File not found");
}
String[] arr = new String[9];
String[] oth = new String[9];
int i = 0;
while(fromFile.hasNextLine()) {
String temp = fromFile.nextLine();
oth[i] = temp.substring(0,1);
arr[i] = temp.substring(2);
i++;
}
int[] fileID;
fileID = new int[9];
for(int j = 0; j < 9; j++) {
fileID[j] = Integer.parseInt(oth[j]);
}
}
}
this should go through and retrieve the numbers(.substring(0,1)) and then the names(.substring(2)), and then converting the numbers to int values.
Try the following:
File file=new File("id_name.txt");
int[] fileID;
fileID= new int[9];
String[] result = file.nextLine().split("-");
for (int x = 0; x < result.length; x++){
if (Character.isDigit(result[x])) { // use the isDigit method to get the ids
System.out.println("this is an id");
fileID[i]= Integer.parseInt(result[x]);
}
Actually my friend, there are several mistakes here.
1) When the first while loop completes, it leaves fromfile.hasNext() as false Hence the second loop never starts.
>> To fix this, You need to put it all in one while loop.
2) fileID is an array. You cannot print it using System.out.println(fileID).
>> You have to tell what kind of output you want. The code will depend on that. For simply printing all the values, you need to make a for loop that prints each value separartely. You should use fileID.length for the no. of times you need to loop it.
3) Basically, fromfile.next() is not the way to do it.
>> You need to use fromfile.nextLine().
I need to solve such task:
Randomly generate the length of the array - save this int into file ("input.txt)" as a first digit;
Randomly generate array elements - save each element into the file ("input.txt")
But the array elements won't save into file.
As I can see from console array has got digits, but they don't save into file.
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
new Main().run();
}
Random rand;
Scanner sc;
PrintWriter pr, pr2;
public void run() throws FileNotFoundException {
pr2 = new PrintWriter(new File("input.txt"));
pr = new PrintWriter(new File("output.txt"));
rand = new Random();
int a = rand.nextInt((int) Math.pow(10, 3));
System.out.println(a);
pr2.print(a);
pr2.close();
sc = new Scanner(new File("input.txt"));
int[] arr = new int[a];
for (int i = 0; i < arr.length; i++) {
arr[i] = rand.nextInt((int) Math.pow(10, 3));
}
for (int i = 0; i < arr.length; i++) {
System.out.println("" + i + ": " + arr[i]);
pr2.print(arr[i]);
}
pr2.close();
return;
}
}
You're closing the stream with pr2.close(); and then trying to print something through it. Then you close it again. Remove the first pr2.close(); And it should all work.
Also you're having unnecessary Scanner object and second PrintWriter.
Your problem is that you're calling pr2.close() right after you write the length of the array. Once you close the PrintWriter, it will no longer allow anything to be written to the file; thus, when you later try to write the values in the array to pr2, pr2 says, "gosh, I know this guy wants me to write something but I'm closed, I just can't do it!" and so nothing gets written.
The PrintWriter works by storing all of your write(...) and print(...) calls into memory, and then actually writing them into your text file when you call the close() or flush() method. Although it's not necessary, if you wanted functional similarity to your current use of the first close() call, you could use flush() instead, but make sure that you do call close() when you are completely done using the Scanner (otherwise you're just asking for a memory leak).
I'm having a problem with my hangman program. I really think what I need to do is beyond what I understand about java. Here's my code
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.Random;
public class HangmanProject
{
public static void main(String[] args) throws FileNotFoundException
{
String scoreKeeper; // to keep track of score
int guessesLeft; // to keep track of guesses remaining
String[] wordList = new String[25];
final Random generator = new Random();
Scanner keyboard = new Scanner(System.in); // to read user's input
System.out.println("Welcome to Nick Carfagno's Hangman Project!");
// Create a scanner to read the secret words file
Scanner wordScan = null;
try
{
wordScan = new Scanner(new BufferedReader(new FileReader("words.txt")));
while (wordScan.hasNext())
{
}
}
finally
{
if (wordScan != null)
{
wordScan.close();
}
}
// get random word from array
class pickRand
{
public String get(String[] wordList)
{
int rnd = generator.nextInt(wordList.length);
return wordList[rnd];
}
}
System.out.println(wordList);
}
}
I was able to get the program to read a file and then print to screen, but I can't figure out how to store the words from file into an array. I not advanced at all, so please try and be as thorough as possible.
1) What you've got so far looks pretty good :)
2) Since you don't know exactly how many or few words you'll have, you don't want an "array". You're probably better off with an "ArrayList". Arrays are "fixed". Lists are "variable".
3) For each "word" you read, just ".add()" it to your arraylist
Voila! Done.
Here's a complete example:
http://www.daniweb.com/software-development/java/threads/311569/readingwriting-arraylist-fromto-file#
You need to save the read line in a String object and assign it to a certain field of the array. For example:
wordList[0] = myString;
This would assign the value of myString to the first field of your array.
I am writing a CSVParser program that seperates words at commas. I am currently trying to find and record the longest word that appears in the file. Here is my class.
import csv.CSVParser;
import java.io.*;
import java.util.*;
public class RecordFormatter {
public static void main (String[] args) {
CSVParser parser = new CSVParser(new File (args[0]));
while (parser.hasNextLine()) {
ArrayList<String> ls = parser.getNextLine();
for (int i = 0; i<ls.size(); i++) {
System.out.print("|" + ls.get(i) + " ");
}
System.out.print("|");
System.out.println();
}
CSVParser parser1 = new CSVParser(new File (args[0]));
ArrayList<Integer> maxCol = new ArrayList<Integer>();
while (parser1.hasNextLine()) {
ArrayList<String> ls1 = parser1.getNextLine();
for (int i = 0; i<ls1.size(); i++) {
maxCol.add(ls1.get(i)); //Here is where my bug occurs.
}
}
}
}
I have created two CSVParsers and am trying to use the second of the two to record the length. I tried (as you can see above) storing the int length value of each word into another Arraylist, but I can't seem to get it to work. Any help would be much appreciated.
Without giving the solution, since this is homework...
Notice that you are keeping every length value rather than comparing the current length against a previous value to determine if it is longer and only then keeping it.
Seems like you need just a single maxLength Integer (or int) rather than a list since you just want the longest single word.
If you wanted the longest word per line, a List might then be appropriate.
Another option would be to use a SortedList and get the largest value (last value) in the list.