Java - FileOutputStream overwrites file, but it doesn't seem to change - java

So, when I write to a file using FileOutputStream, it does change the file's contents, seen as when I read it with an InputStream I get exactly what I wrote. However, when I open the file in the resources directory, it remains the same as before, despite it being changed.
My code:
import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
public class Program {
public static void main(String[] args) throws URISyntaxException, IOException {
String edit = "Edit2";
String fileName = "/File.txt";
URL url = Object.class.getResource(fileName);
try (FileOutputStream fos = new FileOutputStream(new File(url.toURI()))) {
fos.write(edit.getBytes());
}
try(InputStream is = Object.class.getResourceAsStream(fileName)) {
StringBuilder sb = new StringBuilder();
int read = is.read();
while (read != -1) {
sb.append((char) read);
read = is.read();
}
System.out.println(sb.toString());
}
}
}
By the way, I am using IntelliJ IDEA, and have this file on the resources folder. It's just a .txt file with contents Not changed, so I can know if it was overwritten.
I would want to know whether this problem is related to code or not, and if it is, how can I fix it?

Sounds silly, but try refreshing the folder before opening the file.

Turns out that I shouldn't be using Object.class.getResource(fileName) to open the file from the classpath, but instead directly instantiating a File object.
import java.io.*;
public class Program {
public static void main(String[] args) throws IOException {
String edit = "Edit";
String fileName = "resources/File.txt";
File file = new File(fileName);
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(edit.getBytes());
}
try (InputStream is = new FileInputStream(file)) {
StringBuilder sb = new StringBuilder();
int read = is.read();
while (read != -1) {
sb.append((char) read);
read = is.read();
}
System.out.println(sb.toString());
}
}
}
I believed it's related to the path, as CHN pointed out.

Related

Copying Jar file without corruption

I need to copy a .jar file (which is a resource in my project) from a separate runnable jar to the startup folder in windows. Here's the code I have so far.
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class Installer {
public static void main(String[] args) throws IOException
{
InputStream source = Installer.class.getResourceAsStream("prank.jar");
byte[] buffer = new byte[source.available()];
source.read(buffer);
File targetFile = new File(System.getProperty("user.home") + File.separator + "AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\prank.jar");
OutputStream outStream = new FileOutputStream(targetFile);
outStream.write(buffer);
outStream.close();
}
}
My problem is that after the jar file is copied, it is corrupt (although the size of the original and the copy are the same.) Any thoughts on how to do this and have a runnable jar at the end of the process?
Refer to InputStream#available does not work.
The following line
byte[] buffer = new byte[source.available()];
is not correct, as available only return estimate of the size, the jar will be corrupted when estimate is different with actual. (Example from Java – Write an InputStream to a File) seems incorrect as I can't find any reference that guarantee correctness of available for FileInputStream.
Solution from How to convert InputStream to File in Java is more robust,
private static void copyInputStreamToFile(InputStream inputStream, File file)
throws IOException {
try (FileOutputStream outputStream = new FileOutputStream(file)) {
int read;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
// commons-io
//IOUtils.copy(inputStream, outputStream);
}
}
You can consider to use
IOUtils#copy(InputStream, OutputStream)
Files#copy(InputStream, Path, CopyOption...) suggested by Holger for jdk 1.7 or above
Try this -
Path source = Paths.get("location1/abc.jar");
Path destination = Paths.get("location2/abc.jar");
try {
Files.copy(source, destination);
} catch(FileAlreadyExistsException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

Use the FileReader to read the file

Today, I read the Basic I/O in the Java tutorial and I find some problem:
public class CopyCharacters {
public static void main(String[] args) throws IOException {
FileReader inputStream = null;
FileWriter outputStream = null;
try {
inputStream = new FileReader("/workspaces/test/a.txt");
outputStream = new FileWriter("/workspaces/test/b.txt");
int c;
while ((c = inputStream.read()) != -1) {
outputStream.write(c);
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
}
}
But when I run the demo, it failed. In the Console:
Exception in thread "main" java.io.FileNotFoundException: /workspaces/test/b.txt (Access is denied)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:221)
at java.io.FileOutputStream.<init>(FileOutputStream.java:110)
at java.io.FileWriter.<init>(FileWriter.java:63)
at Demo.CopyCharacters.main(CopyCharacters.java:13)
How can I do that?
File might have a lock and forbid you to open it for writing (i.e. your application is still on a break point in debug mode and you forgot to stop it or you killed the app and the process is still running in memory). You can check by doing this:
inputStream = new FileReader("/workspaces/test/a.txt");
File outFile = new File("/workspaces/test/b.txt");
if (!outFile.canWrite()) {
System.err.println("Cannot write into file: " + outFile.getAbsolutePath());
}
outputStream = new FileWriter(outFile);
You can also renname your out file "b.txt" for something else and it will work as before (until you locked it again by accident). An other way to do this is to use a temporary file:
public static void main(String[] args) throws Exception {
FileReader inputStream = null;
FileWriter outputStream = null;
try {
inputStream = new FileReader("/workspaces/test/a.txt");
File file = File.createTempFile("test", null);
outputStream = new FileWriter(file);
System.out.println(file.getAbsolutePath());
int c;
while ((c = inputStream.read()) != -1) {
outputStream.write(c);
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
}
Good for coding (and debugging). It ensures that it will be deleted by the OS after.
Maybe you should try to use a new feature that takes care of your resources automatically by putting them inside the try-catch block?
public static void main(String[] args) throws IOException {
try (
FileReader inputStream = new FileReader("/workspaces/test/a.txt");
FileWriter outputStream = new FileWriter("/workspaces/test/b.txt");
)
{
int c;
while ((c = inputStream.read()) != -1) {
outputStream.write(c);
}
}
}
If you write your code in this manner, you don't need the finally block, because java will take care of the resources that are inside the try block brackets.

Why is is my program not pulling in the files from the folder

I have a program that is suppose to read all the files in my folder and combine the files into on file and place them into a new folder. Some of the files are not being pulled in and I do not know why.
The file names are wonder1.txt, wonder2.txt, wonder3.txt, and wonder4.txt and the folder name is Alice, but only a few of the files are actually in the new folder.
import java.io.*;
import java.util.Scanner;
import java.util.*;
import java.lang.*;
import java.io.PrintWriter;
public class alice {
public static void main(String[] args) throws FileNotFoundException, IOException {
File folder = new File("/Users/DAndre/Desktop/Alice");
//Reads in all the files in that folder
for (final File fileEntry : folder.listFiles()) {
String fileName = fileEntry.getAbsolutePath();
BufferedReader br = new BufferedReader(new FileReader(fileName));
try {
StringBuilder stringBuilder = new StringBuilder();
String line = br.readLine();
while (line != null) {
stringBuilder.append(line);
stringBuilder.append("\n");
line = br.readLine();
}
/**
* Pass original file content as string to another method which
* creates new file with same content.
*/
newFile(stringBuilder.toString());
} finally {
br.close();
}
}
}
public static void newFile(String fileContent) {
try {
String newFileLocation = "/Users/DAndre/Desktop/final/final_copy.txt";
PrintWriter writer = new PrintWriter(newFileLocation);
writer.write(fileContent);//Writes original file content into new file
writer.close();
System.out.println("File Created");
} catch (Exception e) {
e.printStackTrace();
}
}
}
The problem with your solution is that you haven't initialize PrintWriter in append mode, because of which the new file gets overwritten with the content of the last file that was written.
public static void newFile(String fileContent) {
try {
String newFileLocation = "C:\\Users\\Shayan\\Desktop\\files2\\final_copy.txt";
PrintWriter writer = new PrintWriter(new FileOutputStream(new File(newFileLocation), true /* append = true */));
writer.write(fileContent);//Writes original file content into new file
writer.close();
System.out.println("File Created");
} catch (Exception e) {
e.printStackTrace();
}
}
The last argument in the constructor of FileOututStream is set to true, indicating that it should be opened in append mode.
You need to change
PrintWriter writer = new PrintWriter(newFileLocation);
to
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(newFileLocation, true)))
Little explanation: append meant to write it additively, on the contrary write overrides the existing file. In your code you are creating a new file including one of your wonders, but on next iteration the file is recreated. So the content of previous wonder is gone.
With the change PrintWriter object is not recreating the file, instead it writes content to a BufferedWriter which also transfers the stream to an append able FileWriter object.
Little suggest: do not create a PrintWriter object on each iteration.
Second little suggest: You don't need PrintWriter. BufferedWriter itself is good enough as far as I see.

Get file from the specified path

I need to read a file from a specified path. E.g: I have a file called abc.txt and it resides inside /dev/user/assets/data/abc.png.
If one has to read from a Zip file we do something like
Zipfile zipFile = new ZipFile("test.zip");
ZipEntry entry = zipFile.getEntry(imagePath); // where image path is /dev/user/assets/data/abc.png.
Is there a code something similar to the above for reading from a folder?
Like
File folder = new Folder("Users");
and give the path "/dev/user/assets/data/abc.png" to the above and read the image.
Yes, File has two-args constructor File(File parent, String child) that does exactly what you describe (you may just have to throw the leading '/' of the child). Take a look at the JavaDoc
I'm not sure if I understand exactly what you want to do. But if what you want to do is simply to read the contents of a file with a given path, then you should'nt use the File API.
Instead you should use a new FileReader(textFilePath); or a new FileInputStream(imageFilePath);
Look at the following example, taken from the java tutorials.
import java.io.FileReader;
import java.io.FileWriter;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.IOException;
public class CopyLines {
public static void main(String[] args) throws IOException {
BufferedReader inputStream = null;
PrintWriter outputStream = null;
try {
inputStream = new BufferedReader(new FileReader("xanadu.txt"));
outputStream = new PrintWriter(new FileWriter("characteroutput.txt"));
String l;
while ((l = inputStream.readLine()) != null) {
outputStream.println(l);
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
}
}

Why is this data.txt file deleted whenever I restart the program?

I have a simple txt file that will save only 1 word, but whenever I restart the program everything inside the data.txt is deleted - I don't know why?
The whole class code:
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
public class InfoSaver {
File data = new File("data.txt");
FileOutputStream fos;
PrintStream writer;
FileInputStream fis;
DataInputStream reader;
public void init() throws IOException{
fos = new FileOutputStream(data);
writer = new PrintStream(fos);
fis = new FileInputStream(data);
reader = new DataInputStream(fis);
}
public void writeData(String info) {
writer.println(info);
}
public String readData() throws IOException{
return reader.readLine();
}
public void close() throws IOException{
writer.close();
reader.close();
}
}
To add to an existing file instead of overwriting it, use FileOutputStream's constructor that lets you open it in append mode.
fos = new FileOutputStream(data, true);
Because of this line:
fos = new FileOutputStream(data);
This version of the constructor of FileOutputStream will overwite the file, but you could use this version:
public FileOutputStream(File file,
boolean append)
throws FileNotFoundException
You'd have to specify that you want to append to the file by setting the append field to true.
You're not appending new information to the file, you're overwriting it.
Anytime you just open it in the
fos = new FileOutputStream(data);
command, it gets emptied, no matter if you have saved anything inside it or not.
Your FileOutputStream is overwriting your file. If you want to append to the end of the file you need to specify that:
fos = new FileOutputStream(data, true);
When you encounter unexpected behavior it's a good idea to check the API to ensure the functions you're calling are doing what you expect. Here is the API for the FileOutputStream constructor.

Categories

Resources