How to write to a file in Android (without FileNotFoundException Error) - java

I am having some issues writing to a file in my internal storage in Android. What I am wanting to achieve, is it first of all check whether there is a file (of specified name) already existing in the internal storage. If there isn't, I would then like it to create a file with that name, and write specified content to it. If there is already a file, I would simply like it to write specified content appended to what is already stored within the file. I think I have found how I can check if the file is in existence, and also create a new blank file with the specified name if it isn't (see code below). However, when coming to write to the file I get an error message java.io.FileNotFoundException error, even though my code should ensure that there will always be a file in existence to open with the FileOutputStream. Please could anyone tell me what I am doing wrong. Thanks in advance.
public boolean isFilePresent() {
String strASANo = getIntent().getStringExtra("strASA"); //Part of File Name imported passed from parameter
String logsFile = strASANo + "logs";
File file = getBaseContext().getFileStreamPath(logsFile);
return file.exists();
}
//////////////////////////////////////////////////////////////////////////////
public void addSaveClick(View view) {
if (!isFilePresent()) {
File file = new File(getApplicationContext().getFilesDir(), logsFile);
}
FileOutputStream logWriter;
try {
logWriter = openFileOutput(logsFile, MODE_APPEND); //Unhandled Exception: java.io.FileNotFoundException
}
}

Related

SonarQube Vulnerability while using File class in Java

Objective: The batch application needs to read a file from the server. The exact directory might change in future and so we should make it dynamic.
Approach taken: The file path (directories) and the file name will be provided in the application yaml file as follows:
file path: /application/directory
file name: test.csv
Code for the same:
Initial version:
File file = new File(filePath,filename);
SonarQube showed it vulnerable by suggesting this:
A file is opened to read its content. The filename comes from an input parameter. If an unfiltered parameter is passed to this file API, files from an arbitrary filesystem location could be read.
This rule identifies potential path traversal vulnerabilities. In many cases, the constructed file path cannot be controlled by the user. If that is the case, the reported instance is a false positive.
Vulnerable Code:
#GET
#Path("/images/{image}")
#Produces("images/*")
public Response getImage(#javax.ws.rs.PathParam("image") String image) {
File file = new File("resources/images/", image); //Weak point
if (!file.exists()) {
return Response.status(Status.NOT_FOUND).build();
}
return Response.ok().entity(new FileInputStream(file)).build();
}
Solution:
import org.apache.commons.io.FilenameUtils;
#GET
#Path("/images/{image}")
#Produces("images/*")
public Response getImage(#javax.ws.rs.PathParam("image") String image) {
File file = new File("resources/images/", FilenameUtils.getName(image)); //Fix
if (!file.exists()) {
return Response.status(Status.NOT_FOUND).build();
}
return Response.ok().entity(new FileInputStream(file)).build();
}
I have changed my code accordingly:
File file = new File(filePath,FilenameUtils.getName(fileName));
Still I am getting the same error message.
Yes it is a False Positive.
I removed this by using //NOSONAR at the end of the statement
File file = new File("resources/images/", FilenameUtils.getName(image)); //NOSONAR

Trying to create a new file throws FileNotFoundException but file exists in the same package [duplicate]

This question already has answers here:
java.io.FileNotFoundException: the system cannot find the file specified
(8 answers)
Closed 4 years ago.
I have a csv file in the same path as everything else. Now, when I try to create a File object:
public void getMenu() {
File fileMenu = new File("FastFoodMenu.csv");
try {
Scanner inputStream = new Scanner(fileMenu);
while (inputStream.hasNext()) {
String data = inputStream.next();
System.out.println(data);
}
} catch (FileNotFoundException ex) {
Logger.getLogger(FileHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
it throws a FileNotFoundException.
the absolute path to all files in the project is:
C:\Users\kenyo\Documents\NetBeansProjects\OrderFastFood\src\fastfoodorderingsystem
I also checked the name a couple of times. fileMenu.exists() returns false.
First, in your root/working directory (in your case it's the folder containing your project), create a folder called 'menus', here you can store all your menus (so you can play around with multi-file input).
Second, move your FastFoodMenu.csv file to that menus folder.
The FastFoodMenu.csv relative path should now look like this: OrderFastFood\menus\FastFoodMenu.csv.
Third, get your working directory from the System properties. This is the folder in which your program is working in. Then, get a reference (File object) to the menus folder.
Lastly, get a reference to the file in question inside the menu folder. When you get to multi-file reading (and at some point, multi-folder reading), you're gonna want to get the files inside the menu folder as a list so that's why I say to just get the menus folder as it's own reference (or just get the file without the isolated reference to the parent aka '\menus\').
So your code should really look like this:
public void getMenu() {
final File workingDir = File(System.getProperty("user.dir"));
final File menusDir = File(workingDir, "menus");
final File fastFoodMenu = File(menusDir, "FastFoodMenu.csv");
try {
final FileInputStream fis = new FileInputStream(fastFoodMenu);
final BufferedInputStream bs = new BufferedInputStream(fis);
while((l = bs.readLine()) != null) {
System.out.println(l);
}
} catch(FileNotFoundException e) {
System.out.println(e.getMessage());
e.printStackTrace()
}
}
This is all psuedocode but that should at least get you started. Make sure to use BufferedInputStream for efficiency, and when reading files, always pass them into FileInputStream's. It's much better than using the Scanner class. I should also mention that when creating a File object, you're not actually creating a file. What you're doing is your're creating an object, giving it the data you want it to have (such as whether it's a folder, and if it is, what child files/folders do you want it to have, whether it's protected or not, hidden or not, etc) before actually telling the system to create the file with everything else.
Your csv file is probably at the wrong place. You're just specifying the file name, which is a relative path.
Relative paths are always resolved against the working directory of your application, not against the directory where your source file(s) are.
To solve the issue, you can
move the files to the real working directory.
use an absolute path (not advisable!)
specify the folder of your data files as program argument or in a config file (in your working directory)
put the files somewhere into the classpath of your application and load them from there via classloader. Note that files that are in your classpath are usually packed with your application and hence not easily modifiable by the user, so this solution doesn't work if the file must be changed by the user.

Creating a file, read it and discard

I'm getting a file from a HTTP request and I need to read and search for a string.
My problem is that the file is not on the system so I need to transferTo a created file.
My question is: where do usually hosts create this temporary files? I want to read the file, search for how many times a string appears and delete the file? Is this the way things are done?
public static int readTestCaseCode(MultipartFile multipartFile) {
File file = new File(//Do I need to specify a location?)
multipartFile.transferTo();
Scanner scanner = new Scanner(file)
}
Use the static factory method File#createTempFile(String, String) which exactly creates what the name says.
File file = File.createTempFile("myFile", ".exe");
You can also omit the ending and just pass null, which then will be filled with ".tmp", e.g.
File file = File.createTempFile("myFile", null);
The file can then afterwards be deleted by invoking the File#delete() method:
file.delete();

Creating a new directory inside Android internal memory and writing data to it

Most of the examples I have seen deal with external memory or show how to create a new directory inside internal memory but not how to write to it, I tried implementing my own code into it but can't seem to find the created file even though the directory has been created, here is the code that I have been trying to use:
public void fileCreate(Context context, String fileDir) throws Exception{
File myNewDir = context.getDir(fileDir, Context.MODE_PRIVATE);
if (!myNewDir.exists()){
myNewDir.mkdirs();
File testContnet = new File(myNewDir + "/hello_file.txt");
String hello = "Hello world";
FileOutputStream fos = openFileOutput(testContnet.toString(), Context.MODE_PRIVATE);
fos.write(hello.getBytes());
fos.close();
}
}
Now, when I call this function I use:
try {
fileCreate(this, "testerDirectory");
}catch(Exception e) {
e.printStackTrace();
}
With no results. It is just for a small experiment I am doing so it is nothing too serious, but I still want to know about the proper way of creating a directory(in this case one called testerDirectory, and saving the file to it, I believe that my code is wrong but I do not have much experience with this to know exactly where to go. The Android documentation did show me how to create and save files although in this case I am trying to merge that example with that of creating a new directory and saving a file to it. Any help/pointers would be greatly appreciated.
I know also that the file is not being written accordingly upon inspecting the contents of the directory by using the adb shell.
You are only writing a file to the directory if the directory does not already exist.
Move your work with testContnet to be outside of the if block:
public void fileCreate(Context context, String fileDir) throws Exception{
File myNewDir = context.getDir(fileDir, Context.MODE_PRIVATE);
if (!myNewDir.exists()){
myNewDir.mkdirs();
}
File testContnet = new File(myNewDir, "hello_file.txt");
String hello = "Hello world";
FileOutputStream fos = new FileOutputstream(testContnet);
fos.write(hello.getBytes());
fos.flush();
fos.getFD().sync();
fos.close();
}
This way, you create the directory if it does not exist, but then create the file in either case. I also added fos.flush() and fos.getFD().sync(), to ensure all bytes get written to disk before you continue.
UPDATE: You were using openFileOutput(), which does not write to your desired directory. Moreover, it is unnecessary. Just create a FileOutputStream on your File.

rewrite file instead of recreating a file

I have the following piece of code which allows me to recreate a file holding updated data. Even though I used the "StandardOpenOption.TRUNCATE_EXISTING" option to overwrite the old file I was getting an error saying that the file already exists and it wouldn't write on top of it!
File filename = new File("data.txt");
public void writeToFile(char[] data){
filename.delete();
Files.write(filename.toPath(), data, StandardOpenOption.TRUNCATE_EXISTING);
}
Is it possible instead of deleting and recreating the same file over and over to edit the initial file's data?
Thank you
EDIT1: It seems like it was a mistake of mine. Together with "StandardOpenOption.TRUNCATE_EXISTING" I have included "StandardOpenOption.CREEATE_NEW".
This is because I want the file to be created in case it doesn't already exist! How is it possible to first try to edit it and if it doesnt exist create a new one?
Sorry for my initial mistake
The way to go on this one (which worked for me) is creating a try{}catch{} block and within the "try" try to edit the file and if it fails because it doesn't exist create a new file in the "catch".
Look at the JavaDoc of the write method in the Files class, it says: "By default the method creates a new file or overwrites an existing file", so it seems that all you need to do is:
File filename = new File("data.txt");
public void writeToFile(char[] data) throws IOException {
Files.write(filename.toPath(), data);
}

Categories