I am making an application that includes file copying, but when I go through a large directory (1000+) files and copy them to another folder, it uses 290+ MB of RAM.
So, is there any way to change the File of FileOutputStream without creating a new instance of the FileOutoutStream class?
EDIT:
Here is my Java 7 API version.
Path source = FileSystems.getDefault().getPath(Drive.getAbsolutePath(), files[i].getName());
Path destination = FileSystems.getDefault().getPath(Save);
try {
Files.copy(source, destination);
} catch (FileAlreadyExistsException e) {
File file = new File(Save + files[i]);
file.delete();
}
Keep in mind, that this is in a for loop that is being tested on 1000+ file counts.
With the current method I am using 270+ MB of RAM
No, you can't redirect a FileOutputStream to a different file.
If you're using Java 7, you can use the new Files class to copy files. The Files.copy() methods can do most of the work for you.
Otherwise, verify that you're closing your streams. Prior to Java 7's try-with-resources, it could look something like this:
FileOutputStream out = null;
try {
// Create the output stream
// Copy the file
} catch (IOException e) {
// Do something
} finally {
if ( null != out ) {
try { out.close(); } catch ( IOException ) { }
}
}
Have a look at this question: Standard concise way to copy a file in Java?
specifically
..., Apache Commons IO is the way to go, specifically FileUtils.copyFile(); it handles all the heavy lifting for you.
How about some nio2 from Java 7?
Path source = // ...
Path target = // ...
Files.copy(source, target);
See javadoc of Files.copy(...) for details. See also the optional parameter CopyOption.
Related
I am trying to read classes from java.base as InputStreams. I already have a method to read classfiles given a File object, but I am unable to obtain File objects, since I'm using JDK 11 and there isn't an rt.jar file anymore. After following this answer, I have roughly the following code (I'm using Scala, but this is essentially a question about Java, hence the tags):
val fs = FileSystems.newFileSystem(URI.create("jrt:/"), Collections.emptyMap, loader)
Files.list(fs.getPath("/modules")).forEach { mdl =>
Files.walk(mdl).forEach { (classFile: Path) =>
val asFile = classFile.toAbsolutePath.toFile //Here's where I get an exception
//do stuff with that
}
}
Unfortunately, when I use classFile.toFile or classFile.toAbsolutePath.toFile, I get an UnsupportedOperationException, which I guess is because it's not a physical file. However, I require a File object to turn into an InputStream and read. How can I get File objects for every classfile in a certain module (or every module) that is part of the JDK?
You don't necessarily need a File to create an InputStream. You can also use a Path together with Files::newInputStream :
Files.list(fs.getPath("/modules")).forEach(mdl -> {
try(Stream<Path> stream = Files.walk(mdl)) {
stream.forEach(classFile -> {
try (InputStream input = Files.newInputStream(classFile)) {
...
} catch(IOException e) {
...
}
});
} catch(IOException e) {
...
}
});
I am aware that Oracle notes ZIP/GZIP file compressor/decompressor methods on their website. But I have a scenario where I need to scan and find out whether any nested ZIPs/RARs are involved. For example, the following case:
-MyFiles.zip
-MyNestedFiles.zip
-MyMoreNestedFiles.zip
-MoreProbably.zip
-Other_non_zips
-Other_non_zips
-Other_non_zips
I know that apache commons compress package and java.util.zip are the wideley used packages where commons compress actually caters for the missing features in java.util.zip e.g. some character setting whilst doing zipouts. But what I am not sure about is the utilities for recursing through nested zip files and the answers provided on SO are not very good examples of doing this. I tried the following code (which I got from Oracle blog), but as I suspected, the nested directory recursion fails because it simply cannot find the files:
public static void processZipFiles(String pathName) throws Exception{
ZipInputStream zis = null;
InputStream is = null;
try {
ZipFile zipFile = new ZipFile(new File(pathName));
String nestPathPrefix = zipFile.getName().substring(0, zipFile.getName().length() -4);
for(Enumeration e = zipFile.entries(); e.hasMoreElements();){
ZipEntry ze = (ZipEntry)e.nextElement();
if(ze.getName().contains(".zip")){
is = zipFile.getInputStream(ze);
zis = new ZipInputStream(is);
ZipEntry zentry = zis.getNextEntry();
while (zentry!=null){
System.out.println(zentry.getName());
zentry = zis.getNextEntry();
ZipFile nestFile = new ZipFile(nestPathPrefix+"\\"+zentry.getName());
if (zentry.getName().contains(".zip")) {
processZipFiles(nestPathPrefix+"\\"+zentry.getName());
}
}
is.close();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
if(is != null)
is.close();
if(zis!=null)
zis.close();
}
}
May be I am doing something wrong - or using the wrong utils. My objective is to identify whether any of the files or nested zip files have got file extensions which I am not allowing. This is to make sure that I can prevent my users to upload forbidden files even when they are zipping it. I also have the option to use Tika which can do recursive parsing (Using Zukka Zitting's solution), but I am not sure if I can use the Metadata to do this detection how I want.
Any help/suggestion is appreciated.
Using Commons Compress would be easier, not least because it has sensible shared interfaces between the various decompressors which make life easier + allows handling of other compression formats (eg Tar) at the same time
If you do want to use only the built-in Zip support, I'd suggest you do something like this:
File file = new File("outermost.zip");
FileInputStream input = new FileInputStream(file);
check(input, file.toString());
public static void check(InputStream compressedInput, String name) {
ZipInputStream input = new ZipInputStream(compressedInput);
ZipEntry entry = null;
while ( (entry = input.getNextEntry()) != null ) {
System.out.println("Found " + entry.getName() + " in " + name);
if (entry.getName().endsWith(".zip")) { // TODO Better checking
check(input, name + "/" + entry.getName());
}
}
}
Your code will fail as you're trying to read inner.zip within outer.zip as a local file, but it doesn't exist as a standalone file. The code above will process things ending with .zip as another zip file, and will recurse
You probably want to use commons compress though, so you can handle things with alternate filenames, other compression formats etc
I have tried and succeed moving files from one folder to another folder using java . Here is my code
File source = new File("D:\\polo\\");
File desc = new File("E:\\polo2\\");
try {
FileUtils.copyDirectory(source, desc);
} catch (IOException e) {
e.printStackTrace();
}
But i would like to move specific files from one folder to the other not all the files. Is this possible to do in java. Please help us on this
You can use Java SE standard utility
java.nio.file.Files.copy(Path source, Path target, CopyOption... options)
use renameTo
public static void main(String[] args)
{
try{
File source = new File("D:\\polo\\");
File desc = new File("E:\\polo2\\");
if(source .renameTo(new File("E:\\polo2\\" + afile.getName()))){
System.out.println("File is moved successful!");
}else{
System.out.println("File is failed to move!");
}
}catch(Exception e){
e.printStackTrace();
}
}
In java 1.7, new IO classes were added, including the Files utility class which has a method copy.
There is an example of usage here.
Use IOUtils Library for copy file from one location to another location.
For eg.
File source = new File("D:\\polo\\fileold");
File desc = new File("E:\\polo2\\filenew");
IOUtils.copy(source, desc);
Try this..
My program has a function that read/write file from resource. This function I have tested smoothly.
For example, I write something to file, restart and loading again, I can read that data again.
But after I export to jar file, I faced problems when write file. Here is my code to write file:
URL resourceUrl = getClass().getResource("/resource/data.sav");
File file = new File(resourceUrl.toURI());
FileOutputStream output = new FileOutputStream(file);
ObjectOutputStream writer = new ObjectOutputStream( output);
When this code run, I has notice error in Command Prompt:
So, My data cannot saved. (I know it because after I restarted app, nothing changed !!!)
Please help me solve this problem.
Thanks :)
You simply can't write files into a jar file this way. The URI you get from getResource() isn't a file:/// URI, and it can't be passed to java.io.File's constructor. The only way to write a zip file is by using the classes in java.util.zip that are designed for this purpose, and those classes are designed to let you write entire jar files, not stream data to a single file inside of one. In a real installation, the user may not even have permission to write to the jar file, anyway.
You're going to need to save your data into a real file on the file system, or possibly, if it's small enough, by using the preferences API.
You need to read/write file as an input stream to read from jar file.
public static String getValue(String key)
{
String _value = null;
try
{
InputStream loadedFile = ConfigReader.class.getClassLoader().getResourceAsStream(configFileName);
if(loadedFile == null) throw new Exception("Error: Could not load the file as a stream!");
props.load(loadedFile);
}
catch(Exception ex){
try {
System.out.println(ex.getMessage());
props.load(new FileInputStream(configFileName));
} catch (FileNotFoundException e) {
ExceptionWriter.LogException(e);
} catch (IOException e) {
ExceptionWriter.LogException(e);
}
}
_value = props.getProperty(key);
if(_value == null || _value.equals("")) System.out.println("Null value supplied for key: "+key);
return _value;
}
in my android app I'm using an own java library that extracts a .db-file from jar. In Java desktop it works well, but when I try to do it on android, the inputstream blocks forever. The copy method looks like this:
InputStream in = classloader.getResourceAsStream(...);
OutputStream out = new FileOutputStream(new File(...));
try {
while ((read = in.read()) != -1) {
out.write(read);
}
} finally {
try {
in.close();
} catch (final Exception e) {
LOGGER.debug("Error", e);
}
try {
out.close();
} catch (final Exception e) {
LOGGER.debug("Error", e);
}
}
I want to copy this file to the external files dir and android.permission.WRITE_EXTERNAL_STORAGE is granted.
Is there a way to access the file in /data/app/...apk? If not, how can I detect that it can not be accessed without blocking forever?
You should put the database-file in the /assets-folder and copy it to the /databases-folder on first run. A tutorial on this can be found here.
However, if you only want to create the tables and some sample-entry's, you might want to use the onCreate()-method from the SQLiteOpenHelper to do so.
Maybe you should store your data in the raw folder, you access it then :)
http://developer.android.com/guide/topics/resources/index.html
Answering to the question : we can only extract the class files from the apk that we have got, we will not get the layout/xml files or any other files.
There are ways by which we can extract the class files from the apk.