I'm reading through a file like this:
JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
int result = fileChooser.showOpenDialog(this);
if (result == JFileChooser.CANCEL_OPTION) {
System.exit(1);
}
file = fileChooser.getSelectedFile();
java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.FileReader(file));
String line = reader.readLine();
while (line != null) {
//do stuff for each line
}
reader.close();
The file looks like this:
0 LOAD 1,3
1 LOAD 0,2
2 ADD 1,2
3 ADD 0,1
4 LSS 1,3,2
5 STOR 62,1
I've parsed it like this:
String[] actionFirstSplit = line.split(" ");
There's code associated with each line that isn't shown here. For certain lines, I'd like to jump back to a certain line number, and continue reading through the file once again. What is the best way to do this? Do I have to create another reader and skip lines until the particular line I'm interested in? I'm looking along the lines of this post, but I want to continue reading the rest of the file.
If this were my project, I'd
Create a class, perhaps called MyClass (for discussion purposes only), to hold one line's worth of data. It would have line number, String for text (command?), and a List<Integer> to hold a variable number of int parameters.
Create a List<MyClass> to hold a linear collection of objects of this class.
In my single BufferedReader, read each line, create a MyClass object, and place it in the collection.
When I needed to loop back, I simply search through my collection -- no need to re-read from a file since this is a relatively expensive task while looping through a List such as an ArrayList isn't quite so.
Related
I have a software that stores its data in multible nested data objects. On saving this project data, every instance gets an out handle (BufferedWriter) and writes its own data. Most data is single line and no problem, but there are a few multiline strings that come from JTextAreas. For storing them, I wrote a sub method multiLineWriter(), that splits the string in single lines, writes the number of lines and then the single lines. In theory. Because its not always working. Often it writes out the line count as 1 but then writes out two lines. Or it writes out 1, but writes out two lines with text and an empty line. Its not reliable. After loading the project back, often the complete data is destroyed. A typcal object saving block looks like this:
// *** write data to file
public void writeDataFile(BufferedWriter out) {
try {
out.write(""+getHeadline() );
out.newLine();
out.write(""+getStartDateAsString() );
out.newLine();
out.write(""+getEndDateAsString() );
out.newLine();
out.write(""+getPlaceIndex() );
out.newLine();
multiLineWriter(out, getDescription() );
} catch(Exception e) {}
}
// *** read data from File
public void readDataFile(BufferedReader in) {
try {
setHeadline(in.readLine());
setStartDateAsString(in.readLine());
setEndDateAsString(in.readLine());
setPlaceIndex(in.readLine());
setDescription(multiLineReader(in));
} catch(Exception e) {}
}
The multline writer/reader looks like this:
public void multiLineWriter(BufferedWriter out, String areaText) {
try {
String ls = System.getProperty("line.separator");
String[] lines = areaText.split(ls);
int lineCount = lines.length;
out.write(""+lineCount);
out.newLine();
for(int i = 0;i<lineCount;i++) {
out.write(lines[i]);
out.newLine();
}
} catch(Exception e) {}
}
public String multiLineReader(BufferedReader in) {
String targetString = "";
try {
String ls = System.getProperty("line.separator");
int lineCount = Integer.parseInt(in.readLine());
for(int i = 0;i<lineCount;i++) {
targetString = targetString + in.readLine() + ls;
}
} catch(Exception e) {}
return targetString;
}
As said, lineCount often is 1, but the loop seems to go two or more times because I have sometimes two or three lines after the 1 in a datafile.
This is not reliable for the project. Do you have an idea how I can change the multiLineWriter/reader to reliably store and read the data? The JTextArea save method does not work in this combined data file format.
__More info: __
Properties are a good style for the whole datafile. Since I was allright with the old style seen above most of the times I am sticking to that. Changing the current project to properties is a lot of handwork.
I reuse the out. I have Project Object, that creates the out. This out is then passed to multiple objects with subobjects, sometimes in loops, and everyone writes it data to this single out. After all data is written the project Object of course flushes and closes the stream. The empty exceptions are no problem in this case, because there are no exceptions (so there is nothing to analyse in a stack trace). Its not an exception problem but a logical problem.
The JTextArea read/write is not a good option. At time of saving the file, the data is not in a JTextArea but in a string, that was saved sometime ago during runtime from a JTextArea. To use the write method of JtextArea I would need to restore the string to the area and then use the write method. Because of hundreds of those description objects I would need to do this hundred of times in a save process. Sounds not well. On the other hand I am sure that the read method would not work, because it would read in the datafile up to the end and wouldn't handle the nested datastructure in the datafile.
Its not bad to be human readable. Currently this is helping me, to manually correct the values after a save process, so I am not loosing any data (I now this is stupid, but it works:-)
To be short: I guess I have a problem with the split method of strings and the content of the strings in the string array.
Problem should be made clearer. I have this JTextArea. It is like one field in a display for datasets (its a little private genealogy program that mainly manages hundreds of persons and places). A lot of dataobjects have a description field. Contents of the JTextArea are stored to one single String variable when you change the person in display for example (String personDescription). The writeDataFile() Method you see above is for an event object, that has a description field, too.
So when I write a File, I write from one String to the file. Since this string is taken from the JTextArea, it contains all new line characters that you can produce in a JTextArea. When storing this with one out.write (data) call you have multiple lines in the resulting data file because of possible new line characters in the String. So you can't read all this content back with one in.readLine() call. That's why I created the multiline writers and readers. But they don't work as expected.
Here I show you an exerpt from the resulting datafile
...
# +++ FileCollection:
0
# +++ ImageCollection:
0
58
true
Surname
Arthur
25.09.1877
1
01.01.1950
6
https://familysearch.org/
1
Bekannt ist, dass er auf dem Friedhof Großbeerenstr. lag.
Bekannt ist auch, dass die Trauzeugen bei der Heirat Dorothea Surname und Hermann Surname waren. Hermann ist vermutlich ein Bruder von Valerie.
Weitere Informationen gibt es nicht bisher.
# +++ EventCollection:
0
# +++ FileCollection:
0
...
There is more data before and below, but here is the wrong written data. Its directly below the link to familysearch.org. The first line that follows should have the line count. If there is no text it would have a 0 and the next line would be the info sting '# + EventCollection:'. If there would be one line, it would have a 1 and the next line would be that single line of text for description. Or other numbers depending on the amount of lines from the JTextArea. But as you see, there is written a 1 in this case, but there are 3 (!) Lines of text following.
So the main problem seems to be the way I work with the split method in the multiLineWriter().
String ls = System.getProperty("line.separator");
String[] lines = areaText.split(ls);
int lineCount = lines.length;
This seems to be critical. Since I write the resulting array of the split in a loop, this loop must be done three times? Because I have 3 lines of text in the datafile. But the lineCount is written as a 1? So this seems to be wrong. Could be that this string was not splitted, but still contains line break characters. That would not be what I am looking for. And in the array of splittet Strings there should not be any line break characters anymore (that would destroy the file writing, too).
Hope the problem is better described now. And the question is, how should the multiline writer and reader method be designed to store and read this data reliable.
I tried it myself. As I said there was a problem using the split method on strings. I changed this now to use a Scanner. To be correct, I use some ideas from How do I use System.getProperty("line.separator").toString()?
So in the end I just changed the multiLineWrite Method to use the Scanner (from the util package). It looks like this:
public void multiLineWriter(BufferedWriter out, String areaText) {
List<String> slines = new ArrayList<String>();
try {
Scanner sc = new Scanner(areaText);
while (sc.hasNextLine()) {
slines.add(sc.nextLine());
}
int slineCount = slines.size();
out.write(""+slineCount);
out.newLine();
for(int i = 0;i<slineCount;i++) {
out.write(slines.get(i));
out.newLine();
}
} catch(Exception e) {}
}
So now this seems to be reliable for me. I did a test with parallel writing of the split method and the Scanner method, and the split method had the wrong line count and the Scanner was correct.
For example, in my code, I have something like this:
for (int i = 0; i < arraylist.size(); i++) {
while (file.hasNext())
When the for loop goes to i = 1, will it start reading the file at the beginning again, or will the file not be read at all since it was read through at i = 0?
For i > 0, file.hasNext() will always return false since you have already read through the file at i = 0 (leaving the file pointer at the end of the file). So, nothing will happen for i > 0.
To read through the file on each iteration of the for loop, you must seek back to the start of the file after the while loop.
I am not sure what the type of file is in your question, but take a look at java.io.RandomAccessFile and its seek(long pos) method for how to accomplish this (seek(0) rewinds to the start of the file).
It will read from beginning. Does not matter whatever i is. Because you are not telling scanner to not read until some value of i is reached.
Infact, I honestly don't see this loop's significance since you are using while loop after this as well. It will just print same file's all lines once.
For example, if your file has these contents:
con1
con2
con3
and lets say your array size is 4. Then by your loop, this will be the output:
con1
con2
con3
If you want to say, start printing from second line, then use some integer for iteration reference and start printing once its 2. Something like:
int x = 0;
while(scanner.hasNext())
if(x >= 2)
System.out.println(scanner.next());
x++;
}
I don't really get what you want to do, do you want to add each word in the file to an arraylist? And then, didn't you use Scanner to read?
Scanner scanner = new Scanner(new File("path.ext"));
ArrayList<String> strings = new ArrayList<String>();
while(scanner.hasNext()) {
strings.add(scanner.next());
}
scanner.close();
was that your problem?
In this case you read each word in the file from start to end
Your code example is incomplete. If file is an instance of Scanner, hasNext only indicates that there is another token to read, but it does not advance the position in the input stream. Assuming you make a call to next in your block, then THAT call will advance, but it won't start again from the beginning unless you reinitialize your file variable to point to a new Scanner instance.
I need to make a dictionary that takes words from a .txt file. These words (separated line by line) need to be stored in a String array. I have already gotten to the point of separating the words and adding them to a new .txt file, but I have no idea how to add them each to a String array. There are
You need to count the lines in the file. Create an array of that size.
Then for each line in the file, read it and insert it into the array at the index[lineReadFrom].
Since you are not allowed to use ArrayList or LinkedList objects, I would suggest to save every found word "on the fly" while you are reading the input file. These is a series of steps you could follow to get this done:
1. Read the file, line by line: Use the common new BufferedReader(new FileInputStream("/path/to/file")) approach and read line by line (as I assume you are already doing, looking at your code).
2. Check every line for words: Break every possilbe word by spaces with a String.split() and remove punctuation characters.
3. Save every word: Loop through the String array returned by the String.split() and for every element that you considered a word, update your statistics and write it to your dictionary file with the common new BufferedWriter(new FileWriter("")).write(...);
4. Close your resources: Close the reader an writer after you finished looping through them, preferably in a finally block.
Here is a complete code sample:
public static void main(String[] args) throws IOException {
File dictionaryFile = new File("dict.txt");
// Count the number of lines in the file
LineNumberReader lnr = new LineNumberReader(new FileReader(dictionaryFile));
lnr.skip(Long.MAX_VALUE);
// Instantiate a String[] with the size = number of lines
String[] dict = new String[lnr.getLineNumber() + 1];
lnr.close();
Scanner scanner = new Scanner(dictionaryFile);
int wordNumber = 0;
while (scanner.hasNextLine()) {
String word = scanner.nextLine();
if (word.length() >= 2 && !(Character.isUpperCase(word.charAt(0)))) {
dict[wordNumber] = word;
wordNumber++;
}
}
scanner.close();
}
It took about 350 ms to finish executing on a 118,620 line file, so it should work for your purposes. Note that I instantiated the array in the beginning instead of creating a new String[] on each line (and replacing the old one like you did in your code).
I used wordNumber to keep track of the current array index so that each word would be added to the array at the right location.
I also used .nextLine() instead of .next() since you said that the dictionary was separated by line instead of by spaces (which is what .next() uses).
I am trying to display statistics from a simple text file using arrays in Java. I know what I am supposed to do, but I don't really how how to code it. So can anybody show me a sample code on how to do it.
So let's say the text file is called gameranking.txt, that contains the following information (This is a simple txt file to use as an example):
Game Event, 1st place, second place, third place, fourth place
World of Warcraft, John, Michael, Bill, Chris
Call of Duty, Michael, Chris, John, Bill
League of Legends, John, Chris, Bill, Michael.
My goal is to display stats such as how many first places, second places.. each individual won in a table like the following
Placement First place, second, third, fourth
John 2 0 1 0
Chris 0 2 0 1
etc...
My thought:
First, I would read the gameranking.txt and stores it to "input". Then I can use the while loop to read each line and store each line into a string called "line", afterward, I would use the array method "split" to pull out each string and store them into individual array. Afterward, I would count which placement each individual won and display them into a neat table using printf.
My first problem is I don't know how to create the arrays for this data. Do I first need to read through the file and see how many strings are in each row and column, then create the array table accordingly? Or can I store each string in an array as I read them?
The pseudocode that I have right now is the following.
Count how many rows are there and store it in row
Count how many column are there and store it in column
Create an array
String [] [] gameranking = new String [row] [column]
Next read the text file and store the info into the arrays
using:
while (input.hasNextLine) {
String line = input.nextLine();
while (line.hasNext()) {
Use line.split to pull out each string
first string = event and store it into the array
second string = first place
third string =......
Somewhere in the code, I need to count the placement....
Can somebody please show me how I should go about doing this?
I am not going to write the full program, but I will try to tackle each question and give you a simple suggestion:
Reading the initial file, you can get each line and store it in a string using a BufferedReader (or if you like, use a LineNumberReader)
BufferedReader br = new BufferedReader(new FileReader(file));
String strLine;
while ((strLine = br.readLine()) != null) {
......Do stuff....
}
At that point, in the while loop you will go through the string (since it comma delimited, you can use that to seperate each section). for each substring you can
a) compare it with first, second, third, fourth to get placement.
b) if its not any of those, then it could either be a game name or a user name
You can figure that out by position or nth substring (ie if this is the 5th substring, its likely to be the first game name. since you have 4 players, the next game name will be the 10th substring, etc.). Do note, I ignored "Game event" as that's not part of the pattern. You can use split to do this or a number of other options, rather than try to explain that I will give you a link to a tutorial I found:
http://pages.cs.wisc.edu/~hasti/cs302/examples/Parsing/parseString.html
As for tabulating results, Basically you can get an int array for each player which keeps track of their 1st, 2nd, 3rd, awards etc.
int[] Bob = new int[4]; //where 0 denotes # of 1st awards, etc.
int[] Jane = new int[4]; //where 0 denotes # of 1st awards, etc.
Showing the table is a matter of organizing the data and using a JTable in a GUI:
http://docs.oracle.com/javase/tutorial/uiswing/components/table.html
Alrighty...Here is what I wrote up, I am sure there is a cleaner and faster way, but this should give you an idea:
String[] Contestants = {"Bob","Bill","Chris","John","Michael"};
int[][] contPlace=new int[Contestants.length][4];
String file = "test.txt";
public FileParsing() throws Exception {
Arrays.fill(contPlace[0], 0);
Arrays.fill(contPlace[1], 0);
Arrays.fill(contPlace[2], 0);
Arrays.fill(contPlace[3], 0);
BufferedReader br = new BufferedReader(new FileReader(file));
String strLine;
while((strLine=br.readLine())!=null){
String[] line = strLine.split(",");
System.out.println(line[0]+"/"+line[1]+"/"+line[2]+"/"+line[3]+"/"+line[4]);
if(line[0].equals("Game Event")){
//line[1]==1st place;
//line[2]==2nd place;
//line[3]==3rd place;
}else{//we know we are on a game line, so we can just pick the names
for(int i=0;i<line.length;i++){
for(int j=0;j<Contestants.length;j++){
if(line[i].trim().equals(Contestants[j])){
System.out.println("j="+j+"i="+i+Contestants[j]);
contPlace[j][i-1]++; //i-1 because 1st substring is the game name
}
}
}
}
}
//Now how to get contestants out of the 2d array
System.out.println("Placement First Second Third Fourth");
System.out.println(Contestants[0]+" "+contPlace[0][0]+" "+contPlace[0][1]+" "+contPlace[0][2]+" "+contPlace[0][3]);
System.out.println(Contestants[1]+" "+contPlace[1][0]+" "+contPlace[1][1]+" "+contPlace[1][2]+" "+contPlace[1][3]);
System.out.println(Contestants[2]+" "+contPlace[2][0]+" "+contPlace[2][1]+" "+contPlace[2][2]+" "+contPlace[2][3]);
System.out.println(Contestants[3]+" "+contPlace[3][0]+" "+contPlace[3][1]+" "+contPlace[3][2]+" "+contPlace[3][3]);
System.out.println(Contestants[4]+" "+contPlace[4][0]+" "+contPlace[4][1]+" "+contPlace[4][2]+" "+contPlace[4][3]);
}
If you need to populate the contestants array or keep track of the games, you will have to insert appropriate code. Also note, using this 2-d array method is probably not best if you want to do anything other than display them. You should be able to take my code, add a main, and see it run.
Since it's a text file, use Scanner class.
It can be customized so that you can read the contents line-by-line, word-by-word, or customized delimiter.
The readfromfile method reads a plain text file one line at a time.
public static void readfromfile(String fileName) {
try {
Scanner scanner = new Scanner(new File(fileName));
scanner.useDelimiter(",");
System.out.println(scanner.next()); //instead of printing, take each word and store them in string array
scanner.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
This will get you started.
I have college project where i have to read the first word of every line from text file which looks as follow:
23123123213 Samuel classA
23423423423 Gina classC
23423423423 John classD
The text file will be updated with through 3 JTextField which i am able to figure out.
but now i have to populate the JCombobox with first word(23123123213,23423423423 and 23423423423) of all the lines.
I am new to java, i dont even have hint of how about doing it.
I know how to read and write to text files.
Please could someone help me do this?
The code so far i came up with is as follows:
import java.io.*;
public class FileRead
{
public static void main(String args[])
{
try{
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream("RokFile.txt");
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
String[] delims = strLine.split(" ");
String first = delims[0];
System.out.println("First word: "+first);
}
//Close the input stream
in.close();
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
}
With u guys help I was successfully able to extract the first string from each line
but now how could i populate it in Jcombobox, I mean should i save it somewhere first?
Thanks in Advance
I'm not "down" with Java, however I can give you a few pointers:
You can read files, and presumably can read a line.
Each line is (presumably) separated with spaces so what you need to look up is a String.split function
Once you've split a string you will be able to use array index 0 to get the information you need.
Then it's just a case of adding split_string[0] to the JComboBox.
The documents are a great help:
String
JComboBox
You can get the first word using String.split(), or by using indexOf and substring.
There is a tutorial about JComboBox.
The Java Swing classes are based on Model/View, so you have to fill the strings into the Model of the JCombobox.
EDIT: In response to your edit, suppose you have retrieved the values. Then you can indeed save them to a specific data structure. It would be preferable to make the code that retrieves those values into a separate method. The values returned from that method (in, for example, a List<String>) can then be put into the JComboBox.
If you know how to read lines from a text file you can split each line by a delimiter, using the String.split function. In that case you get an array, with which you can get the first string by a normal array indexer, the [] operator that is.
String hello = "Hello world";
String[] delims = hello.split(" ");
String first = delims[0];
To answer your edit, you populate the JComboBox using one of its constructors, for instance the one that takes an Object array, or using the JComboBox.addItem(Object) function.
The latter has an example. Regarding the one with the constructor you can either build an array of objects yourself, or use an arraylist to which you add all your elements and then get an array using the ArrayList.toArray() function.