2

Update:

There were some great solutions, but I realized that there is a problem in my premise: It seems that the rt.exec will not reach back to the java code once the process has been executed. Thank you for all your help!


I want to take a screencap every second programmatically and the title of each screencap should be the timestamp. I'm using vlc to achieve this.

    starttime = System.nanoTime();
    screencapProcess = rt.exec("C:\\VLC\\vlc screen:// --dshow-vdev=screen-capture-recorder --dshow-fps=1 -I dummy --dummy-quiet --rate=1 --video-filter=scene --vout=dummy --scene-format=jpg --scene-ratio=1 --scene-prefix=snap --scene-path=" + path +" --scene-prefix="+ "ScreenCapAt" +   ( String.valueOf(((long)System.nanoTime() - starttime)).substring(9, 14))+" vlc://quit ");

The relevant part is:

    String.valueOf(((long)System.nanoTime() - starttime)).substring(9, 14))

This cause an index out of bounds exception for nanoTimes less that 1.

I can't declare "System.nanoTime() - starttime" as a variable outside this line to get it's length since that would change my times.

Is there a way to get the last 5 digits of this undeclared variable of unknown length on one line?

This answer needs to fit in my rt.exec line.

Some thoughts:

  • Bitwise shifting and masking.
  • Piping into my .exec
  • postprocessing
  • Creating a new class
  • Calling System.nanoTime() - starttime again would increase the time of the operation and throw off my calculations.
  • Is there a better way to atomically get the time of capture?
Tai
  • 490
  • 4
  • 18

4 Answers4

1

I think you're going to have to do it on more than one line. I don't see a way of doing it without evaluating the strings length. This is the best I could come up with:

String diff = ""+((long)System.nanoTime() - starttime);
String lastfive = diff.substring(Math.max(0, diff.length() - 5));

UPDATE: Found a way to do it all on one line:

String lastFive = (""+((long)System.nanoTime() - starttime)).replaceAll("(.*)(\\d{5}$)","$2");
Moob
  • 14,420
  • 1
  • 34
  • 47
  • This will not work in my rt.exec line since it is more than one line. – Tai Nov 11 '13 at 07:53
  • Updated my answer to use a regex to keep just the last 5 chars. – Moob Nov 11 '13 at 11:40
  • Nice work! Although I realized there is a problem in the way I am taking the screencaps so I'll have to rewrite it anyway. Out of curiosity, how would I take the first 5? – Tai Nov 11 '13 at 11:54
  • Flip the regex round and take the first match rather than the second: `...replaceAll("(\\d{5})(.*)$","$1")` – Moob Nov 11 '13 at 12:01
1

In 1 line(except the declaration of calc):

float calc;
String diff = String.valueOf((calc = (long)System.nanoTime() - starttime)).substring(Math.max(0, String.valueOf(calc).length() - 5));
Leo Pflug
  • 544
  • 3
  • 15
  • This looks good! I'm getting answers like 81E8, but that can be fixed by converting to seconds. Once I play around with it a little more, I'll comment a version that fits my needs better. – Tai Nov 11 '13 at 08:16
  • Also do not forget, that I'm using float calc; and long for System.nanoTime() change those types according to your needs. – Leo Pflug Nov 11 '13 at 08:29
  • Also do not forget to check if it's greater than 4 characters. This can also be done in 1 line. – Leo Pflug Nov 11 '13 at 08:32
  • I'm checking by changing the first parameter of Math.max. System.out.println("test3 " + String.valueOf((calc = (float) (((long)System.nanoTime() - starttime)/1000000000.00))).substring(Math.max(4, String.valueOf(calc).length() - 5))); works well. BUT when I run it in my rt.exec I get different results like ScreenCapAt0.00138500001.jpg. I'm trying a hybrid solution now where I put the line in a function and call it in my rt.exec line. Not ideal (and definitely not one line) but let's get something working and move from there :) – Tai Nov 11 '13 at 08:47
  • Okay. But what's so wrong with that result? How should it be? – Leo Pflug Nov 11 '13 at 08:53
  • That result should have been 00001.jpg - instead of 0.00138500001.jpg. I wrote your code in a function and added a print statement. However, it only prints once (but what it does print is a correct value). I think the problems I'm having now has to do with vlc or command line rather than your code. – Tai Nov 11 '13 at 09:11
  • I understand now. The code is NOT recompiling at each screenshot. The code was giving me 0.001385 (I was using the first 8 for testing instead of the last 5) and vlc tacked on 00001 at the end. Thus resulting in 0.00138500001.jpg, 0.00138500030.jpg, etc. No fault of yours, but problematic for me. I think that means that I need to take screencaps differently. – Tai Nov 11 '13 at 09:25
0

Try this:

 String diff=""+ ((long)System.nanoTime() - starttime);

 if(diff.length() >4){// Check if diff length is less than 5
   String lastFive=diff.substring(diff.length()-5, diff.length());
 }
Leo Pflug
  • 544
  • 3
  • 15
Masudul
  • 21,823
  • 5
  • 43
  • 58
  • This will fail if the difference between System.nanoTime() and starttime is less than 10000, which I am guessing is his problem on the first iteration – Scary Wombat Nov 11 '13 at 07:34
  • This will not work in my rt.exec line since it is more than one line. – Tai Nov 11 '13 at 07:56
0

Try:

String diff=""+ ((long)System.nanoTime() - starttime));
String lastFive=  diff.length() > 4 ? 
                 diff.substring(diff.length()-5, diff.length()) : diff;

screencapProcess = rt.exec("C:\\VLC\\vlc screen:// --dshow-vdev=screen-capture-recorder --dshow-fps=1 -I dummy --dummy-quiet --rate=1 --video-filter=scene --vout=dummy --scene-format=jpg --scene-ratio=1 --scene-prefix=snap --scene-path=" + path +" --scene-prefix="+ "ScreenCapAt" +  lastfive +" vlc://quit ");

Update

If you want to recalculate the value then I suggest that you put it into a seperate function

    public static void main(String[] args) throws InterruptedException{ 

    long starttime = (long)System.nanoTime(); 
    Thread.sleep(1000); 
    System.out.println("test1 " + getLastFive (starttime)); 
    Thread.sleep(500); 
    System.out.println("test2 " + getLastFive (starttime)); 
    Thread.sleep(1000);
} 

static private String getLastFive (long starttime) {

    String diff=""+ ((long)System.nanoTime() - starttime); 
    String lastFive= diff.length() > 4 ? diff.substring(diff.length()-5, diff.length()) : diff; 
    return lastFive;

}
Scary Wombat
  • 44,617
  • 6
  • 35
  • 64
  • This will not work in my rt.exec line since it is more than one line. – Tai Nov 11 '13 at 07:55
  • use the variable lastfive in your rt.exec line. See my updated answer – Scary Wombat Nov 11 '13 at 07:57
  • Won't this give me the same name for each screencap? The rt.exec should give me 30 or so screencaps with different names. – Tai Nov 11 '13 at 08:01
  • every time the above block of code is called, `lastfive` will be re-evaulated and then passed into rt.exec. Why does it have to be on one line? – Scary Wombat Nov 11 '13 at 08:06
  • It is not re-evaluated. public static void main(String[] args) throws InterruptedException{ long starttime = (long)System.nanoTime(); float calc; Thread.sleep(1000); String diff=""+ ((long)System.nanoTime() - starttime); String lastFive= diff.length() > 4 ? diff.substring(diff.length()-5, diff.length()) : diff; System.out.println("test1 " + lastFive); Thread.sleep(500); System.out.println("test2 " + lastFive); Thread.sleep(1000);} output: test1 81090 test2 81090 – Tai Nov 11 '13 at 08:14
  • Will not work either since you're declaring starttime within the function itself, thus I'll get an answer under 1 second everytime. If I declared it outside the function it'd work though. Job reasonably done. – Tai Nov 11 '13 at 08:39
  • Look mate your question was originally about arrayIndexException - this has been fixed many times for you. – Scary Wombat Nov 11 '13 at 08:56
  • Please re-read the title of my post :) A separate function was a good idea and will get me what I want. BUT I asked for a one liner. I'd still prefer one. Even if I have an answer that will make my code work. I'm still curious about other/cleaner/faster ways of implementing it. – Tai Nov 11 '13 at 09:07
  • I have updated my answer. I believe that my answer with give you a cleaner and easier to read solution. Such trivial code does not need to be faster. As for one line, this does not give you cleaner or faster, just 'other' – Scary Wombat Nov 12 '13 at 00:04