Как создать ридер из набора строк, не добавляя их сначала в StringBuilder? - PullRequest
1 голос
/ 19 декабря 2011

Представьте, что у меня есть несколько укусов, содержащих большое количество данных. Я должен передать их объединение методу в библиотеке, которую я использую. Я могу использовать для этого либо String, либо Reader.

  1. Присоединение к ним и передача строки не подлежит сомнению, так как я могу столкнуться с OOM. Нет возможности изменить -Xmx больше.
  2. Итак, есть ли способ создать считыватель, основанный на ВСЕХ моих строках без необходимости создания единственной строки и затем создания StringReader? Таким образом, я мог бы избежать ООМ

ps: я уже установил начальную емкость StringBuilder для своего первого варианта, но этого недостаточно, поэтому я ищу способ реализации 2.

Ответы [ 4 ]

2 голосов
/ 19 декабря 2011

Я не знаю встроенного способа или стороннего варианта, но не должно быть так сложно написать свой собственный Reader, используя список (или массив) строк.По словам читателя javadocs:

"Единственные методы, которые должен реализовывать подкласс, это read (char [], int, int) и close ()"

И close () должно быть простым,Так что вам действительно нужно реализовать только один метод read (char [], int, int).Сохраните указатели того, какую строку вы читаете, и где вы находитесь в строке.Остальное оставлено в качестве упражнения для Читателя.:-) И вы можете реализовать read () для скорости.

1 голос
/ 19 декабря 2011

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

Вы должны иметь возможность подкласса класса Reader , реализуя ваши собственные версии методов read (char, int, int) и close (). Метод read (..) может выглядеть примерно так, как показано ниже.

import java.io.IOException;
import java.util.Collection;
import java.io.*;

public class StringArrayReader extends Reader {
    private String[] strings;
    private int iString = 0, iCharInCurrentString = 0;

    public StringArrayReader(String[]strings) {
        this.strings = strings;
    }

    public StringArrayReader(Collection<String> strings) {
        this(strings.toArray(new String[strings.size()]));
    }



    @Override
    public int read(char[] buf, int off, int len) { 
        int iCurrentChar=0;
        while (iCurrentChar < len) {
            if (iCharInCurrentString < strings[iString].length()) {
                buf[iCurrentChar+off] = strings[iString].charAt(iCharInCurrentString);
            } else if (iString + 1 < strings.length) {
                iString++;
                iCharInCurrentString = 0;
                buf[iCurrentChar+off] = strings[iString].charAt(iCharInCurrentString);
            } else {   // current string is over and no more strings
                break;
            }
            iCurrentChar++;
            iCharInCurrentString++;
        }
        return iCurrentChar>0? iCurrentChar: -1;        
    }

    @Override
    public void close() throws IOException {
    }


    /* Demo */
    public static void main(String[] args) throws IOException {
        String s1 = "abcd";
        String s2 = "efgh";
        Reader r1 = new StringArrayReader(new String[]{s1,s2});
        int data = r1.read();
        while(data != -1){
            char dataChar = (char) data;
            System.out.println(dataChar);
            data = r1.read();
        }   
    }
}
1 голос
/ 19 декабря 2011

Вы можете реализовать собственный Reader, данные которого взяты из списка ваших строк.Ваш конкретный подкласс должен был бы реализовать только два метода: read(char[], int, int) и close().Когда ваш читатель закончит использовать одну строку, переходите к следующей.

0 голосов
/ 19 декабря 2011

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

Вы также можете увеличить объем памяти, используемой JVM, с опцией -Xmx (например, -Xmx2g, чтобы выделить до 2 ГБ памяти).

...