Symbolic Link Creation in Android Within an Application's Asset Directory - java

I can't seem to find a solid answer for this specific question.
I'm trying to create a symbolic link programmatically of a directory in my assets folder in another location within the same application's asset directory. Essentially, I'm looking to do the same thing as what the createSymbolicLink method of Java.nio.Files would do.
Is there an available way of doing this with the Android SDK? If not, is it possible in the NDK?

For Android API 21 and above, just use:
Os.symlink(originalFilePath,symLinkFilePath);

There is no public API to do this. You can however use some dirty reflection to create your symbolic link. I just tested the following code and it worked for me:
// static factory method to transfer a file from assets to package files directory
AssetUtils.transferAsset(this, "test.png");
// The file that was transferred
File file = new File(getFilesDir(), "test.png");
// The file that I want as my symlink
File symlink = new File(getFilesDir(), "symlink.png");
// do some dirty reflection to create the symbolic link
try {
final Class<?> libcore = Class.forName("libcore.io.Libcore");
final Field fOs = libcore.getDeclaredField("os");
fOs.setAccessible(true);
final Object os = fOs.get(null);
final Method method = os.getClass().getMethod("symlink", String.class, String.class);
method.invoke(os, file.getAbsolutePath(), symlink.getAbsolutePath());
} catch (Exception e) {
// TODO handle the exception
}
A quick Google search showed this answer if you don't want to use reflection: http://androidwarzone.blogspot.com/2012/03/creating-symbolic-links-on-android-from.html

Related

Loading owl file in android

I know this question was asked earlier but there is no proper solution anywhere right now so i am going to ask it again.
How can i load an owl file in my android project?
The code works in java but they are useless in android . When i try them in an android project then the file can not be accesed . I am using OWLApi 3.4.10.
I am loading the ontology from my mainActivity class. The loading is performed in loadOntology method in OntologyClass class.
In main method the coding is as
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ontologyClass ontology;
ontology = new ontologyClass();
try {
ontology.ontologyLoad();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
The coding of ontologyClass is as:
#Ignore
#SuppressWarnings("javadoc")
public class ontologyClass {
OWLOntology pizza;
OWLOntologyManager manager;
public ontologyClass ontologyLoad() throws OWLOntologyCreationException {
manager= OWLManager.createOWLOntologyManager();
File file= new File("assets/Pizza.owl");
pizza = manager.loadOntologyFromOntologyDocument(file);
return this;
}
The pizza.owl file is inside the assets folder.
In logcat i receive warnings like
FileNotFountException: /assets/Pizza.owl: open failed:ENOENT (no such file or directory)
can anyone fix this file loading problem?
Thanks
Tackling Build path error:
Normally if you are using owl api in java then all you need is just to import the owl api library. But in android if you do only this you will still get error stating "method not found". So you need to perform a second step i.e right click your android project and then
properties-> Java Build Path -> order and export tab
and there check mark the OWLAPi 3.4.10.jar
the answer for the file path in assets folder is as follows:
The directory/path of theowl file in asserts folder can be accessed via InputStream class the File class doesn't work for this folder, so instead of using
File file= new File("assets/Pizza.owl");
use this code
InputStream is= myContext.getAssets().open("Pizza.owl");
and finally use the InputStream instance is, this represents the correct path of the file in assets folder ie
pizza = manager.loadOntologyFromOntologyDocument(is);

read/copy file inside dynamic web project in java

I create a dynamic web app project using JSP/Servlet with eclipse. And I want to create a copy of "db.xls" file in the same place.
I try to create a copy of the "db.xls", the copy will named out.xls but it won't. These files should be located inside the same folder "files". My code compile, db.xls is correctly read, but file out.xls is not created.
What's wrong with my method ? Please help !
public void readExcel()
{
try{
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL url1 = classLoader.getResource("");
// read db.xls
wbook = Workbook.getWorkbook(new File(url1.getPath()+"/db.xls"));
// create a copy of db.xls nammed out.xls
wwbCopy = Workbook.createWorkbook(new File(url1.getPath()+"/out.xls"), wbook);
shSheet = wwbCopy.getSheet(0);
}
catch(Exception e)
{
e.printStackTrace();
}
}
I move the file "db.xls" inside WEB-INF and use getServletContext().getRealPath("/WEB-INF") but the output file "out.xls" still not created.
public void readExcel()
{
try{
// ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// URL url1 = classLoader.getResource("");
String tomcatRoot = getServletContext().getRealPath("/WEB-INF");
wbook = Workbook.getWorkbook(new File(tomcatRoot+"/db.xls"));
wwbCopy = Workbook.createWorkbook(new File(tomcatRoot+"/out.xls"), wbook);
shSheet = wwbCopy.getSheet(0);
}
catch(Exception e)
{
e.printStackTrace();
}
}
System.out your files and you'll see what's wrong
System.out.println(new File(tomcatRoot+"/db.xls").getAbsolutePath());
System.out.println(new File(tomcatRoot+"/out.xls").getAbsolutePath());
You expect the file to be you project directory but it isnt read/writen from/to that location because you have set up the files forlder as source folder in eclipse, so it is part our yours assempbly and lands in the classpath where you can read from a resource, i.e. using classloader and getResource / getResourceAsStream but you cannot and should not write to it, for several resons, most obvious is that your web app might not be unpacked from a war files.
In fact, you dont know where you are reading/writing your files to/from.
You might package your file with the war file and read from it, this is correct. But for writing the best is to have an explicite location on the filesystem where you can write your output files. check this answer for how you could go abut it using context init parameter
check the WEB-INF/classes folder, it might be in there
I think your missing write and close statements.
Try:
wwbCopy.write();
wwbCopy.close();
In order to read files within a web application, the files need to be stored somewhere under the WEB-INF folder, otherwise they won't be deployed as part of the application.
Once you've moved the folders into there you can use the following method within a servlet:
String tomcatRoot = getServletContext().getRealPath("/");
This will give you the root of the web application. Then you must build the path (including the WEB-INF folder) from there:
String sourceFile = tomcatRoot + "/WEB-INF/folder/source.file"
String targetFile = tomcatRoot + "/WEB-INF/folder/target.file"
EDIT: I originally stated that getRealPath() would give you the WEB-INF location. It doesn't, it gives the parent folder.

Know what methods are in .jar files

I know that there is a plugin for ImageJ that handles NIfTI-1 files (http://rsb.info.nih.gov/ij/plugins/nifti.html).
But all its instructions on that page is to use ImageJ as a standalone program, however I am using its API. How can I know what methods are available in this jar file without its source?
I couldn't find the source code either.
For the supported archives in imageJ (such as DICOM) is quite easy :
public class ImageJTest {
public static void main(){
String path = "res/vaca.dcm";
FileInputStream fis;
ImageView image;
try {
fis = new FileInputStream(path);
DICOM d = new DICOM(fis);
d.run(path);
// Stretches the histogram because the pictures were being
// displayed too dark.
(new ij.plugin.ContrastEnhancer()).stretchHistogram(d, 0.1);
Image picture = SwingFXUtils.toFXImage(d.getBufferedImage(),
null);
// Makes the size standard for thumbnails
image = new ImageView(picture);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
How can I load the NIfTI-1 files in imageJ ?
Once you have the class files, which are embedded in the jar file (as #Alvin Thompson pointed out, these are just zip files by a different name), you can use the reflection API to mine the class files to get their methods. A sample follows for one class, cribbed from here:
Method[] methods = thisClass.getClass().getMethods(); // thisClass is an instance of the class you're working with
for(Method method : methods){
System.out.println("method = " + method.getName());
}
JAR files are just fancy ZIP files. You can rename the file to foo.zip, then use any unzip utility to expand its contents. You should be able to at least see what the class files are, and the javadocs may be bundled with it (unlikely these days but possible).
However, if you just want to know what methods are available, probably the best way is to add the JAR to the class path of a project in NetBeans, Eclipse, or IntelliJ and use their code completion features to figure out the API methods and classes.
you can do even a decompile of the jar and see the code that is behind each class using a decompiler.
A good one i found: Java Decompiler
JD-GUI home page: http://java.decompiler.free.fr
It does really good it's job. At least in the tasks i had.

how to access resources(Excel file) in jar file

Hi i have exported my java project as executable jar file. inside my project I am accessing a Excel file containing some data. Now I am not able to access the Excel file when I am trying to access the file.
My project structure is:
Java_Project_Folder
- src_Folder
- resources_Folder(Containing excel file)
I am accessing the excel file like
FileInputStream file=new FileInputStream(new File(System.getProperty("user.dir")
+File.separator+"resources"+File.separator+"Excel.xlsx"));
I have tried accessing this file using getResourceAsStream like:
FileInputStream file=(FileInputStream) this.getClass().getResourceAsStream
("/resources/Excel.xlsx");
But i am getting in is null exception. whats wrong can anyone help?
I bet you have no package called resources in your project.
Trying to use Class.#getResourceAsStream is the way to go. But this method does not return a FileInputStream. It returns an InputStream wich is an interface.
You should be passing the absolute name of the resource
InputStream is = getClass().getResourceAsStream("my/pack/age/Excel.xlsx");
where the excel file is located in the directory
resources/my/pack/age
The first step is to include the excel file itself in your project. You can create a resources folder like you show, but to make sure this gets included in your jar, you add the resources folder in along with your source code files so that it gets built into the jar.
Then
InputStream excelContent = this.getClass().getResourceAsStream("/resources/Excel.xlsx");
should work. From one post at least, the leading forward slash may also mess things up if you use the ClassLoader.
getClass().getResourceAsStream("/a/b/c.xml") ==> a/b/c.xml
getClass().getResourceAsStream("a/b/c.xml") ==> com/example/a/b/c.xml
getClass().getClassLoader().getResourceAsStream("a/b/c.xml") ==> a/b/c.xml
getClass().getClassLoader().getResourceAsStream("/a/b/c.xml") ==> Incorrect
ref: getResourceAsStream fails under new environment?
Also in eclipse you can set the resources folder as a source folder like this:
in the properties of your eclipse project, go to java build path, select sources, and check to see if all needed source fodlers are added (as source folders). If some are missing, just add them manually using add sources... button
ref: Java Resources Folder Error In Eclipse
I tried this and it is working for me.
My Test1 class is in default package, just check where your accessing class is in any package, if it is then go back to exact resource folder from classpath like this "../"
public class Test1 {
public static void main(String[] args) {
new Test1();
}
Test1(){
BufferedInputStream file= (BufferedInputStream) this.getClass().getResourceAsStream("resources/a.txt");
try {
System.out.println((char)file.read());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
FileInputStream file= (FileInputStream)
this.getClass().getResourceAsStream("/resources/Excel.xlsx");
Why do you need FileInputStream? Use
InputStream is = getClass().getResourceAsStream..
Secondly use "resources/Excel.xlsx"
Thirdly when constructing file like this
new
File(System.getProperty("user.dir")+File.separator+"resources"+File.separator+"Excel.xlsx"));
is hard to control slashes. use
new File("parent (userdir property)", "child (resources\Excel.xlsx)")

Java language detection with langdetect - how to load profiles?

I'm trying to use a Java library called langdetect hosted here. It couldn't be easier to use:
Detector detector;
String langDetected = "";
try {
String path = "C:/Users/myUser/Desktop/jars/langdetect/profiles";
DetectorFactory.loadProfile(path);
detector = DetectorFactory.create();
detector.append(text);
langDetected = detector.detect();
}
catch (LangDetectException e) {
throw e;
}
return langDetected;
Except with respect to the DetectFactory.loadProfile method. This library works great when I pass it an absolute file path, but ultimately I think I need to package my code and langdetect's companion profiles directory inside the same JAR file:
myapp.jar/
META-INF/
langdetect/
profiles/
af
bn
en
...etc.
com/
me/
myorg/
LangDetectAdaptor --> is what actually uses the code above
I will make sure that the LangDetectAdaptor which is located inside myapp.jar is supplied with both the langdetect.jar and jsonic.jar dependencies it needs for langdetect to work at runtime. However I'm confused as to what I need to pass in to DetectFactory.loadProfile in order to work:
The langdetect JAR ships with the profiles directory, but you need to initialize it from inside your JAR. So do I copy the profiles directory and put it inside my JAR (like I prescribe above), or is there a way to keep it inside langdetect.jar but access it from inside my code?
Thanks in advance for any help here!
Edit : I think the problem here is that langdetect ships with this profiles directory, but then wants you to initialize it from inside your JAR. The API would probably benefit from being changed a little bit to just consider profiles its own configuration, and to then provide methods like DetectFactory.loadProfiles().except("fr") in the event that you don't want it to initialize French, etc. But this still doesn't solve my problem!
I have the same problem. You can load the profiles from the LangDetect jar using JarUrlConnection and JarEntry. Note in this example I am using Java 7 resource management.
String dirname = "profiles/";
Enumeration<URL> en = Detector.class.getClassLoader().getResources(
dirname);
List<String> profiles = new ArrayList<>();
if (en.hasMoreElements()) {
URL url = en.nextElement();
JarURLConnection urlcon = (JarURLConnection) url.openConnection();
try (JarFile jar = urlcon.getJarFile();) {
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
String entry = entries.nextElement().getName();
if (entry.startsWith(dirname)) {
try (InputStream in = Detector.class.getClassLoader()
.getResourceAsStream(entry);) {
profiles.add(IOUtils.toString(in));
}
}
}
}
}
DetectorFactory.loadProfile(profiles);
Detector detector = DetectorFactory.create();
detector.append(text);
String langDetected = detector.detect();
System.out.println(langDetected);
Since no maven-support was available, and the mechanism to load profiles was not perfect (since you you need to define files instead of resources), I created a fork which solves that problem:
https://github.com/galan/language-detector
I mailed the original author, so he can fork/maintain the changes, but no luck - seems the project is abandoned.
Here is an example of how to use it now (own profiles can be written where necessary):
DetectorFactory.loadProfile(new DefaultProfile()); // SmProfile is also available
Detector detector = DetectorFactory.create();
detector.append(input);
String result = detector.detect();
// maybe work with detector.getProbabilities()
I don't like the static approach the DetectorFactory uses, but I won't rewrite the full project, you have to create your own fork/pull request :)
Looks like the library only accepts files. You can either change the code and try submitting the changes upstream. Or write your resource to a temp file and get it to load that.
The solution provided by Mark Butler is still valid and solved my problem, but the dirname needs to be updated as the jar content has changed.
The problem has been reported by Deepak but I have insufficient reputation to reply in comments. Here you are the two declarations you need.
In order to load short profiles:
String dirname = "profiles/shorttext/";
In order to load long profiles:
String dirname = "profiles/longtext/";
Setting the working dir for me fixed the problem.
String workingDir = System.getProperty("user.dir");
DetectorFactory.loadProfile(workingDir+"/profiles/");

Categories