Умный способ объединить несколько строк в одну строку, которая может быть позже разделена на исходные строки? - PullRequest
0 голосов
/ 15 марта 2012

При условии отсутствия ограничений на символы, которые можно использовать в отдельных строках, и строки могут быть пустыми.

Edit:

Похоже, правильный способ сделать это - использовать разделитель и избежать появления этого разделителя, который уже существует в любой из отдельных строк. Ниже моя попытка этого, которая, кажется, работает. Пропустили ли какие-либо дела, которые сломают его?:

public static void main(String args[])
{
    Vector<String> strings = new Vector<String>();
    strings.add("abab;jmma");
    strings.add("defgh;,;");
    strings.add("d;;efgh;,;");
    strings.add("");
    strings.add("");
    strings.add(";;");
    strings.add(";,;");


    String string = combine(strings);
    strings= separate(string);
    System.out.println();
}

static String combine(Vector<String> strings)
{
    StringBuilder builder = new StringBuilder();

    for(String string : strings)
    {
        //don't prepend a SEPARATOR to the first string
        if(!builder.toString().equals(""))
        {
            builder.append(";");
        }

        string = string.replaceAll(";", ",;");

        builder.append(string);
    }

    return builder.toString();
}

static Vector<String> separate(String string)
{
    Vector<String> strings = new Vector<String>();

    separate(string, strings, 0);

    return strings;
}

static void separate(String string, Vector<String> strings, int currIndex)
{
    int nextIndex = -1;
    int checkIndex = currIndex;

    while(nextIndex == -1 && checkIndex < string.length())
    {
        nextIndex = string.indexOf(';', checkIndex);
        //look back to determine if this occurance is escaped
        if(string.charAt(nextIndex - 1) == ',')
        {
            //this ones is escaped, doesn't count
            checkIndex = nextIndex + 1;
            nextIndex = -1;

        }
    }

    if(nextIndex == -1)
    {
        //no more remain  

        String toAdd = string.substring(currIndex, string.length());
        toAdd = toAdd.replaceAll(",;", ";");
        strings.add(toAdd);
        return;
    }
    else if(currIndex + 1 == nextIndex)
    {
        //empty string 

        strings.add("");
        separate(string, strings, nextIndex);
    }
    else
    {
        //there could be more

        String toAdd = string.substring(currIndex, nextIndex);
        toAdd = toAdd.replaceAll(",;", ";");
        strings.add(toAdd);
        separate(string, strings, nextIndex + 1);
    }
}

}

Ответы [ 5 ]

1 голос
/ 15 марта 2012

Возьмите ваш вектор строк и преобразуйте его в объект JSON и сохраните объект JSON.

(http://www.json.org/ и http://www.json.org/java/)

0 голосов
/ 15 марта 2012

Посмотрите на opencsv, если вы хотите использовать текст с разделителями. API довольно прост в использовании, и он заботится о работе с экранирующими кавычками и тому подобным. Тем не менее, он обрабатывает нулевые значения как пустые строки, поэтому вы можете получить a ,, c, если ваш ввод был {"a", null, "c"}. Если это неприемлемо, вы можете использовать распознаваемую строку и преобразовать ее позже.

char tokenSeparator = ',';
char quoteChar = '"';
String inputData[] = {"a","b","c"};

StringWriter stringWriter = new StringWriter();
CSVWriter csvWriter = new CSVWriter(stringWriter, tokenSeparator, quoteChar);
csvWriter.writeNext(inputData);
csvWriter.close();

StringReader stringReader = new StringReader(stringWriter.toString());
CSVReader csvReader = new CSVReader(stringReader, tokenSeparator, quoteChar);
String outputData[] = csvReader.readNext();
0 голосов
/ 15 марта 2012

Вы можете иметь один и тот же текст в двух строках кода, используя Google Guava библиотека (классы Splitter и Joiner).

public String combine(Collection<String> strings) {
    return Joiner.on("yourUniqueSeparator").join(strings);
}

public Iterable<String> separate(String toSeparate) {
    return Splitter.on("yourUniqueSeparator").split(toSeparate);
}
0 голосов
/ 15 марта 2012

С помощью своего кода вы можете восстановить пустые строки, используя версию с двумя аргументами split:

String[] separate(String string)
{
    return string.split(SEPARATOR, -1);
}

Если вы действительно не можете делать предположений относительно содержимого строки, единственный способ сделать этоправильно, путем экранирования последовательности разделителя (который затем может быть одним символом), где бы он ни находился в исходной строке (строках).Очевидно, что если вы избежите последовательности разделителя, вам нужно удалить результат после разделения.(Механизм escape, вероятно, потребует как минимум еще одного дополнительного escape / unescape.)

EDIT

Вот пример (в стиле XML) экранирования и эскапинга.Предполагается, что последовательность-разделитель "\u0000" (один символ NULL).

/** Returns a String guaranteed to have no NULL character. */
String escape(String source) {
    return source.replace("&", "&amp;").replace("\u0000", "&null;");
}

/** Reverses the above escaping and returns the result. */
String unescape(String escaped) {
    return source.replace("&null;", "\u0000").replace("&amp;", "&");
}

Возможны многие другие варианты.(Важно, чтобы замены при удалении были в обратном порядке по сравнению с заменами, использованными для выхода.) Обратите внимание, что вы все равно можете использовать String.split() для разделения компонентов.

0 голосов
/ 15 марта 2012

Вы можете создать класс, который будет хранить отдельные строки внутри, а затем выводить объединенную версию строк при вызове toString. Возвращение исходных строк тривиально, поскольку они уже хранятся отдельно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...