A Good Method to read files in Java - java

I Really would appreciate it if someone can help me with this. I am trying to do external sorting and I am stuck on the part of merging. I get how I should merge it just not sure what function to use.
Right now I am trying to read in the first words of multiple small text files and store them in a string array of the size of the amount of files. So basically I will have a string array of the first word of each file. Then I determine which one is the smallest alphabetically wise and write that to a new file, after that I would read the next word of the file of that smallest word. This word would be placed in the position of the smallest word that got outputted in string array and compare it to the rest of the first word from the other file. This will keep repeating till all words are sorted.
The main problem I am running into is the fact that I was using scanner and after the first run of comparing it cant switch the smallest word with the next word in the file because scanner don't keep a point of what it has read. I know readline do but since my files are all words separated by only a white space I can't use readline. Can someone please guide me to a sufficient reading function that can't help me solve this problem.
for (int i = 0; i<B;i++)
{
try
{
BufferedReader ins = new BufferedReader(new FileReader(Run-"+ i + ".txt"));
Scanner scanner2 = new Scanner(ins);
temp3[i] = scanner2.next();
System.out.println(temp3[i]);
}
catch(IOException e)
{
}
}
for(int i=0;i<N;i++)
{
String smallest = temp3[0];
int smallestfile = 0;
for(j=0;j<B;j++)
{
int comparisonResult = smallest.compareTo(temp3[j]);
if(comparisonResult>0)
{
smallest = temp3[j];
smallestfile = j;
}
}
BufferedReader ins = new BufferedReader(new FileReader("C:/Run-"+ smallestfile + ".txt"));
Scanner scanner2 = new Scanner(ins);
if(scanner2.hasNext())
{
temp3[smallestfile]=scanner2.next();
}
}
}
catch(Exception e)
{
}

If the files are small enough read the entire file to memory, and use String.split() to separate the strings in arrays and do your magic.
If the the files are bigger, keep then open and read each byte until you find and space, then do it for all the files, compare the strings, do your magic and repeat until all the files reach the end.
EDIT :
how to read the files with BufferedReader
how to split the lines with String.split()
String line = readeOneLineFromTheCurrentFile();
String[] words = line.split(" ");

As for temporarily sorting/storing the words, use a PriorityQueue (not an array). Sorry, I'm too busy watching baseball to add more.

I'm not sure, if I understood you right, but a Scanner does keep the position in a file. You need just as many of them as there are files
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class so {
// returns the index of the smallest word
// returns -1 if there are no more words
private static int smallest(String[] words) {
int min = -1;
for (int i = 0; i < words.length; ++i)
if (words[i] != null) {
if (min == -1 || words[i].compareTo(words[min]) < 0)
min = i;
}
return min;
}
public static void main(String[] args) throws FileNotFoundException {
// open all files
Scanner[] files = new Scanner[args.length];
for (int i = 0; i < args.length; ++i) {
File f = new File(args[i]);
files[i] = new Scanner(f);
}
// initialize first words
String[] first = new String[args.length];
for (int i = 0; i < args.length; ++i)
first[i] = files[i].next();
// compare words and read following words from scanners
int min = smallest(first);
while (min >= 0) {
System.out.println(first[min]);
if (files[min].hasNext()) {
first[min] = files[min].next();
} else {
first[min] = null;
files[min].close();
files[min] = null;
}
min = smallest(first);
}
}
}
Tested with
a.txt: a d g j
b.txt: b e h k m
c.txt: c f i
Update:
In your example, you open and close the file inside the outer for loop. When you reopen a file the next time, it starts at the beginning of the file, of course.
To prevent this, you must keep the file open and move the scanner2 variable and its initialization in front of the outer for loop. You also need multiple Scanner variables, i.e. an array, to keep multiple files open simultaneously.

Related

Reading from a text file into an array - getting "nulls"

I'm reading from a file and copying that into an array. My file has five lines of text, a sentence each. I get my output "Array size is 5" but nothing after that. If I do add a print line of the array, it gives me 5 nulls...
Can someone help explain what I did wrong? Thanks!
public static int buildArray() throws Exception
{
System.out.println("BuildArray is starting ");
java.io.File textFile; // declares a variable of type File
textFile = new java.io.File ("textFile.txt"); //reserves the memory
Scanner input = null;
try
{
input = new Scanner(textFile);
}
catch (Exception ex)
{
System.out.println("Exception in method");
System.exit(0);
}
int arraySize = 0;
while(input.hasNextLine())
{
arraySize = arraySize + 1;
if (input.nextLine() == null)
break;
}
System.out.println("Array size is " + arraySize);
// Move the lines into the array
String[] linesInRAM = new String[arraySize];// reserve the memory
int count = 0;
if (input.hasNextLine())
{
while(count < arraySize)
{
System.out.println("test");
linesInRAM[count] = input.nextLine();
System.out.println(linesInRAM[count]);
count = count + 1;
}
}
In this code
int count = 0;
if (input.hasNextLine())
The above hasNextLine will always be false as you have already read all the way through the file.
Either reset the scanner to the beginning of the file, or use a dynamic list e.g. ArrayList to add the elements to.
My Java is a bit rusty, but the basic gist of my answer is that you should create a new Scanner object so that it reads from the beginning of the file again. This is the easiest way to "reset" to the beginning.
Your code is currently not working because when you call input.nextLine() you're actually incrementing the scanner, and thus at the end of that first while() loop input is sitting at the end of the file, so when you call input.nextLine() again it returns null.
Scanner newScanner = new Scanner(textFile);
Then in the bottom of your code, your loop should look like this instead:
if (newScanner.hasNextLine())
{
while(count < arraySize)
{
System.out.println("test");
linesInRAM[count] = newScanner.nextLine();
System.out.println(linesInRAM[count]);
count = count + 1;
}
}

Reading file into 2D array with unknown dimensions - Java

The task at hand is to read in a file with unspecified dimensions... The only stipulation I have with completing this task is that I'm only allowed to use Arrays - no arraylists, lists, maps, trees, or anything else of the sort... just arrays.
Yes, I sneaked at a sample txt file and it showed values such as :
0 2 3.0
1 0 2.0
2 1 7.0
2 3 1.0
3 0 6.0
But this isn't to say all possible files tested with my code in the future will be the same dimensions.
I have tried normal .hasNext() operations to count how many elements there were in the file, but I haven't been able to find a way to count the number of rows and columns collectively.
I'm a beginner and am not sure how to do this. I have seen examples with bufferedreader but can't comprehend the use of it and the functions within that class to use it without being oblivious to what it's actually doing.
Code:
public void loadDistances(String fname) throws Exception {
String file = fname;
File f = new File(file);
Scanner in = null;
try {
in = new Scanner(f);
}
catch (FileNotFoundException ex) {
System.out.println("Can't find file " + file);
System.exit(1);
}
int rows = 0;
int cols = 0;
while(in.hasNextLine()) {
rows++;
while(in.hasNextDouble()){
cols++;
// statement here which will close once reads a "end of line" character?
// or something of the sorts
}
}
}
try to find oud the dimensions before you are defining an array...
the number of lines could be counted with something like the following snipped:
public int countDimensions(String mytxtFile) throws IOException {
InputStream contentOfFile = new BufferedInputStream(new FileInputStream(mytxtFile));
try {
byte[] a = new byte[1024];
int counter = 0;
int readMyChars = 0;
boolean emptyfile = true;
while ((readMyChars = contentOfFile.read(a)) != -1) {
emptyfile = false;
for (int i = 0; i < readMyChars; ++i) {
if (a[i] == '\n') { ++counter;}}
}
return (counter == 0 && !emptyfile) ? 1 : counter;
} finally {contentOfFile.close();}
}
-now you have got a first dimension for your array...
the number of elements in a row could be defined by counting a "seperator" in a line, like spaces, or a special letter...
I do not know how you want to put the data into the array, or what you want to do with the data...but this could work if i understood you correctly...
BUT NOTE: this whole solution is not very aesthetic & efficient and not recommended.

Read text file for integers and storing to array using scanner and exceptions

I'm trying to loop through a text file for integers and store integers found into an array.
Using a try-catch to determine which words are integers and which are not using InputMismatchException, removing the non-int strings from the input stream. As well as a NoSuchElementException for blank lines in the file.
My main issue is storing the integers and printing those integers in the array, in my second method :o . It also appears my loop is also recording non-ints as null as well. They aren't suppose be stored into the array.
public static void main(String[] commandlineArgument) {
Integer[] array = ReadFile6.readFileReturnIntegers(commandlineArgument[0]);
ReadFile6.printArrayAndIntegerCount(array, commandlineArgument[0]);
}
public static Integer[] readFileReturnIntegers(String filename) {
Integer[] array = new Integer[1000];
// connect to the file
File file = new File(filename);
Scanner inputFile = null;
try {
inputFile = new Scanner(file);
}
// If file not found-error message
catch (FileNotFoundException Exception) {
System.out.println("File not found!");
}
// if connected, read file
if (inputFile != null) {
// loop through file for integers and store in array
while (inputFile.hasNextLine()) {
for(int i = 0; i<array.length; i++)
{
try{
array[i] = inputFile.nextInt();
}
catch(InputMismatchException excep1)
{
String word = inputFile.next();
}
catch(NoSuchElementException excep2){
}
}
}
}
return array;
}
public static void printArrayAndIntegerCount(Integer[] array, String filename) {
//prints number of integers from file
//prints each integer in array
}
}
The approach taken in the first method is a bit flawed, since you're incrementing the i variable whether or not an integer is read.
So for example, if the file looked like this:
4
Hello
5
e
7
The beginning of your array would look like
[4, null, 5, null, 7...]
So you will end up with an array of size 1000, which has nulls at unpredictable places in there.
A slightly better approach would be this:
Keep a separate count variable that says how many integers you actually read.
Add items to the array at index count and not at i (since i just says how many lines you've looked at, whereas count will tell you how many integers you've come across).
When you're finished reading them, either
pass the count variable to the method that prints the array (so it knows only to look at the first count items), or
just copy the entire array into a new array of size count.
Example incorporating this into your code:
if(inputFile != null) {
// the number of integers we've read so far
int count = 0;
// loop through file for integers and store in array
while(inputFile.hasNextLine()) {
for(int i = 0; i < array.length; i++) {
try {
array[count] = inputFile.nextInt();
count++;
} catch(InputMismatchException excep1) {
String word = inputFile.next();
} catch(NoSuchElementException excep2) {
}
}
}
}
Then to copy into a correctly sized array,
Integer[] newArray = new Integer[count];
for(int i = 0; i < count; i++) {
newArray[i] = array[i];
}
and just return newArray instead of array.
Your print method will then simply have the same signature and functionality you'd expect:
public static void printArrayAndIntegerCount(Integer[] array, String filename) {
for(int i = 0; i < array.length; i++) {
// print the number at array[i], and whatever else you want to print
}
}
This is probably the better approach, as you can still keep all the method signatures the same, and don't need to mess around with returning multiple variables or changing global state.
Or alternatively, if you don't want to copy the relevant bits into a new array, then you could just pass the count variable somehow to your second method, and do something like
for(int i = 0; i < count; i++) {
System.out.println("\tindex = " + i + ", element = " + array[i]);
}
Key difference there is you're iterating up to count, and not up to array.length.
You would need to find a way to return that from your first method along with the array (or maybe set a static variable somewhere), and you would then need to change the signature of your second method to be
public static void printArrayAndIntegerCount(Integer[] array, int count, String filename) {
...
}
Assuming all you logic for reading integers from file are correct and also hoping this is kind of home work. Though the following implementation is not the right approach, it just solves your purpose. All we are doing here is iterating all the elements in the array until it reaches the null and keep writing them into a buffer.
public static void printArrayAndIntegerCount(Integer[] array, String filename) {
StringBuilder sb = new StringBuilder();
int count = 0;
for(Integer i : array) {
if(i != null) {
count++;
sb.append("index = ").append(i).append(", element = ").append(array[i]).append("\n");
} else {
break;
}
}
System.out.println("number of integers in file \""+filename+"\" = "+count);
System.out.println(sb);
}
Replace your catch statement with:
catch(InputMismatchException excep1)
{
String word = inputFile.next();
i-=1;
}
You were incrementing the array counter if it found a word. I have run my own test and this worked for me to fix your issue.
public static void printArrayAndIntegerCount(Integer[] array, String filename) {
String message = "";
int i = 0;
while(i < array.length && array[i]!=null){
message = message + "index = "+i+", element = "+array[i]+"\n";
i+=1;
}
System.out.println("number of integers in file \""+filename+"\" = "+i);
System.out.println(message);
}

how to let the size of array to grow and shrink automatically?

int filename = 100;
String[] fileName = new String[filename];
int a = 0;
int totalCount = 0;
int wordCount = 0;
// Count the number of documents containing the query
System.out.println("Please enter the query :");
Scanner scan2 = new Scanner(System.in);
String word2 = scan2.nextLine();
String[] array2 = word2.split(" ");
int[] numofDoc = new int[array2.length];
for (int b = 0; b < array2.length; b++) {
numofDoc[b] = 0;
for (int i = 0; i < filename; i++) {
try {
BufferedReader bf = new BufferedReader(new FileReader(
"C:\\Users\\user\\fypworkspace\\FYP\\abc"
+ i + ".txt"));
int matchedWord = 0;
Scanner s2 = new Scanner(bf);
{
while (s2.hasNext()) {
if (s2.next().equals(array2[b]))
matchedWord++;
}
}
if (matchedWord > 0)
numofDoc[b]++;
} catch (IOException e) {
System.out.println();
}
}
_resultArea.append(array2[b]
+ " --> This number of files that contain this term "
+ numofDoc[b]+ newline);
}
hi, this is my code for calculating number of files that contain a specific input keyed in by the user. This code analyze a folder of text files and search the text files whether it has the input or not.
The problem i facing now is, i now declaring the array size of 100. It means that it will process 100 text files whether the folder have 100 files or not. How do i let the program to process exact number of text files inside a folder ?
Note : The number of text files is dynamic. It doesnt has a constant number of text files inside the folder.
Take a look at java.io.File.list(), and use a List.
For example:
File[] files = dir.list();
List<File> list = new LinkedList<File>();
for (File f : files) {
if (/* f matches our criteria */) {
list.add(f);
}
}
If you need an array after that, do this:
File[] array = list.toArray(new File[list.size()]);
Java arrays are of static size. You should use a List (whose most frequently used implementation is ArrayList) instead, which can grow and shrink dynamically and safely. Not to mention that (since Java 5) it is generic, i.e. typesafe.
Either keep track of the number of text files you read, or use a List, which has a size property.
I am no expert, but I am pretty sure you could use arraylist
Have you tried using a List like
List<String> fileName = new ArrayList<String>();
or you could just maintain the count of files you have
for (int i = 0; i < filenameCount; i++) {

How to read a GRID of data from a text file in Java?

When I say a grid, I mean a multidimensional array. I want this because I am making a 2D game and I want to be able to load levels from data text files. Lets say, for example, I have this 2D array level[3][3]. A simple 3x3 map. And I also have a text file that reads:
1 2 3
4 5 6
7 8 9
In c++, I can simply do:
for (x=0; i<map_width; x++)
{
for (y=0; y<map_height; y++)
{
fscanf(nameoffile, "%d", map[x][y]);
}
}
And that would put all the contents of the text file accordingly into the array.
HOWEVER
I have no idea how to do this in java. Is there any sort of equivalent that will just place the data into the array accordingly? I already know about the scanner class, but I don't know how to use it. I have searched google, to no avail. It doesn't explain much.
Please help! Specifically, I want to know how to scan the file and put whatever int it reads IN THE APPROPRIATE PLACE in the array.
My current code is this, however, it throws a NoSuchElementException:
public void loadMap() {
Scanner sc = null;
try {
sc = new Scanner(inputmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
map[x][y] = sc.nextInt();
}
}
Where inputmap is the file, map[][] is a grid of data for each of the tiles on the map and width and height are pre-specified in a constructor.
Your question is very unhelpful when it comes to how your text files will be actually formatted. For example,
123
456
789
is very different from
1 2 3
4 5 6
7 8 9
and furthermore, you haven't mentioned whether they are always ints, or
1 2 3
4 5 6
a b c
etc. If you gave us a precise description of exactly what goes in these text files we could help you more. The best I can do is show you how to use Scanner to input stuff in general:
The for loop would look similar in Java, but you have to initialize a Scanner object.
Scanner input = new Scanner(myFile); //whatever file is being read
for (x=0; i<map_width; x++)
{
for (y=0; y<map_height; y++)
{
int nextTile = input.nextInt(); //reads the next int
// or
char nextTile = input.nextChar(); //reads the next char
}
}
Beyond that, I would need to know more about what is actually inside these input files.
EDIT:
I copied your for loop directly from your code, but you may want to swap the inner and outer for loops. Shouldn't the width be the inner parameter (reading left to right)?
In Java, it works similar - create a java.util.Scanner object for your file and use it's nextInt method instead of fscanf.
If you don't know the dimensions of the grid
static int[][] readFile(String filename) {
try {
File textfile = new File (GridSearchTest.class.classLoader.getResource(filename).toURI());
Scanner fileScanner = new Scanner(textfile);
int size = Integer.parseInt(fileScanner.next());
String line = fileScanner.nextLine();
int[][] grid = new int [size][size];
int i = 0; int j = 0;
while (fileScanner.hasNextLine()) {
line = fileScanner.nextLine();
System.out.println (line);
Scanner lineScanner = new Scanner(line);
while (lineScanner.hasNext()) {
grid[i][j] = Integer.parseInt(lineScanner.next());
i++;
}
lineScanner.close();
i=0;
j++;
}
fileScanner.close();
return grid;
} catch (IOException e) {
System.out.println("Error reading file: "+ e.getMessage());
System.exit(0);
};
}

Categories