Vicky
Vicky

Reputation: 17385

splitting string in java into fixed length chunks

I have seven strings in a program named string1 through string7.

The size of each of the string will be 30 characters.

I will get a input string of unknown length.

I have to split this input string in 30 char strings and then set first substring into string1, 2nd in string2 and so on until possible. If input string is greater then 210 characters then remaining string at the end will be ignored.

How to handle the case when the input string is of size smaller then 210 char.

For e.g. 145 in which case string1 through string4 will be full and string5 will be made of remaining 15 char.

How to handle this nicely ?

I can do it reading char by char and putting first 30 char and string1, next in string2, etc until all char are consumed.

But is there a better way to do this ?

Upvotes: 11

Views: 42805

Answers (11)

fnordhusen
fnordhusen

Reputation: 161

Using Streams, this one should do it in an easy way:

  private static Stream<String> splitToFixedSize(String input, int maxSize) {
    var noOfChunks = (int) Math.ceil((float) input.length() / maxSize);

    return IntStream.range(0, noOfChunks).mapToObj(i -> {
      var start = i * maxSize;
      var end = Math.min((i + 1) * maxSize, input.length());
      return input.substring(start, end);
    });
  }

Upvotes: 0

CodeToLife
CodeToLife

Reputation: 4171

private   Collection<String> splitStringBySize(String strPrm, int sizePrm) {
    ArrayList<String> splitLcl = new ArrayList<>();
    int lLcl=strPrm.length();
    int quantityLcl = lLcl / sizePrm;
    for (int  i = 0; i <  quantityLcl; i++) {
        splitLcl.add(strPrm.substring(i * sizePrm,(i+1) * sizePrm ));
    }
    int tailLcl = lLcl % sizePrm;

    if(tailLcl>0){
        splitLcl.add(strPrm.substring(lLcl-tailLcl,lLcl));
    }
    return splitLcl;
}

Upvotes: 0

Louis Wasserman
Louis Wasserman

Reputation: 198221

If you can use third-party libraries, with Guava this is just

Iterable<String> chunks = Splitter.fixedLength(30).split(string);

This can be converted to a List<String> with e.g. Lists.newArrayList.

(Disclosure: I contribute to Guava.)

Upvotes: 20

Justin Bahn
Justin Bahn

Reputation: 11

I ran into an issue with a specific usage of this technique. A user was copy/pasting M$ Word content into an HTML field that eventually was picked up by this technique to be split into multiple database fields.

The technique broke against M$ Word's use of carriage returns and other ASCII characters. The REGEX would split off each carriage return instead of a specified number of characters. To correct the issue, I modified Michael Besteck's code to the following:

Matcher m = Pattern.compile(".{1,30}", Pattern.DOTALL).matcher(s);
String s1 = m.find() ? s.substring(m.start(), m.end()) : "";
String s2 = m.find() ? s.substring(m.start(), m.end()) : "";
String s3 = m.find() ? s.substring(m.start(), m.end()) : "";
String s4 = m.find() ? s.substring(m.start(), m.end()) : "";
String s5 = m.find() ? s.substring(m.start(), m.end()) : "";
String s6 = m.find() ? s.substring(m.start(), m.end()) : "";
String s7 = m.find() ? s.substring(m.start(), m.end()) : "";

This accounts for the ASCII characters correctly.

Upvotes: 1

Matthias
Matthias

Reputation: 188

private static Collection<String> splitStringBySize(String str, int size) {
    ArrayList<String> split = new ArrayList<>();
    for (int i = 0; i <= str.length() / size; i++) {
        split.add(str.substring(i * size, Math.min((i + 1) * size, str.length())));
    }
    return split;
}

Upvotes: 9

Jose Tepedino
Jose Tepedino

Reputation: 1584

How about using a char array for splitting the string, create a general-use method receiving the chunk size and maximum size to consider, and returning a String array?

public class SplitStringIntoFixedSizeChunks {

    public static String[] Split(String text, int chunkSize, int maxLength) { 
        char[] data = text.toCharArray();       
        int len = Math.min(data.length,maxLength);
        String[] result = new String[(len+chunkSize-1)/chunkSize];
        int linha = 0;
        for (int i=0; i < len; i+=chunkSize) {
            result[linha] = new String(data, i, Math.min(chunkSize,len-i));
            linha++;
        }
        return result;
    }

    public static void main(String[] args) { 
        String x = "flskdafsld~fdsakçkçfsda sfdaldsak~çfdskkfadsçlkçfldskçlflçfdskçldksçlkfdslçakafdslçdsklçfdskçlafdskçkdfsçlkfds~çlkfasdçlçfdls~kçlf~dksçlsakdçlkfç";
        System.out.println("x length: "+x.length());
        String[] lines = Split(x, 30, 210);
        for (int i=0; i < lines.length; i++) {
            System.out.println("lines["+i+"]: (len: "+lines[i].length()+") : "+lines[i]);
        }
    }
}

This example results:

x length: 145
lines[0]: (len: 30) : flskdafsld~fdsakçkçfsda sfdald
lines[1]: (len: 30) : sak~çfdskkfadsçlkçfldskçlflçfd
lines[2]: (len: 30) : skçldksçlkfdslçakafdslçdsklçfd
lines[3]: (len: 30) : skçlafdskçkdfsçlkfds~çlkfasdçl
lines[4]: (len: 25) : çfdls~kçlf~dksçlsakdçlkfç

Upvotes: 2

peddn
peddn

Reputation: 98

import java.util.ArrayList;


public class Test {

public static void main(String[] args) {

    // your input
    String input = "";

    // strings 1-7 as array list
    ArrayList<String> results = new ArrayList<String>();

    int length;

    if(input.length() > 210) {

        length = 210;

    } else {

        length = input.length();

    }

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

        if((length - (i + 30)) > 0) {

            results.add(input.substring(i, i + 30));

        } else {

            results.add(input.substring(i, length));

        }

    }

    for(int a = 0; a < results.size(); a++) {

        System.out.println("size: " + results.get(a).length() + " content: " + results.get(a));

    }

    }

    }

Upvotes: 0

Michael Besteck
Michael Besteck

Reputation: 2423

Since your Strings are not in an array or List you need to assign them explicitely.

    Matcher m = Pattern.compile(".{1,30}").matcher(s);
    String s1 = m.find() ? s.substring(m.start(), m.end()) : "";
    String s2 = m.find() ? s.substring(m.start(), m.end()) : "";
    String s3 = m.find() ? s.substring(m.start(), m.end()) : "";
    String s4 = m.find() ? s.substring(m.start(), m.end()) : "";
    String s5 = m.find() ? s.substring(m.start(), m.end()) : "";
    String s6 = m.find() ? s.substring(m.start(), m.end()) : "";
    String s7 = m.find() ? s.substring(m.start(), m.end()) : "";

Upvotes: 4

Vicky
Vicky

Reputation: 17385

This is what I did. Seems to work. Please comment if I am wrong anywhere:

package com.mypackage;

import java.util.ArrayList;
import java.util.List;


public class TestClass {

public static List<String> splitEqually(final String text, final int size) {

    List<String> ret = new ArrayList<String>((text.length() + size - 1) / size);
    for (int start = 0; start < text.length(); start += size) {

        if (start + size > 0) {

            String temp = text.substring(start, Math.min(text.length(), start + size));
            int length = temp.length();

            for (int i = 0; i < (size - length); i++) {
                temp = temp + " ";
            }

            ret.add(temp);

        } else {
            ret.add(text.substring(start, Math.min(text.length(), start + size)));
        }


    }
    return ret;
}

public static void main(final String args[]) {

    String input = "hello wo";

    String str1, str2, str3, str4, str5;

    List<String> result = TestClass.splitEqually(input, 3);

    try {
        str1 = result.get(0);
        System.out.println("1: " + result.get(0));

        str2 = result.get(1);
        System.out.println("2: " + result.get(1));

        str3 = result.get(2);
        System.out.println("3: " + result.get(2));

        str4 = result.get(3);
        System.out.println("4: " + result.get(3));

        str5 = result.get(4);
        System.out.println("5: " + result.get(4));

    } catch (IndexOutOfBoundsException e) {
    }

}
}

Upvotes: 0

Theja
Theja

Reputation: 762

This might help you.

public static void main(String args[]) throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String st = br.readLine();
            int len = st.length();
            String[] str = new String[7];
            len=len/30;
            int i=0;
            for(; i<7 && i<len; i++  ){
                str[i] = st.substring(30*i, 30*(i+1));
                System.out.println(str[i]);
            }
            if(i!=7){
                str[i] = st.substring(30*i, st.length());
                System.out.println(str[i]);
                }

        }

Upvotes: 1

npinti
npinti

Reputation: 52185

This is something which should work:

 String str = "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111";
        if (str.length() > 210)
        {
            str =  str.substring(0, 209);
        }
        String newStr  = str.replaceAll("(.{30})", "$1|");
        System.out.println(newStr);
        String[] newStrings = newStr.split("\\|");

What it does is that it takes the given string and at every 30 characters, it throws in a seperator. In this case, I am assuming that you have an idea of what will the user enter and what not so that you can throw in a seperator (or group of seperators) which the user will not enter. Once I do that, I split the string using the seperator I have just added.

Upvotes: 2

Related Questions