I'm trying to dump a large integer array (10 000 elements) into a text file but am encountering some problems. I've tried two different approaches and neither seems to be working. Below is the function I've written:
private static void writeToFile(String name, int[] a){
try {
FileWriter fw = new FileWriter(name);
BufferedWriter bw = new BufferedWriter(fw);
bw.write("working");
for (int n: a){
bw.write(n + " ");
}
bw.close();
} catch (IOException e) {
System.err.print("Unable to write to file " + name+ ".");
e.printStackTrace();
}
}
The first thing I tried was creating a string in the for loop and then writing the whole string to the file. Neither method works and gives me the same results as follows:
File is created but left blank
Works fine for shorter arrays (~10 elements)
Works fine if the space is a letter eg: bw.write(n + "a")
Any idea what I'm doing wrong? Or is there an even easier way that I'm not seeing?
Thanks,
Civatrix
Can you explain how you're viewing/reading in the file afterwards? Your code is basically fine as far as I can see (bar moving the close() to a finally block), and it really should make no difference whatsoever whether a space or other letter is added. But that might make a difference e.g. to a text editor, I suppose...?
That code will write all the elements of a[] to the file followed by a space, unless it gets an exception. However it won't write any lines. Is that your problem? If so, you need bw.newLine() after each write().
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.
I have been trying to get my try/catch set up to work but it doesn't seem to run either the try section or the catch section and just returns the default value of the variable.
I had it working before and cant remember what it was that i changed because I haven't touched it for a while
i can include the data file if requested
Any ideas?
package firsttry;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.InputMismatchException;
import java.util.Scanner;
public class csv{
public double speed(int tool , int block){
double blockbreak = 0;
//Define file variable thing
//runs through file
try {
String filename = "data.csv";
File file = new File(filename);
Scanner inputStream = new Scanner(file);
//runs through each line as long as there is something next
while (inputStream.hasNext()){
String data = inputStream.next();//gets a whole line
String[] values = data.split(",");
if (values[1].equals(block)){
blockbreak = Double.parseDouble(values[tool + 2]);
System.out.println(blockbreak);
blockbreak = 4;
}
}
}catch (Exception e) {
System.out.println("ERROR");
blockbreak = 4;
}
return blockbreak;
}
public String name(int block){
String filename = "data.csv";
File file = new File(filename);
//runs through file
try {
Scanner inputStream = new Scanner(file);
//runs through each line as long as there is something next
while (inputStream.hasNext()){
String data = inputStream.next();//gets a whole line
String[] values = data.split(",");
if (values[1].equals(block)){
//int speed = Integer.parseInt(values[tool]);
String blockname = values[0];
return blockname;
}
}
} catch (FileNotFoundException e) {
}
return filename;
}
}
Don't have enough reputation to comment, so writing here.
You should modify your if condition in each function() written above,
if (values[1].equals(block)){
}
It will not give you an output you are expecting.
Comparing string with int is incorrect, for example
System.out.println("1".equals(1)); -> will print false
You are observing that the default value is being returned.
Does this mean that your function returns 0? (As initialized here? double blockbreak = 0;)
If that is the case, you should look into what happens in your loop.
This if statement looks dodgy.
if (values[1].equals(block))
What do you expect to happen?
Also, please post a line that matches the if statement and a line that doesn't, and the expected output from the function.
Possible reasons why you only get the default value:
data.csv is an empty file.
values[1].equals(block) returns false. (Which will always be the case since you're comparing a String to an int.)
catch (FileNotFoundException e) doesn't do anything, so you wouldn't know if the file was not found.
To elaborate on point 2, consider values[1].equals(String.valueOf(block))
Let me suggest some troubleshooting tips.
Write a unit test so you can easily run this repeatedly.
Put a System.out.println into the code in a few places to see which places it hits and when (On small problems this is often easier than debugging if you don't typically debug, I often have it print out a letter at the beginning of any code that comes after a decision point like if, loop and try/catch constructs.)
Print out the value of each line as you read it.
Print the value of blockbreak
I would guess your loop or the if statement aren't executing. Printing some values will tell you this quickly.
Also, if you truly intend Blockbreak to be assigned a value, try NOT assigning a default value of 0 in the beginning. This will stop you from compiling until you have assigned a value in every possible program flow path--a very handy feature (May not help in your case because of the way your while loop is structured, but it's a useful habit not to assign initial values until you need to in Java).
public static String findAndDeleteStudent(String qStudent)
{
String fileName = "data/Students.txt";
String findNumber = qStudent;
File file = new File(fileName);
Scanner dataText = null;
String result="";
try
{
dataText = new Scanner(file);
while (dataText.hasNext())
{
String line = dataText.nextLine();
if (line.contains(findNumber))
{
//System.out.println(line);
//line.trim();
//System.out.println(items[1]);
System.out.println(line);
result ="done";
}
}
}
catch (NumberFormatException nfe)
{
result = "error";
}
catch (NoSuchElementException nsf)
{
result = "error";
}
catch (FileNotFoundException fnf)
{
result = "error";
}
return result;
}
I want to know the shortest way to delete the line string without re-writing the whole text file without the line string (that i want to delete).
I am able to retrieve the line as a string from the file using above code.
but can't delete. please help.
If the file is small enough and you are bulk deleting, then you could always read into into a HashMap and run .remove(qStudent) (assuming the key is based on qStudent). Then, you can write out the HashMap to the file when finished with all deletes. If, however, you're only deleting one here and there, then yes, you'll have to do some form or (re)write. It is possible, though to do random access into a file if (1) each entry is the exact same size, (2) that size is known, and (3) there is a deterministic way to locate each student (unlikely, however). Then you can use a java.io.RandomAccessFile and its seek function to skip to the exact location. For larger files, if they are sorted, then you can use a RandomAccessFile and binary search to speed up locating the record in question. Also for large files, you can use memory mapping. The last two, however, will still require file (re)writing.
As MarsAtomic suggested, (and Hot Licks corrected) you can't remove bytes randomly from a file.
But there are two optimizations possible.
But there is no need to completely rewrite the file.
If your line-to-be-deleted is halfway across the file, you don't need to touch the first half of the file. You would just need to rewrite second half of the file.
You can scan line by line and once you find the line, you can start copying.
But while copying, there is no need to go line by line, you can go for faster ways of copying by transferring large number of lines at once.
Hope this helps.
OK so I have read plenty of examples on here dealing with reading in lines from a text file and splitting them up but im not quite sure I understand how to do it in my situation. I have a file that is basically separated into three columns as follows:
START 5000
FIND A
PLUS B
SAVE C
STOP
A, INT 69
B, INT -420
C, CRAZY 008484342
What I am trying to do is read in this .txt file containing the above information. I figured reading in the file line by line would be best, then splitting it into the correct columns. The problem that I am having is the fact that the 1st column is not always here. It is an optional one. If they were all filled in, im almost positive I could just use use something like
String[] array1 = myLine.split(",");
Another idea I had was to split the line based on ,'s then split the line again based on " " but im not exactly sure how to do this. Maybe somthing like
String[] array1 = myLine.split(",");
String[] array2 = array1[1].split(" ");
Also, is there any way to just read in the file and store each row into like (String, String String) then just check for ints vs strings? Maybe in a try catch? or like:
Scanner input = new Scanner(File);
while(input.hasNext()){
String str = input.next();
try{
b = Integer.parseInt(str);
}
I am not sure if this is as hard as a task as im making it but maybe so... Any help with this topic would be appreciated.
After looking over some more code, I have the following to start:
public static void main(String[] args) {
String file ="TEST.txt";
try{
FileReader input = new FileReader(file);
BufferedReader bufferReader = new BufferedReader(input);
String line;
while ((line = bufferReader.readLine()) != null) {
// Is this where I would attempt to split the lines?
System.out.println(line);
}
bufferReader.close();
}catch(Exception e){
System.out.println("Error while reading file line by line:" + e.getMessage());
}
}
}
So with this, I am successfully reading in the file and displaying the information back to the output console. Now for separating the lines... Ill be posting my work as I go, any help and or suggestions would be appreciated! Also thank you to those who have already commented with helping to split the stings, ill be attempting this now!
You can combine both expressions and only checked the array's length. e.g.:
String[] array = line.trim().split("[, ]+");
switch(array.length) {
case 2:
// do something
break;
case 3:
// do something
break;
default:
// something wrong
break;
}
The trim() in the line is for avoid empty string in the first element array.
Use split(" +") which will split on any numbers of spaces. This works because split handles regex. If you want to split on any type of whitespace you can also use split("\\s+). After you get the array check if it has 2 or 3 elements and handle it accordingly.
Well ... I don't have the time yet for a long answer. But I'd recommend you to read a little bit about regular expressions (RegEx) and how it is used in java ... I am sure this will help you with this problem and a huge amount of future problems like this ...
Try this: http://www.vogella.com/articles/JavaRegularExpressions/article.html ... of this http://docs.oracle.com/javase/tutorial/essential/regex/ ... if the first one does not help ;)
After running my program I get this beautifully formatted text:
What do I need add to my code in order to get this text outputted to a .txt file exactly as is?
Assuming you're currently writing your output to the screen using something like System.out.Println(...), a comparable way to write text to a file is to use a PrintStream.
You should be able to find many examples of how to do that if you search; here's one.
import java.io.*;
class PrintStreamDemo {
public static void main(String args[]){
FileOutputStream out;
PrintStream ps; // declare a print stream object
try {
// Create a new file output stream
out = new FileOutputStream("myfile.txt");
// Connect print stream to the output stream
ps = new PrintStream(out);
ps.println ("This data is written to a file:");
System.err.println ("Write successfully");
ps.close();
}
catch (Exception e){
System.err.println ("Error in writing to file");
}
}
}
ps. one caution: the "beautifully formatted" part of your text probably relies on the output being displayed in a monospaced font (all characters the same width); if viewed in a non-monospaced font, the columns won't line up. If you're saving it as a plain .txt file, you don't have control over what font someone else will use to display that file when they open it.
Update:
There are a couple of approaches you could take, if you find you've got a program full of System.out.println calls and you want to direct the output to a file instead.
1) The quick & dirty way would be to open a PrintStream to your desired output file, then call System.setOut() to redirect System.out to the specified PrintStream.
2) A perhaps cleaner way would be to rewrite all the calls of System.out.println to use your own output method. That way when you want to change how you're handling output (for example, send it to multiple files, to both the screen and a file, or whatever), you have just one place to change. More work up front, but gives you more flexibility in the end.
You didnt clarify where data come from, but anyway input or db, I would place on a multidimensional array. Then print will be easy.
P.S. Also to keep format I would use tab separated values "/t"
public class Parser {
private void parseData{
int[][] array = new int[3][12];
// print array in rectangular form
for (int r=0; r<array.length; r++) {
for (int c=0; c<array[r].length; c++) {
System.out.print(array[r][c] + "\t");
}
System.out.println("");
}
}
}