I'm using the following code for append new position data obtained by GPS, each time position change.
if (isExternalStorageWritable()) {
if (myFile.exists()) {
try {
FileOutputStream fOut = new FileOutputStream(myFile);
OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
myOutWriter.append(location.getLatitude()+", "+location.getLongitude()+", "+nodeCounter+"\n");
myOutWriter.close();
fOut.close();
nodeCounter++;
} catch (Exception e) {
}
} else {
try {
myFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}else
{
Log.i("logGPSData","Error");
}
The problem is that the append does not work, since each time a new row is inserted, the previous row is overwritten, so my file contains always one line, even if I collect many gps data.
The second argument means if text should be appended to the existing file, change the following lines in your code:
FileOutputStream fOut = new FileOutputStream(myFile);
OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
to:
FileOutputStream fOut = new FileOutputStream(myFile,true);
OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut,true);
From the Docs:
public FileOutputStream(String name,boolean append)
throws FileNotFoundException
Creates a file output stream to write to the file with the specified name. If the second argument is true, then bytes will be written to the end of the file rather than the beginning. A new FileDescriptor object is created to represent this file connection.
First, if there is a security manager, its checkWrite method is called with name as its argument.
If the file exists but is a directory rather than a regular file, does not exist but cannot be created, or cannot be opened for any other reason then a FileNotFoundException is thrown.
Parameters:
1) name - the system-dependent file name
2) append - if true, then bytes will be written to the end of the file rather than the beginning
Throws:
1)FileNotFoundException - if the file exists but is a directory rather than a regular file, does not exist but cannot be created, or cannot be opened for any other reason.
2)SecurityException - if a security manager exists and its checkWrite method denies write access to the file.
Since:
JDK1.1
Related
I created a text file with the content "Hello" and I was trying to read these characters from the file and write it back to the same file again.
Assumptions:
1. the file now has the content "Hello" (Overwritten)
2. the file now has the content "HelloHello" (Appended)
3. the file now has the content infinite "Hello" (or an exception gets thrown)
Actual result:
Original "Hello" characters gets deleted from the text file, and the file was left empty.
Actual test
#Test
public void testCopyStream() throws IOException {
File workingDir = new File(System.getProperty("user.dir"));
File testFile = new File(workingDir, "/test.txt");
FileReader fin = new FileReader(testFile);
FileWriter fos = new FileWriter(testFile);
copyStream(fin, fos);
fin.close();
fos.close();
}
I have created the following method for "copying" the data in the InputStream to the OutputStream:
private void copyStream(Reader in, Writer out) throws IOException {
int b;
while ((b = in.read()) != -1) {
out.write(b);
}
}
I tried using debugger to find out the problem, and the debugger shows b = in.read() was assigned -1 at the first iteration of the while loop. Then I executed the code step by step while inspecting the file's content and found that "Hello" keyword got deleted from the file right after statementfinal FileWriter fos = new FileWriter(testFile); gets executed.
I first thought this was due to the InputStream and OutputStream were pointed to the same file so the file gets sort of "locked" by JVM for execution safety?
So I tried swapping those two lines:
FileWriter fos = new FileWriter(testFile);
FileReader fin = new FileReader(testFile);
And the result turned out the same: the file content got eliminated right after the statement FileWriter fos = new FileWriter(testFile);
My questions is: why the content gets cleaned out by FileWriter?. Is this some behavior related to FileDescriptor? Is there a way to read and write to the same file?
Just FYI,
copyStream() method is working fine, I have tested it with other tests.
It's not about using append() method instead of write()
The statement FileWriter fos = new FileWriter(testFile); truncates the existing file.
It does not make sense for you to use streaming access to read and write the same file, as this won't give reliable results. Use RandomAccessFile if you want to read / write the same file: this has calls to seek current position and perform read or writes at different positions of a file.
https://docs.oracle.com/javase/7/docs/api/java/io/RandomAccessFile.html
FileWriter actually deletes everything in a file before writing. To preserve the text, use
new FileWriter(file, true);
The true parameter is the append parameter of the filewriter. Otherwise it will just overwrite everything
this is my directory structure
Inside the server I have the following code for saving a file that gets sent from the client
fileName = reader.readLine();
DataInputStream dis = null;
try {
dis = new DataInputStream(csocket.getInputStream());
FileOutputStream fos = new FileOutputStream(fileName);
buffer = new byte[4096];
int fileSize = 15123;
int read = 0;
int totalRead = 0;
int remaining = fileSize;
while((read = dis.read(buffer, 0, Math.min(buffer.length, remaining))) > 0) {
totalRead += read;
remaining -= read;
fos.write(buffer, 0, read);
}
fos.close();
dis.close();
} catch (IOException e) {
}
break;
I'm wondering how I would go about saving the file within the xml folder? I've tried using getClass().getResource and such but nothing seems to work.
fileName is just a simple string containing the name of the file, not a path or anything.
I get the correct path using this code:
File targetDir = new File(getClass().getResource("xml").getPath());
File targetFile = new File(targetDir, fileName);
targetFile.createNewFile();
System.out.println(targetFile.getAbsolutePath());
dis = new DataInputStream(csocket.getInputStream());
FileOutputStream fos = new FileOutputStream(targetFile.getAbsolutePath(), false);
But it still won't save it there...
The best way is to receive explicitly the target path for storing files, either through a .properties file or a command-line argument. In this way, you make your program flexible to be installed and adapted in different environments.
But if you wish your program to assume the target directory automatically, the best option is to set a relative path before creating the FileOutputStream, as long as you start your program always from the same path:
File targetDir=new File("xml");
File targetFile=new File(targetDir, fileName);
FileOutputStream fos = new FileOutputStream(targetFile);
This will work assuming the program is started from server as current directory.
Update
Other minor suggestions about your program:
Never base the exit condition of the loop on a hard-coded file size, because it is not possible to know it a priori. Instead, check explicitly if the value returned by read is less than 0 => that means End Of File reached.
Consequently, do not bother to calculate the exact amount of data to get through a call to read. Just enter the buffer size, because you are setting a maximum data size.
Never let exceptions catched without a proper treatment: If you know how to make your program recover, enter a proper code into the catch block. Otherwise, you'd better not catch them: Declare them in the throws clause and let them be propagated to the caller.
Always create stream resources through the try-with-resources instruction, to ensure they got closed at the end:
try (FileOutputStream fos = new FileOutputStream(...))
{
// ... use fos...
}
Save unnecessary instructions: If you don't care about if the file already exists on the filesystem or not, don't call createNewFile. But if you care, check the returned value and bifurcate consequently.
I try to create file and it does created but not at ProjectName\src\com\company\xml but in ProjectName\out\production\ProjectName\com\company\xml
my code:
File targetDir = new File(this.getClass().getResource("xml").getPath());
// get the parent of the file
String parentPath = targetDir.getParent( );
String fileName="xml/name.txt";
//do something
File targetFile = new File(parentPath, fileName);
targetFile.createNewFile();
Just pay attention that after compilation you will try to save it into a jar file and it a complicated thing to do.
usually you need to save file into file outside from your jar(separate in the root) like this:
Im writing to a file through a FileOutputStream that is opened via its constructor taking a FileDescriptor.
My desired behavior: When I write to the file I want that to be the only content of it. E.g. writing "Hello" should result in the file containing just "Hello".
Actual behavior: Each time I write something, it is simply appeneded. E.g. in the above example I will get "HelloHello".
How can I open a FileOutputStream like Im doing, and have it not be in append mode?
Note: I am forced to use a FileDescriptor.
According to the ContentProvider.java file documentation, you can use "rwt" mode to read and write in file in truncating it.
ParcelFileDescriptor pfd = context.getContentResolver.openFileDescriptor(uri, "rwt");
FileOutputStream fos = new FileOutputStream(pfd.getFileDescriptor());
#param mode Access mode for the file. May be "r" for read-only access,
"rw" for read and write access, or "rwt" for read and write access
that truncates any existing file.
Hope this help despite that the question was posted a long time ago.
If you use FileOutoutStream then the ctor provides an option for you to specify whether you want to open the file to append or not. Set it to false and it will work.
OutputStream out = null;
try {
out = new FileOutputStream("OutFile", false);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
FileOutputStream(File file, boolean append)
Make the argument append to false, so it overrides the existing data everytime when you call.
https://docs.oracle.com/javase/7/docs/api/java/io/FileOutputStream.html#FileOutputStream(java.io.File,%20boolean)
FileOutputStream outputStream;
try {
outputStream = openFileOutput("your_file", Context.MODE_PRIVATE);
//Context.MODE_PRIVATE -> override / MODE_APPEND -> append
outputStream.write("your content");
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
I'm creating an app which requires to write a file for every user (in JSON format).
The app successfully creates the file, But it's empty. In the code I added a finer output to see how the converted JSON String looks like, and I noticed that it's complete (it contains everything, so the conversion is ok). But the string isn't present in the file.
//create a new FileWriter C:/.../42.guser
FileWriter writer = null;
//for every User
for(int i=0; i<users.size(); i++) {
try {
File f = new File(Users.usersDir.getPath()+"/"+i+".guser");
//Create new file
f.createNewFile();
writer = new FileWriter(f);
//convert to json and write to file. Here we get the object with KEY = keys[i].
String stringedUsr = gson.toJson(users.get(keys[i]));
logger.finer("Converted user: \""+stringedUsr+"\""); //Output seems ok
//Write (NOT WORKING)
writer.write(stringedUsr);
logger.fine("Wrote updated user \""+keys[i]+"\" to file "+f.getCanonicalPath());
} catch (IOException e) {
FAILS++;
e.printStackTrace();
}
}
//End of for
What am I doing wrong?
Note: i gave to the app all the necessary Permissions. No AccessControlExceptions
First of all think about closing your writer.
When closing, it should flush() your data first (as mentioned in the doc here)
You can also flush() manually.
I have some word documents and excel sheets which has some images along with the file text content. I want to create a copy of that file and keep it at a specific location. I tried the following method which is creating file at specified location but the file is corrupted and cannot be read.
InputStream document = Thread.currentThread().getContextClassLoader().getResourceAsStream("upgradeworkbench/Resources/Upgrade_TD_Template.docx");
try {
OutputStream outStream = null;
Stage stage = new Stage();
stage.setTitle("Save");
byte[] buffer= new byte[document.available()];
document.read(buffer);
FileChooser fileChooser = new FileChooser();
fileChooser.setInitialFileName(initialFileName);
if (flag) {
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Microsoft Excel Worksheet", "*.xls"));
} else {
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Microsoft Word Document", "*.docx"));
}
fileChooser.setTitle("Save File");
File file = fileChooser.showSaveDialog(stage);
if (file != null) {
outStream = new FileOutputStream(file);
outStream.write(buffer);
// IOUtils.copy(document, outStream);
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
Can anyone suggest me any different ways to get the proper file.
PS: I am reading the file using InputStream because it is inside the project jar.
PPS: I also tried Files.copy() but it didnt work.
I suggest you never trust on InputStream.available to know the real size of the input, because it just returns the number of bytes ready to be immediately read from the buffer. It might return a small number, but doesn't mean the file is small, but that the buffer is temporarily half-full.
The right algorithm to read an InputStream fully and write it over an OutputStream is this:
int n;
byte[] buffer=new byte[4096];
do
{
n=input.read(buffer);
if (n>0)
{
output.write(buffer, 0, n);
}
}
while (n>=0);
You can use the Files.copy() methods.
Copies all bytes from an input stream to a file. On return, the input stream will be at end of stream.
Use:
Files.copy(document, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
As the class says, the second argument is a Path, not a File.
Generally, since this is 2015, use Path and drop File; if an API still uses File, make it so that it uses it at the last possible moment and use Path all the way.