my question is related to my previous question (How to display data from txt file in specific format).
I was wondering if it is possible at the first place, to store data on txt file in specific format rather than store it first and then retreived it again and display it in specific format?
e.g. instead of store data on txt file like this
Jessica
Walking
20 minutes
Matthew
Run
10 minutes
I wanted to store it in txt file in this format
Jessica Walking 20 minutes
Matthew Run 10 minutes
Regarding your comment to adeel's answer:
Thanks adeel825, however I dont know where to put the "\t".. so far I use this method: new PrintStream(fout).println (name); new PrintStream(fout).println (exercise); new PrintStream(fout).println("10 minutes");
First, don't call "new PrintStream(fout)" everytime you print something. Do this:
PrintStream ps = new PrintStream(fout);
ps.print(name);
ps.print('\t');
ps.print(exercise);
ps.print('\t');
ps.print(time);
ps.println();
Or simply:
PrintStream ps = new PrintStream(fout);
ps.println(name + '\t' + exercise + '\t' + time);
Edit
In response to your comment:
one more question...some of the name are too long and it requires more tab..I have put ps.print('\t','\t'); but it seems not working..
If this is a problem, it sounds like you are trying to store them in the manner you want to display them. I had assumed you were trying to store them in a way that would be easy to parse programmatically. If you want to store them displayed in columns, I'd suggest padding with spaces rather than tabs.
If you know that all the columns are going to be less than, say, 30 characters wide, you could do something like this with printf:
ps.printf("%30s%30s%30s%n", name, exercise, time);
That syntax can look quite byzantine if you're not used to it.. basiclly each "%30s" means pad the string argument so that it is at least 30 characters wide. Your result won't look right if any of the values are 30 or more characters wide. If you can't know ahead of time, you'll have to loop through the values in each column to determine how wide the columns need to be.
There is no problem with storing data this way. All you need to do is write out the values and delimit them with a tab character "\t"
You need to "handcode" your formatting. Best way to do this would be to wrap your file-accessing code somewhere, and create something like:
OpenFile()
CreateEntry(name, type, time)
If you want to write records of fixed length you can use the String.[format][1] method
ps.println(String.format("%20s%20s%20s",name,exercise,time))
This will create a table with 20 characters in each field. You can readup on the syntax here
[1]: http://java.sun.com/javase/6/docs/api/java/lang/String.html#format(java.lang.String, java.lang.Object...)
Related
My programm needs to read a file that has different data structures with a variable separator.
In my properties-file you can set the separator and put coordinates for values of different variables:
separator = ;
variable1 = 1,7
variable2 = 2,42
I would like to have a way where I can access a column and a line with some kind of coordinates.
I'm thinking of a syntax like this:
file.get(1,7,";")
(Which would give you the value of the 1st line and 7th column with the specific separator)
Does someone know a library or a code snippet that does exactly this?
Using String.split() :
public String get(File file, int lineNumber, int column, String separator ) {
//getting to the lineNumber of the file ommitted
// suppose you got it in a String named "line"
return line.split(separator)[column - 1];
}
You can use OpenCSV or SuperCSV for example. I'm not aware of any library that does your 'coordinates' gettings, but it's as simple as reading the CSV with the given separator as List-of-Lists and then call
csv.get(1).get(7)
Seems to be a simple file processing, You should first process the file -
create ArrayList<ArrayList<String>> processedFile
Read every line, split using "line".split(separator)
Store the array above in the ArrayList processedFile at current index
increase the index with every line
Once processedFile is ready, you can simply use processedFile.get(row).get(column). Also once the file is processed, all the other queries will be O(1). Hints are enough, try writing the code yourself, you will learn more.
PS: Take care of NullPointerExceptions wherever required.
Suppose I've a couple of objects' values stored on a text file. In the beginning, there will be some values which will have the same value, for instance, all students by default will have 0 age. Now if I want to make an edit in the age of one student using the conventional file handling approach, I'll end up making changes to all other students who have 0 age, while writing my data onto the temporary file. Thus, I was hoping that if there is a better way to make changes to a file using file handling in java. Just to give an example of the issue at hand consider the following text file
Edsger
Dijkstra
123
72 years
Ruth
Dijkstra
12345
29 years
The line indicates a space between the age and the name. Now, my task is to construct a program where a user can change any detail, such as the First Name, surname, roll_number or the age. As you can see from the example given above, two people can share some data that is common. In this case, it is the surname. However, the roll number (123,12345) will always be unique. The problem comes when you have to change similar data. Suppose the user wants to edit the surname. Then by I would create a temporary file which would hold this data and later I would read this data with some conditions to it. So the code might look like this:
Note: This data is stored at a known location "abc.txt".
BufferedReader br=new BufferedReader(new FileReader("abc.txt"));
BufferedWriter bw=new BufferedWriter(new FileWriter("Temp.txt"));
String a=br.readLine();
while(a!=null)
{ bw.write(a);
bw.newLine();
a=br.readLine();
}
br.close();
bw.close();
BufferedReader br1=new BufferedReader(new FileReader("Temp.txt"));
BufferedWriter bw1=new BufferedWriter(new FileWriter("temp.txt"));
String b=br1.readLine();
while(b!=null)
{
if(b.equals(requested_surname))
bw1.write(w);//w is the String that holds the altered surname as desired by the User, for the sake of an example say it is Euler
else
bw1.write(b);
bw1.newLine();
b=br1.readLine();
}
bw1.close();
br1.close();
f.delete();
As a result the Original text file "abc.txt" will show something like this:-
Edsger
Euler
123
72 years
Ruth
Euler
12345
29 years
Now this will be a bungling problem as I intend to change only Ruth's surname! I know that this is slightly different from what I initially asked, but I think that if I could target the line below "Ruth", I can make the desired changes.
Please Help...
There are several approaches to do this.
You could store the data in a csv file, 1 line for each object:
123,Edsger,Dijkstra,72
12345,Ruth,Dijkstra,29
4567,Ruth,Euler,27
Then, on program start-up read all the objects in memory (in a structure) for easy access. On program exit or save, write everything back to the file (assuming the number of objects isn't really big - i.e. not millions).
Another way is to store every field of the object as a fixed width value:
123 Edsger Dijkstra 72
12345 Ruth Dijkstra 29
4567 Ruth Euler 27
That way changes to the data can easily be written 'in place' in the file. You only have to make sure the fields don't exceed the maximum size. The number fields could even be in binary format if needed.
With fixed width, or an exact size for each object, it is easy (and faster) to look up a certain object or roll number: since the size of the objects is known, file seek can be used to jump directly to the beginning of each object - no parsing is needed.
Note: the objects don't need to be on a separate line in this case (I've done it for clarity) - but if they are, newlines (could be \r or \r\n or \n) will have to be added to the size of the objects.
Of course, searches for a certain person/object should always be done on a unique ID, in this case roll number, never on the name.
File can be thought as a character array.
char[] file = ... // file (on disk)
char[] newData = ... // data to be written
int pos = ... // the position in the file to write to
for (i=0; i<newData.; i++) {
file[pos+i] = newData[i];
}
You can particularly make use of seek().
Check this out as well:
http://docs.oracle.com/javase/tutorial/essential/io/rafs.html
Assume I have a StringBuffer with values "1 \n 2 \n 3 \n...etc" where \n is a line break.
How would I add these values to an existing CSV file as a column using Java? Specifically, this would be the last column.
For example, let's say I have a CSV file that looks like this:
5, 2, 5
2, 3, 1
3, 5, 2
..
etc.
The output should look like this given the StringBuffer after using the method to add the column to the csv file:
5, 2, 5, 1
2, 3, 1, 2
3, 5, 2, 3
..
etc.
I also plan to add columns with 1000s of values so I am looking for something that does not have high memory consumption.
Thanks ahead of time.
Edit: Columns may be different sizes. I see people saying to add it at the end of each line. The problem is, it will add the values to the wrong columns and I cannot have that happen. I thank you all for your suggestions though as they were very good.
Edit 2: I have received critique about my use of StringBuffer and yes, I agree, if this problem were isolated, I would also suggest StringBuilder. The context of this problem is a program that has synchronized threads (acting as scenarios) collecting response times given a range of concurrent threads. The concurrent threads execute concurrent queries to a database and once the query has been executed, the result is appended to a StringBuffer. All the response times for each synchronized thread is appended to a StringBuffer and written to a CSV document. There can be several threads with the same response time. I can use StringBuilder but then I would have to manually synchronize the threads appending the response times and in my case, I do not think it would make too much of a difference in performance and would add an unnecessary amount of code. I hope this helps and I once again, thank you all for your concerns and suggestions. If after reading this, you are still not convinced that I should use StringBuffer, then I ask that we please take this discussion offline.
Edit 3: I have figured out how to go around the issue of adding the columns if the rows are different sizes. I simply add commas for every missing column (also note, that my rows would be growing with each column). It looks like #BorisTheSpider's conceptual solution actually works with this modification. The problem is I am not sure how to add the text at the end of each line. My code so far (I removed code to conserve space):
//Before this code there is a statement to create a test.csv file (this file has no values before this loop occurs).
for (int p = 0; p<(max+1); p = p + inc){
threadThis2(p);
//threadThis2 appends to the StringBuffer with several comma delimited values.
//p represents the number of threads/queries to execute at the same time.
comma = p/inc; //how many commas to put if there is nothing on the line.
for (int i = 0; i < comma; i++) {
commas.append(",");
}
br = new BufferedReader (new FileReader("test.csv"));
List <String> avg = Arrays.asList(sb.toString().split(", "));
for (int i = 0; i < avg.size(); i++) {
if (br.readLine()==null)
{w.write(commas.toString() + avg.get(i).toString() + ", \n");}
else { w.write(avg.get(i).toString() + ", \n");}
}
br.close();
sb.setLength(0);
commas.setLength(0);
}
Please note this code is in its early stages (I will of course declare all the variables outside the for loop later on). So far this code works. The problem is that the columns are not side by side, which is what I want. I understand I may be required to create temporary files but I need to approach this problem very carefully as I might need to have a lot of columns in the future.
Apparently there are two basic requirements:
Append a column to an existing CSV file
Allow concurrent operation
To achieve Requirement #1, the original file has to be read and rewritten as a new file, including the new column, irrespective of its location (i.e., in a StringBuffer or elsewhere).
The best (and only generic) way of reading a CSV file would be via a mature and field-proven library, such as OpenCSV, which is lightweight and commercially-friendly, given its Apache 2.0 license. Otherwise, one has to either do many simplifications (e.g., always assume single-line CSV records), or re-invent the wheel by implementing a new CSV parser.
In either case, a simple algorithm is needed, e.g.:
Initialize a CSV reader or parser object from the library used (or from whatever custom solution is used), supplying the existing CSV file and the necessary parameters (e.g., field separator).
Read the input file record-by-record, via the reader or parser, as a String[] or List<String> structure.
Manipulate the structure returned for every record to add or delete any extra fields (columns), in memory.
Add blank fields (i.e., just extra separators, 1 per field), if desired or needed.
Use a CSV writer from the library (or manually implement a writer) to write the new record to the output file.
Append a newline character at the end of each record written to the output file.
Repeat for all the records in the original CSV file.
This approach is also scalable, as it does not require any significant in-memory processing.
For Requirement #2, there are many ways of supporting concurrency and in this scenario it is more efficient to do it in a tailored manner (i.e., "manually" in the application), as opposed to relying on a thread-safe data structure like StringBuffer.
I read a text file containing list of words with their tags and put them as an ArrayList in an a wrapping ArrayList (ArrayList).
[[1, that, that, that, DT, DT], [2, table, table, table, NN, NN]]
Now I want to write the in a text file in a same format as follows:
1 that that that DT DT
2 table table table NN NN
each of the above rows is an ArrayList with 6 columns.
the following code return a file with Ԁ inside.
public void setPPOSOfWordInDevelopmentList(ArrayList<ArrayList> trainingList){
try{
FileOutputStream streamFile = new FileOutputStream("developmentFile.txt");
ObjectOutputStream streamFileWriter = new ObjectOutputStream(streamFile);
for(ArrayList word: developmentWordsList){
String inputWord = (String)word.get(1);
extractTag(inputWord,trainingList);
String extractedPPOSofWord =(String)findMaxTag().get(1);
word.set(5, extractedPPOSofWord);
}
streamFileWriter.close();
System.out.println(developmentWordsList);
}
catch(Exception e){
System.out.println("Something went wrong, check the code");
}
}
this code is coupled with some others so it is not easy to change the format of objects returned by the functions.
If you want to write a simple text file, would be better if you use a BufferedWriter. For your content, you can format it in a StringBuffer or a StringBuilder if it is too long. Here in this post, I replied to a question related with the kind of formatting you're trying to make. But you should need to adapt it according to your format and the logic of using a wrapping array.
Export array values to csv file java
I think, the loop or "enhanced for" statement should be used as something like:
for (ArrayList<String> innerArray: wrapperArray) {
for (String word : innerArray) {
//Adapt to your required format using a StringBuilder
}
}
//Here at the end save the content of your StringBuilder or StringBuffer using the BufferedWriter.
Hope you can get an idea on how to achieve this. Best regards :)
What you want sounds eerily like a standard CSV file. This stackoverflow thread will set you straight on how to parse that sort of content. I would strongly recommend that you refactor along the lines of a CSV file instead of using the ObjectInput/OutputStreams. It'll be easier to maintain and you'll be able to use tools like Excel and OpenOffice Calc to view your files when debugging.
If you are certain to use custom format file you can use formatted printing and add padding accordingly. It's pretty easy:
for (ArrayList<String> list : trainingList) {
writeToStream(
String.format(
%s, %-5s, %-5s, %-5s,
list.getAt(0),list.getAt(1),list.getAt(2),list.getAt(3)
);
}
}
This should work if your strings aren't longer than five characters. Just keep in mind that blank characters are bad demiliters and you will face indentation problems if you use other than monospaced fonts.
This question already has an answer here:
Closed 12 years ago.
Possible Duplicate:
do searching in a very big ARPA file in a very short time in java
my file's format:
\data\
ngram 1=19
ngram 2=234
ngram 3=1013
\1-grams:
-1.7132 puluh -3.8008
-1.9782 satu -3.8368
\2-grams:
-1.5403 dalam dua -1.0560
-3.1626 dalam ini 0.0000
\3-grams:
-1.8726 itu dan tiga
-1.9654 itu dan untuk
\end\
As you can see I have a number of lines in ngram 1,2 and 3. There is no need to read the whole file. If an input string is a one-word string, the program can just search in \1-grams: part. If an input string is a two-word string, the program can just search in \2-grams: part and so on. At last if the program finds the input string in the file, it has to return two numbers which are located at the left and right sides of the string. Also, I have to say that each part of the file has been sorted. I am sure that I do not have to read the file completely, and using the index file can not solve my problem. These ways take a lot of time, and my lecturer said that searching has to be done in less than 1 minute for such a big file. I think the best thing is to find a way to jump to a specific line not byte of the file, but I do not know how I can do it. It will be great if someone can help me to solve my problem.
My file is almost 800MB. I have found that using BufferedReader is a good way to read a file very fast, but when I read such a big file and put it in an array line by line, it takes more than 30 minutes.
How big is your file? A minute is a very long time. I would suggest using a BufferedReader for efficiency (and also for its readLine method).
If that really takes too long, two approaches come to mind that don't use indexes:
Force every line in the file to be the same length. Then you can jump to a specific line by calculating its start. If you don't know the line number you need, then at least you can use this to efficiently do a binary search of the entire file.
Jump to an arbitrary position and read forward until you get to a line that starts with a \. That will tell you whether you've found the right part or whether you need to jump forward from there or backward from the arbitrary position that you jumped to. This can also be used to create a binary search strategy for the data you need. It relies on the \ being a reliable indicator of the start of a part.