views:

226

answers:

5

Hi, I'm just stuck with a problem (maybe Simple). But I can't figure out how to solve it, maybe someone of you can help me.

I receive as input an string with this format:

D0001001.tiff

And I need to return the next one (given that the next one is the received incremente by factor of one.

Input: D0001001.tiff Output: D0001002.tiff

No zero can be missed. The method I have is this (without refactoring ;) )

private String getNextImageName(String last_image_name)
{
    // Splits the name from the start to the . (not inclusive)
    String next_name = last_image_name.substring(0, last_image_name.indexOf(".") - 1 );
    String next_extension = last_image_name.substring(last_image_name.indexOf(".") + 1, last_image_name.length() - 1 );

    String next_name_without_D = next_name.substring(1);
    int next_name_withoud_D_value = Integer.parseInt( next_name_without_D );

    // Increments to get the new name
    next_name_withoud_D_value++;

    String full_next_name = "D" + next_name_withoud_D_value + "." + next_extension;

    return full_next_name;
}

But the results are not as the expected:

Input: D0002001.tiff Output: D201.tif

--

There are some constraints, for example, the number of 0 can't disappear because eventually the file can hace different number:

D0001001.tiff or D9999999001.tiff

but the second one goes only through 999

D0001001.tiff to D0001999.tiff

By this moment I'm so stuck that I can't even think...

Thanks

+1  A: 

If would use Regexp instead to make the code a bit cleaner:

private static final Pattern imgPattern = Pattern.compile("(.*)(\\d*)\\.(.*)");

public static String getNextImageName(String last) {
  // The pattern captures the numerical value and the extension
  Matcher matcher = imgPattern.matcher(last);
  if (!matcher.matches()) {
    throw new IllegalArgumentExecption("Not image pattern: " + last);
  }

  String prefix = matcher.group(1);
  String num = matcher.group(2);
  int numVal = Integer.value(num);
  String ext = matcher.group(3);

  return String.format("%s%0" + num.length() + "d.%s",
                prefix, numVal + 1, ext);
}

A couple of comments:

  1. Lookup Regexp specification to understand patterns and captures. The given pattern basically "returns" the numberical value and the extension

  2. String.format() can format numbers and inserts 0 as pad as well. String.format("%02d, 1) returns "01" while String.format(%02d, 200) returns "200".

notnoop
Throwing an Error seems pretty intense for a bad input. Why not IllegalArgumentException?
erickson
Thanks msaeed. It works perfectly. I don't even understand the code. But this afteernoon I´ll start to study regex. As it seems is very powerfull.
Sheldon
Horrible code compared to the #1 answer by penpen. Why do people jump to Regex for solutions like this?
Bill K
@erickson, thanks. `IllegalArgumentException` is better
notnoop
@Bill_K, penpen solution is the last line in my answer, you still need to parse the number and extension. Regexp is good for that
notnoop
+1  A: 
private static final Pattern p = Pattern.compile("D([0-9]+)(\\..+)");

private String getNextImageName(String previous)
{
  Matcher m = p.matcher(previous);
  if (!m.matches())
    throw new IllegalArgumentException("Invalid name: " + previous);
  String number = m.group(2);
  String ext = m.group(2);
  String next = String.valueOf(Integer.parseInt(number) + 1);
  int pad = Math.max(number.length() - next.length(), 0);
  StringBuilder buf = new StringBuilder(1 + number.length() + ext.length());
  buf.append('D');
  while (pad-- > 0)
    buf.append('0');
  buf.append(next);
  buf.append(ext);
  return buf.toString():
}
erickson
+3  A: 

String.format can do the trick for the padding part, for instance:

System.out.println(String.format("D%07d", 10));

gives

D0000010
penpen
The size of number is not fixed. Good hint though
notnoop
A: 
public String getNextImageName(String s) {
    int t = Integer.parseInt(s.substring(1,8));
    return new Formatter().format("D%07d.tiff", (t + 1) % 2000).toString();
}

I wasn't sure if you were saying the numbers wrapped at 1999, if they don't, you should take out the % 2000.

DigitalRoss
The problem is that as I mention, the number of characters within the name is not fixed. But that class is very useful.
Sheldon
+1  A: 
import static org.apache.commons.lang.StringUtils.*;
import static java.lang.Long.*;
import static java.lang.String.*;

...

String fileName = "D0009999.tiff";

String numericPortion = substringBetween(fileName, "D", ".tiff");
int minimumNumberOfDigits = numericPortion.length();
long numericValue = parseLong(numericPortion);

String nextFileName = format("D%0" + minimumNumberOfDigits + "ds.tiff", ++numericValue);
SingleShot
this is another elegant solution. And I understand it :D Cool SingleShot
Sheldon
Nice solution. Solves this problem perfectly. Not quite robust though.
notnoop
Thanks msaeed. What do you mean by "not quite robust"? Lack of handling number format exceptions and such or something else? Thx.
SingleShot
This would fail if he got a 'jpeg' image or one that starts with `DMC` or any of the other common prefixes. Works great for this limited use though.
notnoop