tags:

views:

597

answers:

8

Hi All,

This is my first question in this forum... I have a file with numerous data fields (both numeric and characters) in the file. I want to delimit the file with set of delimiter length like 2,5,1,9,6 etc.

(Alternatively: I have a list of field lengths such as 2,5,1,9,6, and I want to insert comma delimiters in (a copy of) the source string after each field.)

For example, if my file is like this:

9483trdcvge245621jde

then I need to insert commas at 2,5,1,9,6 etc. and the output will be:

94,83trd,c,vge245621,jde,

I need to do this in JAVA

Please help me to solve this issue. Thanks in advance

+1  A: 

I think I don’t understand the question. Read the file, line by line, and insert commas into the string.

String newString = line.substring(0, firstComma) + "," + line.substring(firstComma + 1);

Of course this is terribly inefficient and can be optimized in numerous ways.

Bombe
I dunno exactly what the question looked like when you answered, but this does not represent a solution to the problem.
Jonathan Leffler
+7  A: 
if (myString.equals("9483trdcvge245621jde")) {
        myString = "94,83trd,c,vge245621,jde";
    }

Jokingly ;-)

I think something like this...

private static final int[] pos = {2, 5, 1, 9, 6};
private static final String DIV = ",";

public static String parse(String str) {
 int start = 0;
 StringBuilder sb = new StringBuilder();
 for (int i = 0; i < pos.length; i++) {
  if (i > 0) { 
   sb.append(DIV);
  }
  int end = start + pos[i];
  if (end <= str.length()) {
   sb.append(str.substring(start, end));
   start = end;
  } else {
   sb.append(str.substring(start));
  }

 }
 return sb.toString();
}
gedevan
You could remove the "if (i > 0)" bit by using a variable (I usually use 'pad') and setting pad = ""; before the loop, and setting it to "," (or DIV) at the end of the loop, and unconditionally including pad in the appended data.
Jonathan Leffler
+1  A: 

Assuming you have all these as Strings you can use String.substring(start, end). Then simply append + the substrings and commas together.

String data = "9483trdcvge245621jde";
String result = "";

result += data.substring(0,2) + ",";
result += data.substring(2, 7) + ",";
result += data.substring(7, 8) + ",";

etc...

Note: Using + to append string like this is very slow as it reallocates and moves data around each time. There are faster ways to concatenate Strings if speed is an issue.

Cogsy
Any good compiler will compile your code to using StringBuilders behind the scenes. In fact, I find '+' and '+=' more readable so I almost always prefer it (as a rule) over StringBuilder, except when doing a concat inside an iteration.
eljenso
Doesn't generalize well; I can see only the first number from the sequence 2,1,5,9,6 - so there isn't an obvious generalization of your code.
Jonathan Leffler
The sequence given has relative values from the previous comma (before the comma is inserted). 0-2, 2-7, 7-8 are the absolute ranges of this sequence.
Cogsy
+3  A: 

Read in the file as a StringBuilder then use something like this

StringBuilder sb = new StringBuilder(file); //The string builder
while (/*the string builder isn't finished*/)
{
  int position = ;//The position you want the comma at 2 or 4 or whatever
  sb.insert(position, ",");
}

Loop through as many times as needed.

Gareth
+1  A: 
String newString = "";
int[] positions = { 2, 5, 1, 9, 6 }; //etc
for (int i = 0; i > positions.length; i++) {
    String tempString = "";
    if (i == positions.length) { //for the last item
      tempString = oldString.substring(0, positions[i]);
    }
    else { //every item except the last item
      tempString = oldString.substring(0, positions[i]) + ",";
    }
    oldString = oldString.substring(positions[i]);
    newString += tempString;
}

Stored the positions in an array. Iterate through, adding the delimited strings to a new string and removing them from the old one. This might not be the best way, but its how I would do it. :P

Simon Hartcher
+2  A: 

I think i would do it this way

  • str being the input string
  • pos being the lengths of the parts after which we should put a comma

Code:

public static String partition(String str, int[] pos) {
    int oldPos = 0;
    StringBuilder builder = new StringBuilder(str.length() + pos.length);
    for(int len : pos) {
        builder.append(str.substring(oldPos, oldPos+len)).append(',');
        oldPos += len;
    }
    builder.append(str.substring(oldPos)).append(',');
    return builder.toString();
}
Johannes Schaub - litb
+1  A: 

Here's one solution:

package com.foo;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class Commafy {

    public static final String SEPARATOR = ",";

    private static void fail(String message) {
        System.err.println(message);
        System.exit(1);
    }

    private static int[] argsAsInts(String[] args) {
        if (args.length < 2) {
            fail("argument list of file name followed by field lengths is required");
        }
        int[] result = new int[args.length - 1];
        for (int i = 1; i < args.length; ++i) {
            try {
                result[i - 1] = Integer.parseInt(args[i]);
            } catch (NumberFormatException nfe) {
                fail("can't convert argument \"" + args[i] + "\" to integer");
            }
        }
        return result;
    }

    private static int[] partialSums(int[] lengths) {
        int[] result = new int[lengths.length];
        int start = 0;
        for (int i = 0; i < lengths.length; ++i) {
            result[i] = start;
            start += lengths[i];
        }
        return result;
    }

    private static int[] fieldsEndAt(int[] lengths, int[] starts) {
        int[] result = new int[lengths.length];
        for (int i = 0; i < lengths.length; ++i) {
            result[i] = starts[i] + lengths[i];
        }
        return result;
    }

    private static void process(
        String fileName, int[] starts, int[] ends
    ) throws IOException {
        BufferedReader br = new BufferedReader(
            new FileReader(fileName)
        );
        final int MIN_LENGTH = ends[ends.length - 1];
        String line = br.readLine();
        while (line != null) {
            if (line.length() < MIN_LENGTH) {
                System.err.println("short input line \"" + line +"\" skipped");
            } else {
                StringBuilder sb = new StringBuilder();
                String separate = "";
                for (int i = 0; i < starts.length; ++i) {
                    sb.append(separate).append(line.substring(starts[i], ends[i]));
                    separate = SEPARATOR;
                }
                System.out.println(sb.toString());
            }
            line = br.readLine();
        }
        br.close();
    }

    public static void main(String[] args) {
        int[] lengths = argsAsInts(args);
        int[] starts = partialSums(lengths);
        int[] ends = fieldsEndAt(lengths, starts);
        try {
            process(args[0], starts, ends);
        } catch (IOException e) {
            fail("I/O Exception while processing input");
        }
    }

}

Given a data file named data/fixedlengthdata.text containing:

9483trdcvge245621jde
9483trdcvge245621jdelong
9483trdcvge245621
9483trdcvge245621jde

and run with arguments of:

data/fixedlengthdata.text 2 5 1 9 3

it produces output of:

94,83trd,c,vge245621,jde
94,83trd,c,vge245621,jde
short input line "9483trdcvge245621" skipped
94,83trd,c,vge245621,jde

(where the third line above goes to stderr, of course.)

joel.neely
Super...Its works great..Thanks a lot man.....
A: 

This is probably the most bizzare requirement that I've ever seen, but anyway...

Psuedo-code

Collection<Integer> indexes; // initialized with indexes to add commas at 
StringBuilder bldr = new StringBuilder();

for (int i = 0; i < inString.length(); i++){

     bldr.append(inString.charAt(i));

     if (indexes.contains(i))
         bldr.append(",");

}

return bldr.toString();
bpapa