How to find whether a process is running on Windows/Linux - java

I want my program to be able to detect whether OBS-Studio is currently running, and if it is, perform certain functionality in my program. The problem is I can't seem to find a solution that will work on both platforms. I've found things that use taskList, wmic.exe and others on windows, and I've found things using top, ps aux and others on linux, however these are very platform specific, and not easily ported. Is there a universal use case, and if so, what might it be?
I'm aware of ProcessHandle in Java9+, however my program runs Java8, with no current hope of upgrading, so that's not possible.

I Cannot think of a solution that will work on both platforms,
maybe use something like below to determine the operating system in Java then from there, use a conditional statement to execute the portion of the code appropriate for your host machine.
os = System.getProperty("os.name");
I hope this helps

I ended up creating a method that would return a Map<Integer, String> for all processes by running os-specific commands:
public Map<Integer, String> getProcesses() {
final Map<Integer, String> processes = Maps.newHashMap();
final boolean windows = System.getProperty("os.name").contains("Windows");
try {
final Process process = Runtime.getRuntime().exec(windows ? "tasklist /fo csv /nh" : "ps -e");
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
reader.lines().skip(1).forEach(x -> { // the first line is usually just a line to explain the format
if (windows) {
// "name","id","type","priority","memory?"
final String[] split = x.replace("\"", "").split(",");
processes.put(Integer.valueOf(split[1]), split[0]);
}
else {
// id tty time command
final String[] split = Arrays.stream(x.trim().split(" ")).map(String::trim)
.filter(s -> !s.isEmpty()).toArray(String[]::new); // yikes
processes.put(Integer.valueOf(split[0]), split[split.length - 1]);
}
});
}
}
catch (IOException e) {
e.printStackTrace();
}
return processes;
}
This hasn't been tested on Windows, but it should work. It also hasn't been tested on literally anything else other than Linux, but I hope this serves as a helpful method for others to work off of.

Related

How to implement Word2Vec in Java?

I installed word2Vec using this tutorial on by Ubuntu laptop. Is it completely necessary to install DL4J in order to implement word2Vec vectors in Java? I'm comfortable working in Eclipse and I'm not sure that I want all the other pre-requisites that DL4J wants me to install.
Ideally there would be a really easy way for me to just use the Java code I've already written (in Eclipse) and change a few lines -- so that word look-ups that I am doing would retrieve a word2Vec vector instead of the current retrieval process I'm using.
Also, I've looked into using GloVe, however, I do not have MatLab. Is it possible to use GloVe without MatLab? (I got an error while installing it because of this). If so, the same question as above goes... I have no idea how to implement it in Java.
What is preventing you from saving the word2vec (the C program) output in text format and then read the file with a Java piece of code and load the vectors in a hashmap keyed by the word string?
Some code snippets:
// Class to store a hashmap of wordvecs
public class WordVecs {
HashMap<String, WordVec> wordvecmap;
....
void loadFromTextFile() {
String wordvecFile = prop.getProperty("wordvecs.vecfile");
wordvecmap = new HashMap();
try (FileReader fr = new FileReader(wordvecFile);
BufferedReader br = new BufferedReader(fr)) {
String line;
while ((line = br.readLine()) != null) {
WordVec wv = new WordVec(line);
wordvecmap.put(wv.word, wv);
}
}
catch (Exception ex) { ex.printStackTrace(); }
}
....
}
// class for each wordvec
public class WordVec implements Comparable<WordVec> {
public WordVec(String line) {
String[] tokens = line.split("\\s+");
word = tokens[0];
vec = new float[tokens.length-1];
for (int i = 1; i < tokens.length; i++)
vec[i-1] = Float.parseFloat(tokens[i]);
norm = getNorm();
}
....
}
If you want to get the nearest neighbours for a given word, you can keep a list of N nearest pre-computed neighbours associated with each WordVec object.
Dl4j author here. Our word2vec implementation is targeted for people who need to have custom pipelines. I don't blame you for going the simple route here.
Our word2vec implementation is meant for when you want to do something with them not for messing around. The c word2vec format is pretty straight forward.
Here is parsing logic in java if you'd like:
https://github.com/deeplearning4j/deeplearning4j/blob/374609b2672e97737b9eb3ba12ee62fab6cfee55/deeplearning4j-scaleout/deeplearning4j-nlp/src/main/java/org/deeplearning4j/models/embeddings/loader/WordVectorSerializer.java#L113
Hope that helps a bit

Using ini4j to edit Windows registry

Im currently working on a java program and I need to read/write to the registry. i've looked at several API's to do this and I found ini4j (ini4j Project Page). I also need to edit ini files so I like this solution because it does both. I'm curious if anybody has tried ini4j in this type of scenario?
I found a better solution for reading/writing to the registry without the need for ini4j or passing arguments to the command line. I use JNA quite a lot in my program so I figured that it would be easier to use native library calls instead of including an additional library to do this for me. Here is an example from my project were I search through the registry looking for a specific key. The specific key is also dependent on whether or not the OS is x64 or x86.
public static String GetUninstallerPath() {
try {
//if (logger.IsInfoEnabled) logger.Info("GetUninstallerPath - begin");
String uninstallerPath = null;
try {
String vncDisplayName = "UltraVNC";
String subkey32 = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
String subkey64 = "Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
boolean is64Bit = Platform.is64Bit();
String[] key;
if (is64Bit) {
key = Advapi32Util.registryGetKeys(WinReg.HKEY_LOCAL_MACHINE,
subkey64);
} else {
key = Advapi32Util.registryGetKeys(WinReg.HKEY_LOCAL_MACHINE,
subkey32);
}
if (key != null) {
for (String nextSubkeyName : key) {
TreeMap<String, Object> subKey = Advapi32Util.registryGetValues(
WinReg.HKEY_LOCAL_MACHINE,
subkey64 + "\\" + nextSubkeyName);
Object value = subKey.get("DisplayName");
Object path = null;
if (value != null) {
if (value.toString().startsWith(vncDisplayName)) {
path = subKey.get("UninstallString");
if (path != null) {
uninstallerPath = path.toString().trim();
}
}
}
}
}
}
catch (Exception ex) {
System.err.println(ex.getMessage());
}
return uninstallerPath;
}
}
I use objects to initially store the key values because I kept getting NullPointerExceptions. Feel free to provide another solution.
Unfortunately your test for 64 bits using Platform.is64Bit() doesn't do what you think it does...
It tells you if your JVM is 32 bits or 64 bits, not if your Windows is 32 bits or 64 bits...
The only reason why your code seems to work as intended is because the Windows registry redirector takes care of the "magic" involved (accessing the right registry key) for you...
When your code runs on a 32 bits JVM on a 64 bits Windows Platform.is64Bit() returns false and you are using subkey32 (ie "Software\Microsoft\Windows\CurrentVersion\Uninstall").
I unfortunately did the same mistake as you and released a program with the same erroneous test after readings threads such as yours which is why I am now posting this even though this thread is several years old.

Java Preferences and Internationalization (i18n)

The Java tutorials recommend using the Preferences API over Properties files.
Properties files and ResourceBundles are the recommended way to handle Internalization requirements in applications.
I am considering using both for a desktop application that will display preferences in a locale specific way.
Can anyone point out problems with this approach?
Maybe I should just use Properties files period?
I am considering using both for a desktop application that will display preferences in a locale specific way.
OK, so what you want is translated configuration file in form of:
some_translated_key=some_value
Well, unless you want to support MUI at some point it should not be a big deal. However, if you do, so that different users on the same computer could use different languages, or user might be able to switch language, you would have troubles in matching key to a property. You would have to scan all translations while reading the key, and you would surely end up with multiple entries for the same key. How to resolve that? Well, that's a good question.
From my experience, configuration files should be language-independent (neutral culture) and should never be edited by hand (that is translating keys doesn't really matter).
I thought there could be a problem with character encoding, but following code snippet works without an issue (files are UTF-8 encoded):
public class Main {
private static final String FILE_NAME = "i18ned.properties";
private File propertiesFile;
private Properties properties;
public Main() {
properties = new Properties();
propertiesFile = new File(FILE_NAME);
if (propertiesFile.exists()) {
try {
properties.load(new BufferedReader(new FileReader(
propertiesFile)));
} catch (FileNotFoundException e) {
// not likely, but should be logged either way
} catch (IOException e) {
// logger should be used instead
e.printStackTrace();
}
}
}
public void saveProperties() {
try {
properties
.store(new BufferedWriter(new FileWriter(propertiesFile)), "");
} catch (IOException e) {
// oops, use logger instead
e.printStackTrace();
}
}
public static void main(String[] args) {
Main main = new Main();
main.storeSome();
main.readSome();
}
private void readSome() {
String highAsciiKey = "żółć";
String value = properties.getProperty(highAsciiKey);
System.out.println(value);
}
private void storeSome() {
String highAsciiKey = "żółć";
String highAsciiValue = "łąkę";
properties.setProperty(highAsciiKey, highAsciiValue);
saveProperties();
}
}
Using resource bundle for localizing applications is the standard way in java. The problems of this way are:
there is no compile time check of number and type of parameters required by resource.
It is hard to hold files clean, e.g. there is no mechanism the helps to remove unused strings
It is hard to make all texts translated to all supported languages.
etc....
The probably better internationalization mechanism is suggested by Google in their GWT. They generate class with method per string.
For example if you have text Hello, {0} they will generate method
String hello(String name);
So, you cannot pass neither 0 nor 2 arguments to this method. Only one.
This partially solves the second problem also. It is easier to see if method is not used in whole project. It does not solve the 3rd problem anyway.

Having trouble opening a file in Java

I am trying to open this file in java and i want to know what i am doing wrong. The in file lies in the same directory as my Java file, but i tried to open this with both netbeans and eclipse and it gave a file not found exception. Can someone help me open this file and read from it. I am really new to java files. Here is the code
import java.util.*;
import java.io.*;
public class Practice
{
public static void main(String[] args)throws IOException
{
FileReader fin = new FileReader("anagrams.in");
BufferedReader br = new BufferedReader(fin);
System.out.println(fin);
String string = "Madam Curie";
String test = "Radium came";
string = string.toLowerCase();
test = test.toLowerCase();
string = string.replaceAll("[^a-zA-Z0-9]+", "");
test = test.replaceAll("[^a-zA-Z0-9]+", "");
char[] array = string.toCharArray();
char[] array2 = test.toCharArray();
boolean flag = false;
HashMap hm = new HashMap();
for(int i = 0; i < array.length; i++)
{
hm.put(array[i], array[i]);
}
for(int i = 0; i < array2.length; i++)
{
if(hm.get(array2[i]) == null || test.length() != string.length())
{
flag = false;
i = array2.length;
}
else
{
flag = true;
}
}
System.out.println(flag);
}
}
A few tips:
Abide to proper code indentation
If you're using an IDE like Eclipse, it can automatically correct indentation for you
Develop debugging instinct
Try to get what the current working directory is, and list all the files in it
Refactor repetitive code
Writing paired statements like you did should immediately raise red flags
Effective Java 2nd Edition
Item 23: Don't use raw types in new code
Item 52: Refer to objects by their interfaces
Item 46: Prefer for-each loops to traditional for loops
Use sensible variable names
With regards to 2, try something like this:
public static void listDir() {
File current = new File(".");
System.out.println(current.getAbsolutePath());
for (String filename : current.list()) {
System.out.println(filename);
}
}
Then in your main, simply call listDir before everything else, and see if you're running the app from the right directory, and if there's a "anagrams.in" in the directory. Note that some platforms are case-sensitive.
With regards to 3 and 4, consider having a helper method like this:
static Set<Character> usedCharactersIn(String s) {
Set<Character> set = new HashSet<Character>();
for (char ch : s.toLowerCase().toCharArray()) {
set.add(ch);
}
return set;
}
Note how Set<E> is used instead of Map<K,V>. Looking at the rest of the code, you didn't seem to actually need a mapping, but rather a set of some sort (but more on that later).
You can then have something like this in main, which makes the logic very readable:
String s1 = ...;
String s2 = ...;
boolean isNotQuiteAnagram = (s1.length() == s2.length()) &&
usedCharactersIn(s1).containsAll(usedCharactersIn(s2));
Note how variables are now named rather sensibly, highlighting their roles. Note also that this logic does not quite determine that s1 is an anagram of s2 (consider e.g. "abb" and "aab"), but this is in fact what you were doing.
Since this looks like homework, I'll leave it up to you to try to figure out when two strings are anagrams.
See also
Java Coding Conventions
Java Language Guide/For-each loop
Java Tutorials/Collections Framework
Related questions
Why doesn't Java Map extends Collection?
Make sure that the file lies in the same directory as your .class file. It doesn't matter if it is in the same as your .java file or not.
Other than that, the only problem I can see is in your indentation, which doesn't matter.
The normal practice is to put resources in the runtime classpath or to add its path to the runtime classpath so that you can get it by the classloader. Using relative paths in Java IO is considered poor practice since it breaks portability. The relative path would be dependent on the current working directory over which you have totally no control from inside the Java code.
After having placed it in the classpath (assuming that it's in the same folder as the Java class itself), just do so:
BufferedReader reader = null;
try {
InputStream input = Practice.class.getResourceAsStream("anagrams.in");
reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); // Or whatever encoding it is in.
// Process it.
// ...
} finally {
if (reader != null) try { reader.close(); } catch (IOException ignore) {}
}
Closing in finally is by the way mandatory to release the lock on the file after reading.
Put the anagrams.in file in the same location as the .class file. Then you will be able to read the file. And this should help you get some links on how to read from files in Java.

Listing files in Java without using java.io

how to list files and directories in current directory without using java.io.*?
This is actually possible without having to write any JNI or make any Runtime calls.
import java.net.URL;
import sun.net.www.content.text.PlainTextInputStream;
public class NoIO {
public static void main(String args[]) {
NoIO n = new NoIO();
n.doT();
}
public void doT() {
try {
//Create a URL from the user.dir (run directory)
//Prefix with the protocol file:/
//Users java.net
URL u = new URL("file:/"+System.getProperty("user.dir"));
//Get the contents of the URL (this basically prints out the directory
//list. Uses sun.net.www.content.text
PlainTextInputStream in = (PlainTextInputStream)u.getContent();
//Iterate over the InputStream and print it out.
int c;
while ((c = in.read()) != -1) {
System.out.print((char) c);
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
It's amazing what a little thought and boredom will do (and an inability to jump to hasty conclusions (where there's a will, there's a way)).
You could probably also do it using the ClassLoader, by overriding it, at some point Java has to iterate over all the files in the classpath, by hooking at that point you can print out all the files that it tries to load without using any kind of java.io.*.
After some investigation I don't think this is possible very easily, certainly not for a homework assignment unless it's some kind of RE'ing assignment or Forensics assignment.
You can use Runtime.getRuntime().exec():
String[] cmdarray;
if (System.getProperty("os.name").startsWith("Windows")) {
cmdarray = new String[] { "cmd.exe", "/c", "dir /b" };
} else { // for UNIX-like systems
cmdarray = new String[] { "ls" };
}
Runtime.getRuntime().exec(cmdarray);
Thanks to #Geo for the Windows commands.
You could use JNA to make native calls to the underlying OS.
As an exercise in hard work it might be a worth while.
Another option is writing OS specific code in C and accessing it via JNI. But once again. Why do you want this?

Categories

Resources