I have a property file named sysconfig.properties, I want to read it multiple times, because it is mutable.But I found when I changed the content of the sysconfig.properties then I read the content that is imutable, which is the same with the first time I read from the systemconfig.properties file.The content of the sysconfig.propertes file as follows:
isInitSuccess=TRUE
isStartValid=2013
May be sometime it will been changed as follows:
isInitSuccess=FALSE
isStartValid=2013
The code of read the properties file as follows:
InputStream inStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath);
I use the code read the file mutilple times, but every time the "isInitSuccess" is "TRUE", even though I changed the isInitSuccess=FALSE.Is the system just read it one time, then I read the file, it just get the input stream from the memory?
But when I use the code below, it will work fine:
InputStream inStream = new FileInputStream(new File(strPath));
I googled, but I did not find any help, the problem confused me a lot, any help would be appreciate.
You need to read up on what the classpath is.
In short, Java has a concept of classpath which includes all the resources (.class files, .properties files, and anything really) it needs to run. When you use ClassLoader#getResourceAsStream(String), you're actually getting the InputStream of a classpath resource. This resource can be a physical resource on disk or it can be in an archive.
When you use a FileInputStream, you are getting the InputStream of a file on disk.
The InputStream from the ClassLoader and the one from the FileInputStream do not correspond to the same file.
You should read up on how your IDE (or whatever build system) handles your files.
Related
My question is simple. Would Java handle a .zip file with about 450,000 files in there? The code that I wrote would not load all of the files, just one specific file would be searched in the zip, and be read line by line. The file size is about 500kb.
Would this work or will I get an OutOfMemory Exception?
Oh sry, uncompressed there about 0,5MB. Zipped are they whole files about 250mb.
Ok, the name of the Files are IDs + Date(unique) in that zip file. If i have to check a log, ill call Java and give the ID + Date and Java is reading just that one file, never more.
Edit: It works, it works very well. About 400.000 files in a zip, if u have the Memory to Zip the Files works without any problem.
Edit2: It works on Linux Filesystems witout a problem, on NTFS sometimes it crashed. NTFS has a problem with that musch files in 1 Zip.
Using the zip filesystem in Java 7, you can actually access one individual file pretty easily and open a BufferedReader on it.
First you have to create the FileSystem:
public static FileSystem getZipFileSystem(final String zipPath)
{
final Path path = Paths.get(zipPath).toAbsolutePath();
final Map<String, Object> env = new HashMap<>();
final URI uri = URI.create("jar:file:" + path.toString());
return FileSystems.newFileSystem(uri, env, null);
}
Once you have done that, you can create a BufferedReader from an entry in the zip itself:
try (
final FileSystem fs = getZipFileSystem("/path/to/the.zip");
final BufferedReader reader = Files.newBufferedReader(fs.getPath("path/to/entry"),
StandardCharsets.UTF_8);
) {
// operate on the reader
}
You could also read all lines in the entry at once using Files.readAllLines().
If you wish to copy a zip entry to a file on the filesystem, you can also do that:
Files.copy(zipfs.getPath("path/to/entry"), Paths.get("file/on/local/fs"));
Or you can directly copy the result to an OutputStream, or directly create an entry from an OutputStream...
Or even walk the entire zip using Files.walkFileTree().
Or get all the entries in a "directory" in a zip using Files.newDirectoryStream(). Note that as its name says, this is a stream; unlike File.listFiles() (which only works on files on disk anyway), this returns a iterator over the entries.
Or... Or... Or...
Note that a FileSystem needs to be .close()d.
I'm not sure that I understand what you're trying to do.
If it's 0.5 MB/file and 450,000 files, you'll need 225GB. You won't have enough memory to do all this in a single zip in memory even if you get 90% compression.
I'd recommend breaking it into manageable chunks. You'll be able to parallelize that way too, so it's not a bad idea.
i know this question has been asked several times, but i think my problem differs a bit from the others:
String resourcePath = "/Path/To/Resource.jar";
File newFile = new File(resourcePath);
InputStream in1 = this.getClass().getResourceAsStream(resourcePath);
InputStream in2 = this.getClass().getClassLoader().getResourceAsStream(resourcePath);
The File-Object newFile is completely fine (the .jar file has been found and you can get its meta-data like newFile.length() etc)
On the other hand the InputStream always return null.
I know the javadoc says that the getResourceAsStream() is null if there is no resource found with this name, but the File is there! (obviously, because it's in the File-Object)
Anyone know why this happens and how i can fix it so that i can get the .jar File in the InputStream?
The getResourceAsStream() method doesn't load a file from the file system; it loads a resource from the classpath. You can use it to load, for example, a property file that's packaged inside your JAR. You cannot use it to load a file from the file system.
So, if your file resides on the file system, rather than in your JAR file, better use the FileInputStream class.
I have an application that requires a user to upload a zipfile containing xml report file among other files.
What I want to do is, to verify it is a zip, then open and check if there is an xml file, and verify some few nodes which are required in that xml.
I want to do this before I save this zipfile to a disk/filesystem, and withought creating a temporary file. I will only save the file if it passes the validation.
I am using Spring multipart CommonsMultipartFile to manage uploads.
The application is using Java, jsp, tomcat
Thanks.
See my comment on the OP about the wisdom of buffering the entire file in memory.
One quick first check for a valid zip file would be to check the first 4 bytes for the appropriate "magic" bytes. a zip file should start with the first 4 bytes {(byte)0x50, (byte)0x4b, (byte)0x03, (byte)0x04}. the only way to really check it, however, is to attempt to unzip it.
If you want to check whether a file is a ZIP file, perhaps you can use getContentType() method of the URLConnection class? Something like this:
URL u = new URL(fileUrl);
URLConnection uc = u.openConnection();
String type = uc.getContentType();
But it would be much faster to detect the magic bytes which, for the ZIP format, are 50 4B.
when I new a File Object ,I found that there is not a file be create in disk,so I guess a File Obeject is not equal to a disk file, but when I write something to the File object through stream, I found the file be created in disk.
So, can I think like this, new File() - does not create a real file in disk, it is just an object in ram. But when you write something to the File through stream, for example:
FileWrite stream = new FileWrite(file);
stream.write(string);
..the stream will create a new file when the file does not exist (maybe function steam.write() does this?)?
How about File#createNewFile()? If you're using Java 7, you can also use Files.createFile(Path), as in this example from the Java tutorial.
FileWriter creates or truncates the file as required. The write put something in it. File is a file path name which may or may not exist. e.g. File.exists() is not always true and File.delete() can delete a file (i.e. the file no longer exists)
In a unit test I am overwriting a config file to test handling bad property values.
I am using Apache Commons IO:
org.apache.commons.io.FileUtils.copyFile(new File(configDir, "xyz.properties.badValue"), new File(configDir, "xyz.properties"), false)
When investigating the file system I can see that xyz.properties is in fact overwritten - size is updated and the content is the same as that of xyz.properties.badValue.
When I complete the test case which goes through code that reads the file into a Properties object (using a FileReader object) I get the properties of the original xyz.properties file, not the newly copied version.
Through debugging where I single step and investigate the file I can rule out it being a timing issue of writing to the file system.
Does the copy step somehow hold a file handle? If so how would I release it again?
If not, does anybody have any idea why this happens and how to resolve it?
Thanks.
If you initialized the FileReader object before this object, then it will have already stored a temp copy of the old version.
You'll need to reset it:
FileReader f = new FileReader("the.file");
// Copy and overwrite "the.file"
f = new FileReader("the.file");
In the Unix filesystem model, the inode containing the file's contents will persist as long as someone has an open filehandle into the file, or there is a directory entry pointing to it.
Replacing the file's name in the directory, does not remove the inode (contents of the file), so your already-open filehandle can continue to be used.
This is actually exploitable to create temporary files that never need to be cleaned up: create the file, then unlink it immediately, while keeping it open. When you close the file handle, the inode is reaped
I realize that this doesn't answer your question directly, but I think that it would be better to maintain two separate files, and arrange for your code to have the name of the configuration file configurable / injected at runtime. That way, your tests can specify which config file to use, rather than overwriting a single file.