How to change a value of a file using Java IO function - java

Can anyone help me how to change a line in a file using java IO function. The file is located at SDCard. I have tried some solution from different blog, but failed.
I need to change one attribute wpa_oper_channel=1 to 2,3,4..... as user demand in the file sdcard/sample.txt.
I have also tried using SED command, but still not working. Please suggest if there any solution using java IO function.
The Command I have used using SED :
sed -i 's/wpa_oper_channel=[0-9]\\+/wpa_oper_channel=7/' sample.txt

If your configuration file is in the form of a Properties file. This means each line is in a format of key=value. You can easily read, modify and write it. Here is an example, I assume you have no problem with reading and writing a file through streams.
File sdcard = Environment.getExternalStorageDirectory();
File file = new File(sdcard,"sample.txt");
InputStream is = new FileInputStream(file); // Read your existing file
Properties props = new Properties();
props.load(is);
props.setProperty("wpa_oper_channel", "4");
OutputStream out = new FileOutputStream(file); // Your output file stream
prop.store(output, null); // Save your properties file without header
By doing this, you may lose if there is another type of line like comments or else.
Update
I updated to source code. But still you need to get read and write permission.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I haven't test the code, It will work with some exception handling. If it is not work please specify your error.

You just have to
read the file's content into memory (there are millions of examples on how to do that with java),
change the content (finding the position could be done using e.g. indexOf("wpa_oper_channel="))
write the content back to the file (there are millions of examples for that too)

What android do you use?
From android 4.4+ user haven't access to edit and remove files from SD Card. You must copy them to external storage and use there. See this link - http://code.google.com/p/android/issues/detail?id=67570

Related

URI to file in Zip incorrect if path contains spaces

I want to get the URIs to the entries of a zip file in order to keep references to it's contents without having to keep the zip file open.
Therefore I open the zip file using the zip filesystem and export the Path of the entries as URI.
Path zipfile = ...
URI uriOfFileInZip;
try(FileSystem fs = FileSystems.newFileSystem(zipfile, null)){
Path fileInZip = fs.getPath("fileInZip.txt");
uriOfFileInZip = fileInZip.toUri();
}
Now I want to read the file again, so I try to open a stream to the file.
InputStream is = uriOfFileInZip.toURL().openStream();
This works as long as the path of the zip file does not contain any spaces. As soon as it contains spaces, I get an error like this
java.io.FileNotFoundException: D:\example\name%20of%20zipfile.zip (The system cannot find the file specified)
the URI to the file in the zip is
jar:file:///D:/example/name%2520of%2520zipfile.zip!/fileInZip.txt
the name of the zip is
D:\example\name of zipfile.zip
I wonder about the %2520 this seems like an issue with the URL encoding, but shouldn't this be handled transparently? Or is it a bug?
Any ideas to solve this problem?
Looks like a bug.
Seems as if com.sun.nio.zipfs.ZipPath.toUri() is either messed up, or I didn't read the corresponding RFC yet ;-). Played around with some other file names. There seems to be a double encoding going on for the zip file path, but not for the file entry in the zip.
Besides not using the URI-approach you could also build the URI yourself from scratch, but then you are not that flexible anymore. Or you just undo the unnecessary encoding:
String uriParts[] = uriOfFileInZip.toString().split("!");
uriParts[0] = URLDecoder.decode(uriParts[0], "UTF-8");
uriOfFileInZip = URI.create(String.join("!", uriParts));
But to be honest, I would rather try to omit the URI for zip files or if you really have to, rename the files beforehand ;-) Better yet: open a bug if it does not behave as stated in the corresponding RFCs.
You may also want to get some additional information from the following question regarding bug, etc.:
Java 7 zip file system provider doesn't seem to accept spaces in URI
EDIT (added proposal without URI):
You can also try to completely work with your Path instance (fileInZip) instead of the URI, as the path instance "knows" its filesystem.
As soon as you need access to the file inside the zip, you create a new FileSystem based on the information of the Path instance (fileInZip.getFileSystem()). I did not elaborate that completely, but at least the file store should contain all the necessary information to access the zip file again. With that information you could call something like FileSystems.newFileSystem(Paths.get(fileStoreName), null).
Then you can also use Files.newInputStream(fileInZip) to create your InputStream. No need to use URI here.
This is only reproducible with JDK 8. The later versions do not have this issue.
For the following code:
Map<String, String> env = new HashMap<>();
env.put("create", "true");
final FileSystem fs = FileSystems.newFileSystem(new URI("jar:file:/D:/path%20with%20spaces/junit-4.5.jar"), env);
System.out.println(fs.getPath("LICENSE.TXT").toUri()); `
I got the following output with JDK 1.8.0_212 :
jar:file:///D:/path%2520with%2520spaces/junit-4.5.jar!/LICENSE.TXT
whereas with JDK 11.0.3:
jar:file:///D:/path%20with%20spaces/junit-4.5.jar!/LICENSE.TXT
A search through the Java bug system shows that it had been fixed in JDK 9 with JDK-8131067 .

Extracting files from res folder in Executable JAR (txt files to be specific)

I would like to ask if its possible to put text files into my jar, I use them to make my map in my game, but users can get Highscores. now I want to save the Highscores with the map, so I have to save the map on the user their PC. Is there any way how I could do this? I've searched the internet for some ideas but I could not find anything that even came close to what I've wanted. I only had 3/4th of a year java so I don't know much about these things, everything that happens outside the debug of eclipse are problems for me(files are mainly one of those things, null exceptions, etc).
The main question now.
Is it possible to do? If yes, do you have any terms I could search on, or some sites/guides/tutorials? If no, is there any other way how I could save the highscores?
EDIT:
to make clear
Can I get the text file (the text inside the file) to be extracted to a different file in like the home directory of my game (where I save the settings and stuff) the basic maps are inside the jar file, so I want them to be extracted on the first start-up of the program
Greetings Carolien
"extracted to a different file in like the home directory of my game (where i save the settings and stuff) the basic maps are inside the jar file, so i want them to be extracted on the first startup of the program"
You can get the URL by using getClass().getResource()
URL url = getClass().getResource("/res/myfile.txt");
Then create a File object from the URI of the URL
File file = new File(url.toURI());
Then just perform your normal file operations.
if (file.renameTo(new File(System.getProperty("user.home") + "\\" + file.getName()))) {
System.out.println("File is moved successful!");
} else {
System.out.println("File is failed to move!");
}
Assuming your file structure is like below, it should work fine
ProjectRoot
src
res
myfile.txt
Note: the above is moving the entire file. If you want to extract just the data inside the file, then you can simple use
InputStream is = getClass().getResourceAsStream("/res/myfile.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
The just do normal IO operation with the reader. See here for help with writing the file.

File.renameTo() fails

I have eclipse plugin jface application.
A thread writes file via BufferedWriter.
After writing is done I close the buffer after that I try to rename the file.
But sometimes file is not renamed!
I tried to add some Thread.Sleep(BIG_NUMBER) between couple of retries this didn't help.
It looks like the file getting some kind of lock. (when I kill the jvm I can rename the file).
Is there something I can do?
OS: Windows XP, windows 7
JAVA version: 1.5
File.RenameTo() is platform dependent and relies on a few conditions to be met in order to succesfully rename a file, a better alternative is using
Path source = currentFile.toPath();
try {
Files.move(source, source.resolveSibling(formattedName));
} catch (IOException e) {
e.printStackTrace();
}
Read more here.
From the javadocs:
Many aspects of the behavior of this method are inherently
platform-dependent: The rename operation might not be able to move a
file from one filesystem to another, it might not be atomic, and it
might not succeed if a file with the destination abstract pathname
already exists. The return value should always be checked to make sure
that the rename operation was successful.
Note that the Files class defines the move method to move or rename a file in a platform independent manner.
For the File.renameTo() to work,The file will need to be somehow writable by external applications.
You can also do something like below:
File o=new File("oldFile.txt");
File n=new File("newFile.txt");
n.delete();
o.renameTo(n);
n.delete() : We need to delete the file(new.txt) if exists.
o.rename(n) : so that the file(old.txt) is renamed as new.txt
How to find out why renameTo() failed?
Reliable File.renameTo() alternative on Windows?
http://www.bigsoft.co.uk/blog/index.php/2010/02/02/file-renameto-always-fails-on-windows
We have had issues under Windows 7 with UAC and unexpected file permissions. File#canWrite will return true even though any attempts to perform file I/O will fail.
Make sure the file you are trying to rename actually exists
Make sure that the location you are attempting to write the file (or rename the file) to is accessible. We write a simple text file to the location, check to see if it exists and that it's contents is correct (we're paranoid) before we attempt any further I/O.
This is working fine for me. Rename is done using two steps but don't forget to set permissions in manifest.xml with:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
public boolean RenameFile(String from, String to) {
to.replace(" ", ""); // clear all spaces within file name
File oldfile = new File(from);
File newfile = new File(to);
File tempfile = new File(to + ".tmp"); // add extension .tmp
oldfile.renameTo(tempfile);
return (tempfile.renameTo(newfile));
}

Save my Unique ID (String) and retrieving it later when I re-launch my Java application

I want to save a Unique ID (which is a String) which gets created when I launch my Java application. Now I want to save this somewhere (I think in some file on the disk) so that when I relaunch my application I should be able to read it and use that ID.
I want to know what is the good way to saving such ID. I am thinking of creating a Properties file and save it then retrieve it from it when I relaunch application. Is there a better or standard way for this?
EDIT :
Additionally what should be the folder location for storing on the disk. Should it be relative to my execution path or some Logged-in user specific path?
1. If its the same Java application that writes or reads this String, then use Serialization, it will be in non-readable form when saved.
2. If reading and writing is from different program, then use Text file.
3. Using Property file will be also a good approach.
If your app/program needs to store more data at some point sqlite3 might be the best option for you. It is easy to implement and use.
Download sqlite3
EDIT: How many IDs will be stored in the app? If there are just a few, a textfile or property file is enough.
EDIT2: Navigate to your Documents folder on your machine and you will see folders of programs/games. Thats where you should place the file/db. However you can also store it in the installation path on your hard drive. Also make sure your user launches the app trough a shortcut, not the actual execution file
Use the FileWriter and File classes from Java.
It should be something like that:
File f = new File(your path here);
if (f.exists()){
BufferedReader br = new BufferedReader(new FileReader(your path here));
String a = br.readLine();
br.close();
}else{
FileWriter fw = new FileWriter(your path here);
fw.write(your ID String);
fw.flush();
fw.close();
I hope this is want u meant.
Best regards
edit: just noticed too late that your edited your post....

Understanding Simple XML Parser - New File Output - Java

I am trying to learn how to use the Simple XML Framework as detailed in this thread : Best practices for parsing XML.
I am using the following code :
public class SimpleXMLParserActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
Serializer serializer = new Persister();
Example example = new Example("Example message", 123);
File result = new File("example.xml");
try {
Log.d("Start", "Starting Serializer");
serializer.write(example, result);
} catch (Exception e) {
// TODO Auto-generated catch block
Log.d("Self", "Error");
e.printStackTrace();
}
}
}
I am having a problem understanding the line
File result = new File("example.xml");
1) Does this line create a new file in my app called example.xml ? If so where is this file located.
2) Or does this line look for an existing file called example.xml and then add to it ? If so where should the example.xml file be placed in my app bundle so that it can be found. I do notice at the moment I am getting an error message :
java.io.FileNotFoundException: /example.xml (Read-only file system)
Thank you.
File result = new File("example.xml")
This line will just store the filename "example.xml" in a new File object. There is no check if that file actually exists and it does not try to create it either.
A file without specifying an absolute path (starting with / like new File("/sdcard/example.xml")) is considered to be in the current working directory which I guess is / for Android apps (-> /example.xml (Read-only file system))
I guess serializer.write(example, result); tries to create the actual file for your but fails since you can't write to '/'.
You have to specify a path for that file. There are several places you can store files, e.g.
Context#getFilesDir() will give you a place in your app's home directory (/data/data/your.package/files/) where only you can read / write - without extra permission.
Environment#getExternalStorageDirectory() will give you the general primary storage thing (might be /sdcard/ - but that's very different for devices). To write here you'll need the WRITE_EXTERNAL_STORAGE permission.
there are more places available in Environment that are more specialized. E.g. for media files, downloads, caching, etc.
there is also Context#getExternalFilesDir() for app private (big) files you want to store on the external storage (something like /sdcard/Android/data/your.package/)
to fix your code you could do
File result = new File(Environment.getExternalStorageDirectory(), "example.xml");
Edit: either use the provided mechanisms to get an existing directory (preferred but you are limited to the folders you are supposed to use):
// via File - /data/data/your.package/app_assets/example.xml
File outputFile = new File(getDir("assets", Context.MODE_PRIVATE), "example.xml");
serializer.write(outputFile, result);
// via FileOutputStream - /data/data/your.package/files/example.xml
FileOutputStream outputStream = openFileOutput("example.xml", Context.MODE_PRIVATE);
serializer.write(outputStream, result);
or you may need to create the directories yourself (hackish way to get your app dir but it should work):
File outputFile = new File(new File(getFilesDir().getParentFile(), "assets"), "example.xml");
outputFile.mkdirs();
serializer.write(outputFile, result);
Try to avoid specifying full paths like "/data/data/com.simpletest.test/assets/example.xml" since they might be different on other devices / Android versions. Even the / is not guaranteed to be /. It's safer to use File.separatorChar instead if you have to.
2 solutions to do it cleanly :
use openFileOutput to write a private file in the application private directory (which could be located in the internal memory or the external storage if the app was moved there). See here for a snippet
or use the File constructor to create the File anywhere your app has write access. This is if you want to store the file on the SDCard for example. Instantiating a file doesn't create it on the file system, unless you start writiung to it (with FileOutputStream for example)
I'd recommend approach 1, it's better for users because these files get erased when your app is uninstalled. If the file is large, then using the External Storage is probably better.
What I read on the Android pages, I see it creates a file with that name:
File constructor
I think it writes it to the /data/data/packagname directory
edit: the 'packagename' was not shown in the tekst above. I put it between brackets. :s
Try saving to /sdcard/example.xml.

Categories

Resources