Converting a jar-file URI to a File - java

I need to access a configuration file from within my Jar, so I use:
URL configUrl = Object.class.getResource("/config.xml");
Now I need to convert URL into a File object, because that's what the ConfigurationFile object downstream needs for initialization. When I try this:
new File(configUrl.toURI())
I get:
java.lang.IllegalArgumentException: URI is not hierarchical
When I try this:
new File(Thread.currentThread().getContextClassLoader().getResource("config.xml").getFile())
I get:
File does not exist: 'file:\E:\Apps\jarfile.jar!\config.xml'
NOTE: Unfortunately I must have a File object, on an InputStream.

If file is inside of JAR... you can use getResourceAsStream() and read directly or using URL...
URL urlConfig = Object.class.getResource(CONFIG_FILE);
if (urlConfig == null) {
// throw <error>
}
URLConnection connConfig = urlConfig.openConnection();
InputStream isConfig = connConfig.getInputStream(); // do things
Save content to a temporal File... (wait 1 second... mmm)
public static File doThing(InputStream is) throws IOException {
File tmp = null;
FileOutputStream tmpOs = null;
try {
tmp = File.createTempFile("xml", "tmp");
tmpOs = new FileOutputStream(tmp);
int len = -1;
byte[] b = new byte[4096];
while ((len = is.read(b)) != -1) {
tmpOs.write(b, 0, len);
}
} finally {
try { is.close(); } catch (Exception e) {}
try { tmpOs.close(); } catch (Exception e) {}
}
return tmp;
}

Your question doesn't make sense. A resource may be inside a JAR file, and an item in a JAR file simply is not a file, or a File.
Period.
If you need a File object you are going to have to distribute the item separately from the JAR file.

Have you tried this:
File f;
try {
f = new File(url.toURI());
} catch(URISyntaxException e) {
f = new File(url.getPath());
}

Related

How to parse file inside a zip without writing to disk - java

I have a password protected zip file [in the form of a base64 encoded data and the name of the zip file] which contains a single xml. I wish to parse that xml without writing anything to disk. What is the way to do this in Zip4j? Following is what I tried.
String docTitle = request.getDocTitle();
byte[] decodedFileData = Base64.getDecoder().decode(request.getBase64Data());
InputStream inputStream = new ByteArrayInputStream(decodedFileData);
try (ZipInputStream zipInputStream = new ZipInputStream(inputStream, password)) {
while ((localFileHeader = zipInputStream.getNextEntry()) != null) {
String fileTitle = localFileHeader.getFileName();
File extractedFile = new File(fileTitle);
try (InputStream individualFileInputStream = org.apache.commons.io.FileUtils.openInputStream(extractedFile)) {
// Call parser
parser.parse(localFileHeader.getFileName(),
individualFileInputStream));
} catch (IOException e) {
// Handle IOException
}
}
} catch (IOException e) {
// Handle IOException
}
Which is throwing me java.io.FileNotFoundException: File 'xyz.xml' does not exist at line FileUtils.openInputStream(extractedFile). Can you please suggest me the right way to do this?
ZipInputStream keeps all content of a zip file. Each call of zipInputStream.getNextEntry() delivers the content of each file and moves "pointer" to the next entry (file). You also can read the file (ZipInputStream.read) before moving to the next entry.
Your case:
byte[] decodedFileData = Base64.getDecoder().decode(request.getBase64Data());
InputStream inputStream = new ByteArrayInputStream(decodedFileData);
try (ZipInputStream zipInputStream = new ZipInputStream(inputStream, password)) {
ZipEntry zipEntry = null;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
byte[] fileContent = IOUtils.toByteArray(zipInputStream);
parser.parse(zipEntry.getName(),
new ByteArrayInputStream(fileContent)));
}
} catch (Exception e) {
// Handle Exception
}

How to duplicate a file given a different name in the same directory in windows

I have been trying to duplicate a file but change the name of it in the same windows directory but I got not luck.
I cant just copy the file in the same directory because of the windows rule that two files cannot have the same name in the same directory.
I am not allowed to copy it to another directory then rename it, and then move it back in the same directory.
And I don't see any helpful implementation in the File.class.
Tried something like that but it didnt work:
File file = new File(filePath);
File copiedFile = new File(filePath);
//then rename the copiedFile and then try to copy it
Files.copy(file, copiedFile);
An initial attempt would be using Path as suitable:
Path file = Paths.get(filePath);
String name = file.getFileName().toString();
String copiedName = name.replaceFirst("(\\.[^\\.]*)?$", "-copy$0");
Path copiedFile = file.resolveSibling(copiedName);
try {
Files.copy(file, copiedFile);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
You could create a new file in the same directory and then just copy the contents of the original file to the duplicate
See: Java read from one file and write into another file using methods
For more info
you can also use this snippet from https://www.journaldev.com/861/java-copy-file
private static void copyFileUsingStream(File source, File dest) throws IOException {
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(source);
os = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
} finally {
is.close();
os.close();
}
}
#Pierre his code is perfect, however this is what I use so I won't be able to change the extension:
public static void copyWithDifferentName(File sourceFile, String newFileName) {
if (sourceFile == null || newFileName == null || newFileName.isEmpty()) {
return;
}
String extension = "";
if (sourceFile.getName().split("\\.").length > 1) {
extension = sourceFile.getName().split("\\.")[sourceFile.getName().split("\\.").length - 1];
}
String path = sourceFile.getAbsolutePath();
String newPath = path.substring(0, path.length() - sourceFile.getName().length()) + newFileName;
if (!extension.isEmpty()) {
newPath += "." + extension;
}
try (OutputStream out = new FileOutputStream(newPath)) {
Files.copy(sourceFile.toPath(), out);
} catch (IOException e) {
e.printStackTrace();
}
}

Regarding moving the serialized file based on a condition through java

I have to make a program to copy the serialized files from a source folder to target folder only if the target folder does not contain that
serialized file, so the first condition is to check whether the file that i am copying is already existed in target folder or not
if it exists then do not need to copy but if does not exists then copy, so this check of whether file exists or not is need to be done
at every second
source folder is C:\ter\
target folder is C:\bvg\
file to be transffered is gfr.ser
I have come up with this below program but still check is not implemented please advise how can I implement this check also..
class ScheduledTask extends TimerTask {
public void run() {
InputStream inStream = null;
OutputStream outStream = null;
try {
File source = new File("C:\\ter\\");
File target = new File("C:\\avd\\bvg\\");
// Already exists. do not copy
if (target.exists()) {
return;
}
File[] files = source.listFiles();
for (File file : files) {
inStream = new FileInputStream(file);
outStream = new FileOutputStream(target + "/" + file.getName());
byte[] buffer = new byte[1024];
int length;
// copy the file content in bytes
while ((length = inStream.read(buffer)) > 0) {
outStream.write(buffer, 0, length);
}
inStream.close();
outStream.close();
}
System.out.println("File is copied successful!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
the above approach is not working
You can use exists method of java.io.File class like this.
public void run() {
InputStream inStream = null;
OutputStream outStream = null;
try {
File source = new File("C:\\ter\\gfr.ser");
File target = new File(" C:\\bvg\\gfr.ser");
if (target.exists()){ // Already exists. do not copy
return;
}
inStream = new FileInputStream(source);
outStream = new FileOutputStream(target);
byte[] buffer = new byte[1024];
int length;
// copy the file content in bytes
while ((length = inStream.read(buffer)) > 0) {
outStream.write(buffer, 0, length);
}
inStream.close();
outStream.close();
System.out.println("File is copied successful!");
} catch (IOException e) {
e.printStackTrace();
}
}

Write file if not existing

I am trying to create a block that writes a file when the file doesn't exsist, but it has turned into a Catch-22. The file doesn't exist, so it can't write the file so it can exsist. Here is my attempt:
if(!FileReadWrite.file2.exists())
FileReadWrite.fileWrite();
public static File file2 = new File("./settings.txt");
public static void fileWrite()
{
try
{
FileWriter fstream = new FileWriter(file2);
BufferedWriter out = new BufferedWriter(fstream);
String c = Byte.toString(Textures.a);
out.write(c);
out.close();
}catch (Exception e)
{
System.err.println("Error: " + e.getMessage());
}
int ch;
StringBuffer strContent = new StringBuffer("");
InputStream fin = null;
try
{
fin = new FileInputStream(file2);
while ((ch = fin.read()) != -1)
{
strContent.append((char) ch);
}
fin.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
I am using Eclipse. The file is in the bin folder, but when I export it to a jar it is outside the jar folder.
Exception in thread "main" java.lang.ExceptionInInitializerError
at srcD.Main.<init>(Main.java:19) //(FileReadWrite.fileWrite())
at srcD.Main.main(Main.java:129) //(Make JFrame)
Caused by: java.lang.NullPointerException
at srcD.FileReadWrite.<clinit>(FileReadWrite.java:7) //(public file...)
... 2 more
I think this ClassLoader.getSystemResource("settings.txt") code returns null and .getFile() gets an NPE
Answer to comment
Firstly you should understand that method getSystemResource NOT for outside resources read this
For load outside resources from jar you have to use full path to resource, full != absolute,
how to find full path
start point + path to resource
For example we have next files structure /Users/fakeuser/tetsproject/ - this folder contains your jar and conf folder contains or should contain settings.txt, if you have delivery structure like this your code will be
public static File file2 = new File("./conf/settings.txt");
And that is all.

Test if file exists

I'm trying to open a file in android like this :
try
{
FileInputStream fIn = context.openFileInput(FILE);
DataInputStream in = new DataInputStream(fIn);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
if(in!=null)
in.close();
}
catch(Exception e)
{ }
, but in case the file does not exists a file not found exception is thrown . I'd like to know how could I test if the file exists before attempting to open it.
I think the best way to know if a file exists, without actually trying to open it, is as follows:
File file = getContext().getFileStreamPath(FILE_NAME);
if(file.exists()) ...
The documentation says Context.openFileInput either returns an inputStream (file found) or throws a FileNotFoundException (not found)
http://developer.android.com/reference/android/content/Context.html#openFileInput(java.lang.String)
So it looks like the exception is your "test".
You could also try using standard
java.io.File file = new java.io.File(PATHTOYOURCONTEXT , FILE);
if (file.exists()) {
FileInputStream fIn = new FileInputStream(file);
}
But that is not recommended. Context.openFileInput() and Context.openFileOutput() make sure you stay in your applications storage context on the device, and that all of your files get
deleted when your app gets uninstalled.
With the standard java.io.File this is the function I have created, and works correctly:
private static final String APP_SD_PATH = "/Android/data/com.pkg.myPackage";
...
public boolean fileExistsInSD(String sFileName){
String sFolder = Environment.getExternalStorageDirectory().toString() +
APP_SD_PATH + "/Myfolder";
String sFile=sFolder+"/"+sFileName;
java.io.File file = new java.io.File(sFile);
return file.exists();
}
why dont you just catch the FileNotFound exception and take that as the file not being present.
If you want to ensure a file exists (i.e. if it doesn't exist create a new one, if it does then don't erase it) then use File.createNewFile:
https://docs.oracle.com/javase/7/docs/api/java/io/File.html#createNewFile()
e.g.
{
String pathName = <file path name>
File file = new File (pathName);
Uri pathURI = Uri.fromFile (file);
boolean created;
String mIOException = "";
String mSecException = "";
try
{
created = file.createNewFile();
if (created)
{
ctxt.sendBroadcast (new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, pathURI));
}
}
catch (IOException ioex)
{
mIOException = ioex.getMessage();
}
catch (SecurityException sex)
{
mSecException = sex.getMessage();
}
}
If you want to open a file in any case (i.e. if it doesn't exist create a new one, if it does append to the old one) you can use this, no testing necessary:
public static void write_custom_log(String message){
File root = Environment.getExternalStorageDirectory();
try{
BufferedWriter fw = new BufferedWriter(new FileWriter(new File("/mnt/sdcard/tjb_tests/tjb_log_file.txt"),true));
if (root.canWrite()){
fw.write(message);
fw.close();
}
} catch (IOException e) {
Log.e("One", "Could not write file " + e.getMessage());
}
}
My suggestion is to check length of the file. if file.length() returns 0 that means file doesn't exist.

Categories