this method is suppose to ask the user for the file name that is already created that contains list of numbers, if file does not exist i have to let the user know. im having trouble figuring out how to assign the numbers in the file to a new array?
public static int[] inputData() throws IOException
{
int count = 0;
System.out.print("enter input filename: ");
File myFile = new File("input.txt");
if(!myFile.exists())
{
System.out.print("file does not exist ");
System.exit(0);
}
Scanner inputFile = new Scanner(myFile);
while(inputFile.hasNext() && count < ARRAY_SIZE)
{
array[count++] = input.nextInt();
}
return array[];
}
You need to learn how to declare and allocate a new array, which you'll pass back. It looks like it'll be an array of int, and you'll make it a certain size (is ARRAY_SIZE defined somewhere already?) when you call new. See the official tutorial on arrays.
(As a note, it's usually a bad idea to use an external upper limit in a for loop over an array. The array comes with a built-in length you can use that will always be the correct size.)
Where are you defining the variable array?
your problem is going to be that you don't know how big you need the array to be. The best option is to use an ArrayList as this allows dynamic sizing. (As a result it needs to be a list of Integers rather than ints)
public static Integer[] inputData() throws IOException
{
List<Integer> fileData = new ArrayList<Integer>();
int count = 0;
System.out.print("enter input filename: ");
File myFile = new File("input.txt");
if(!myFile.exists())
{
System.out.print("file does not exist ");
System.exit(0);
}
Scanner inputFile = new Scanner(myFile);
while(inputFile.hasNext())
{
fileData.add(inputFile.nextInt());
}
return fileData.toArray(new Integer[fileData.size()]);
}
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.
Below are two functions in my class, I want to first read the number of lines from a text file, then store the contents in an array. The problem I am having is that if I do not comment out int aNumber = numOfObjects(newInput); the array does not get stored and printed, it's as if numOfObjects function got to the end of the text file, and I can no longer access it. If I comment it out it works fine. I tried adding a second Scanner object but it didn't help. What can I do to make it work?
public void correctListItems(FileInputStream inputFile,FileOutputStream outputFile){
newInput = new Scanner(inputFile);
forCapturing = new Scanner(inputFile);
int aNumber = numOfObjects(newInput);
System.out.println(aNumber);
for(int i=0; forCapturing.hasNextLine(); i++){
publicationArray[i] = new Publication();
publicationArray[i].publication_code = forCapturing.nextLong();
publicationArray[i].publication_name = forCapturing.next();
publicationArray[i].publication_year = forCapturing.nextInt();
publicationArray[i].publication_authorname = forCapturing.next();
publicationArray[i].publication_cost = forCapturing.nextDouble();
publicationArray[i].publication_nbpages = forCapturing.nextInt();
System.out.println(publicationArray[i]);
System.out.println("-----------------------------------\n");
}
}
private int numOfObjects(Scanner aScanner){
int count = 0;
while (aScanner.hasNextLine()){
count++;
aScanner.nextLine(); //if this isn't included you'll experience an infinite loop
}
System.out.println(count);
return count;
}
}
There is a way to do this as you want. i.e. by reading through the file 2 times. First to count and then to capture.
Just add below lines after your line int aNumber = numOfObjects(newInput); in correctListItems function.
public void correctListItems(FileInputStream inputFile,FileOutputStream outputFile){
newInput = new Scanner(inputFile);
int aNumber = numOfObjects(newInput);
newInput.close();
inputFile.close();
inputFile = new FileInputStream(
new File(
"inputfile.txt"));
System.out.println(aNumber);
forCapturing = new Scanner(inputFile);
for(int i=0; forCapturing.hasNextLine(); i++){
....
....
So basically closing the scanner as well as file is important. And then creating the fileinputreader stream again will reset the file pointer to the beginning of the file. As you might already know, If the input file is not from the project folder, you have to give the complete path.
As a good process, its always better to close both the scanner object and file object after you're done, And then reinitialize the objects to start working on them again.
Hope this helps.
It looks like the scanner class uses an iterator internally. This means that it needs to be closed at some point, which I cant find in your code. Therefore I would (1) add following line to the numOfObects function before the return: “aScanner.close()”.
(2) I would create the second Scanner instance after you called the function, just to be sure. Hope it works.
Cheers!
The scanner doesn't move to the next line unless you call nextLine. So the loop is infinite since you're always on the first line.
But why do you need to know the number of objects in advance? Why not simply use a list instead of publicationArray?
Well, I am not exactly sure but I can be quite certain that the FileInputStream object once the bytes has been read by Scanner once, the scanner will have a token to indicate that a particular line has been read.
How about you change your code to:
public void correctListItems(FileInputStream inputFile,FileOutputStream outputFile){
forCapturing = new Scanner(inputFile);
for(int i=0; forCapturing.hasNextLine(); i++){
publicationArray[i] = new Publication();
publicationArray[i].publication_code = forCapturing.nextLong();
publicationArray[i].publication_name = forCapturing.next();
publicationArray[i].publication_year = forCapturing.nextInt();
publicationArray[i].publication_authorname = forCapturing.next();
publicationArray[i].publication_cost = forCapturing.nextDouble();
publicationArray[i].publication_nbpages = forCapturing.nextInt();
System.out.println(publicationArray[i]);
System.out.println("-----------------------------------\n");
}
System.out.println("Number of lines: "+ i);
}
At least with this, you would not have to run 2 loops to the same set of data. better performance too and get the thing you need done in 1 round of a loop
I'm trying to create a 2D array from a .txt file, where the .txt file looks something like this:
xxxx
xxxx
xxxx
xxxx
or something like this:
xxx
xxx
xxx
So I need to handle multiple sizes of a 2D array (Note: Each 2D array will not always be equal x and y dimensions). Is there anyway to initialize the array, or get the number of characters/letters/numbers per line and number of columns? I do not want to use a general statement, something like:
String[][] myArray = new Array[100][100];
And then would filling the array using filewriter and scanner classes look like this?
File f = new File(filename);
Scanner input = new Scanner(f);
for(int i = 0; i < myArray[0][].length; i++){
for(int j = 0; j < myArray[][0].length, j++){
myArray[i][j] = input.nextLine();
}
}
You have several choices as I see it:
Iterate through the file twice, the first time getting the array parameters, or
Iterate through it once, but fill up a List<List<SomeType>> possibly instantiating your Lists as ArrayLists. The latter will give you much greater flexibility in the short and long run.
(per MadProgrammer) The third option is to re-structure the file to provide the meta data required to make decisions about the size of the array.
For example, using your code,
File f = new File(filename);
Scanner input = new Scanner(f);
List<List<String>> nestedLists = new ArrayList<>();
while (input.hasNextLine()) {
String line = input.nextLine();
List<String> innerList = new ArrayList<>();
Scanner innerScanner = new Scanner(line);
while (innerScanner.hasNext()) {
innerList.add(innerScanner.next());
}
nestedLists.add(innerList);
innerScanner.close();
}
input.close();
Java Matrix can have each line (which is an array) by your size desicion.
You can use: ArrayUtils.add(char[] array, char element) //static method
But before that, you need to check what it the file lines length
Either this, you can also use ArrayList> as a collection which is holding your data
I need to make a program which reads a file in a method. The file is a "data.txt" type and will have a list of numbers (double data type) with one number on each line.
Ex:
23.4
12.3
111.4533
I need to then put this in an array (NOT a 2D array)and return it to the main method.
I used filename.length() but it makes the array size larger than it should be and I'm getting an array out of bounds error.
I can initialize the array in a while loop, but it keeps saying I need to declare the size of the array first and I don't know how to do this. So I tried just using a while loop to get the number of lines and then using another loop to input the elements but it won't let me return the array to the main method without initializing the array. Here's what I have so far:
java.io.File file = new java.io.File(file);
int arraySize = (int)file.length();
int size = 0;
int i = 0;
try{
Scanner input = new Scanner(file);
while(input.hasNextLine()){
size++;
}
double [] array;
array1 = new double [size];
while(input.hasNext()){
array[i] = input.nextDouble();
i++;
}
Any suggestions? I'm really stuck on this. Thanks.
Two possible solutions:
a) Use a collection which grows on demand instead of using a fixed array (e.g., ArrayList). You can also convert it afterwards into an array again.
b) Close the scanner and open the file again after you counted the number of lines.
The problem right now is that you are not redefining the Scanner, so after you determine the size, the Scanner is at the end of the file and so there are no more doubles to be read in.
Also, when determining the size, you need to actually read in the line each loop so you skip to new lines, or else I think you will have an infinite loop. If you never read in a line, it always has more.
Try this (tested and works):
java.io.File file = new java.io.File(file);
int size = 0;
int i = 0;
try {
Scanner input = new Scanner(file);
while(input.hasNextLine()){
input.nextLine(); // have to change the lines
size++;
}
double [] array;
array = new double [size];
// reopen the file so you start from the beginning again
input = new Scanner(file);
while(input.hasNext()){
array[i] = input.nextDouble();
i++;
}
// print out the array
for (double d : array) {
System.out.println(d);
}
} catch (Exception e) {
e.printStackTrace();
}
Or you could just use an ArrayList which has no defined size (you can .add elements to it and so you don't need to know the size beforehand to populate it). And then just convert the ArrayList to a regular array afterword if you wanted to.
Try this:
java.io.File file = new java.io.File("C:\\Users\\Mike\\Desktop\\data.txt");
try {
Scanner input = new Scanner(file);
ArrayList<Double> list = new ArrayList<Double>(); // define empty ArrayList
while(input.hasNextLine()) {
list.add(input.nextDouble()); // have to change the lines
}
// convert ArrayList to array
// (although you don't need to do this if you're fine with an ArrayList)
double[] array = new double[list.size()];
for (int i = 0; i < list.size(); i++) {
array[i] = list.get(i);
}
// print out the array
for (double d : array) {
System.out.println(d);
}
} catch (Exception e) {
e.printStackTrace();
}
Assuming your filename variable is a String of the file's name then filename.length is only giving you the total characters in the name. If you have called your File object filename then filename.length() returns a long of the file's length in bytes and not the number of rows inside it.
To get the number of lines in a file you can refer to this question for many possible answers: Number of lines in a file in Java
But more likely you want to use an expandable Collection instead of a fixed length array as you do not then need to calculate and read the whole file before you begin using it. Something like an ArrayList could be ideal. But it does depend on your use case.
You can always convert the ArrayList back to an Array afterwards:
String[] lines = lineList.toArray(new String[lineList.size()]);
I would recommend using an ArrayList. That way you don't have to be aware of the size while creating the array. As other's have said, you can convert to a array after you are done adding values to the ArrayList.
Assuming your data.txt file has your doubles line by line with no spaces. you could use the following code:
ArrayList <Double> doubleArray = new ArrayList<Double>();
Scanner fileScan = null;
try {
fileScan = new Scanner(new File("/path/to/file"));
while (fileScan.hasNextDouble()){
doubleArray.add(fileScan.nextDouble());
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
use below code
read line by line of text file and parse each line element to double
add double parsed value to arraylist
convert arraylist to array.
String fileName=null;
File file = null;
try {
fileName="path/filename.txt";
file = new File(fileName);
} catch (Exception e) {
System.out.println(e.getMessage());
// TODO: handle exception
}
List<Double> elements = new ArrayList<>();
try{
Scanner input = new Scanner(file);
while(input.hasNextLine()){
elements.add(Double.parseDouble(input.nextLine()));
}
double[] ret = new double[elements.size()];
for(int index = 0;index < ret.length;index++)
ret[index] = elements.get(index);
System.out.println(ret);
System.out.println("end");
}
catch(Exception e){
}
I have a .txt file that lists integers in groups like so:
20,15,10,1,2
7,8,9,22,23
11,12,13,9,14
and I want to read in one of those groups randomly and store the integers of that group into an array. How would I go about doing this? Every group has one line of five integers seperated by commas. The only way I could think of doing this is by incrementing a variable in a while loop that would give me the number of lines and then somehow read from one of those lines that is chosen randomly, but I'm not sure how it would read from only one of those lines randomly. Here's the code that I could come up with to sort of explain what I'm thinking:
int line = 0;
Scanner filescan = new Scanner (new File("Coords.txt"));
while (filescan.hasNextLine())
{
line++;
}
Random r = new Random(line);
Now what do I do to make it scan line r and place all of the integers read on line r into a 1-d array?
There is an old answer in StackOverflow about choosing a line randomly. By using the choose() method you can randomly get any line. I take no credit of the answer. If you like my answer upvote the original answer.
String[] numberLine = choose(new File("Coords.txt")).split(",");
int[] numbers = new int[5];
for(int i = 0; i < 5; i++)
numbers[i] = Integer.parseInt(numberLine[i]);
I'm assuming you know how to parse the line and get the integers out (Integer.parseInt, perhaps with a regular expression). If you're sing a scanner, you can specify that in your constructor.
Keep the contents of each line, and use that:
int line = 0;
Scanner filescan = new Scanner (new File("Coords.txt"));
List<String> content = new ArrayList<String>(); // new
while (filescan.hasNextLine())
{
content.add(filescan.next()); // new
line++;
}
Random r = new Random(line);
String numbers = content.get(r.nextInt(content.size()); // new
// Get numbers out of "numbers"
Read lines one by one from the file, store them in a list and generate a random number from the list's size and use it to get the random line.
public static void main(String[] args) throws Exception {
List<String> aList = new ArrayList<String>();
Scanner filescan = new Scanner(new File("Coords.txt"));
while (filescan.hasNextLine()) {
String nxtLn = filescan.nextLine();
//there can be empty lines in your file, ignore them
if (!nxtLn.isEmpty()) {
//add lines to the list
aList.add(nxtLn);
}
}
System.out.println();
Random r = new Random();
int randomIndex=r.nextInt(aList.size());
//get the random line
String line=aList.get(randomIndex);
//make 1 d array
//...
}