Итак, с функциональной шляпой, это выглядит тривиально .... но в C # есть некоторые существенные недостатки.
вы, вероятно, рассмотрите это как разворот IEnumerable (google it and you Вероятно, в некоторых документах Haskell, возможно, есть некоторые вещи F #, если вы знаете F #, косоглазие в документах Haskell, и это будет иметь смысл).
Unfold относится к fold ( «aggregate»), за исключением повторения через входной IEnumerable, он выполняет итерацию через выходные структуры данных (это аналогичная связь между IEnumerable и IObservable, на самом деле я думаю, что IObservable реализует «разворачивающийся», называемый generate ...)
в любом случае сначала вам нужен метод разворачивания, я думаю, что это работает;
static IEnumerable<T> Unfold<T, U>(Func<U, IEnumerable<Tuple<U, T>>> f, U seed)
{
var maybeNewSeedAndElement = f(seed);
return maybeNewSeedAndElement.SelectMany(x => new[] { x.Item2 }.Concat(Unfold(f, x.Item1)));
}
это немного тупо, потому что C # не реализует некоторые из функций, которые функциональные langauges принимают как должное ... но он в основном принимает семя, а затем генерирует ответ «Maybe» следующего элемента в IEnumerable и следующем семестре (возможно, не существует в C #, поэтому мы использовали IEnume (я не могу ругаться, чтобы подделать его), и конкатенирует остальную часть ответа (я не могу ручаться за сложность этого «O (n?)».
Как только вы это сделали,
static IEnumerable<IEnumerable<T>> Batch<T>(IEnumerable<T> xs, int n)
{
return Unfold(ys =>
{
var head = ys.Take(n);
var tail = ys.Skip(n);
return head.Take(1).Select(_ => Tuple.Create(tail, head));
},
xs);
}
все выглядит довольно чистым ... вы берете «n» элементы как «следующий» элемент в IEnumerable, а «tail» - это остальная часть необработанного списка.
, если в голове ничего нет ... вы закончили ... вы возвращаете «Nothing» (но поддельно как пустой IEnumerable>) ... иначе вы возвращаете элемент головы и хвост для обработки.
вы, вероятно, можете сделать это с помощью IObservable, вероятно, существует уже такой «пакетный» метод, и вы, вероятно, можете его использовать.
Если риск переполнения стека вызывает беспокойство (вероятно, он должен ), тогда вы должны реализовать в F # (и, вероятно, уже есть такая библиотека F # (FSharpX?)).
(Я только сделал некоторые рудиментарные тесты этого, так что могут быть нечетные ошибки в там).
Хороший способ сделать это использует свободное городское население Apache IOUtils
для копирования InputStream
в StringWriter
... что-то как
StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, encoding);
String theString = writer.toString();
, или даже
// NB: does not close inputStream, you'll have to use try-with-resources for that
String theString = IOUtils.toString(inputStream, encoding);
, С другой стороны, Вы могли использовать ByteArrayOutputStream
, если Вы не хотите смешивать свои Потоки и Писателей
Принятие во внимание регистрирует, нужно сначала добраться java.io.Reader
экземпляр. Это может тогда быть считано и добавлено к StringBuilder
(нам не нужно StringBuffer
, если мы не получаем доступ к нему в нескольких потоках, и StringBuilder
быстрее). Прием здесь - то, что мы работаем в блоках, и как таковой не нуждаются в других потоках буферизации. Размер блока параметризован для оптимизации производительности во время выполнения.
public static String slurp(final InputStream is, final int bufferSize) {
final char[] buffer = new char[bufferSize];
final StringBuilder out = new StringBuilder();
try (Reader in = new InputStreamReader(is, "UTF-8")) {
for (;;) {
int rsz = in.read(buffer, 0, buffer.length);
if (rsz < 0)
break;
out.append(buffer, 0, rsz);
}
}
catch (UnsupportedEncodingException ex) {
/* ... */
}
catch (IOException ex) {
/* ... */
}
return out.toString();
}
Apache палата общин позволяет:
String myString = IOUtils.toString(myInputStream, "UTF-8");
, Конечно, Вы могли выбрать другие кодировки символов помимо UTF-8.
Также см.: ( документация )
Во-первых, вы должны знать кодировку строки, которую вы хотите преобразовать. Поскольку java.io.InputStream
оперирует базовым массивом байтов, однако строка состоит из массива символов, который требует кодировки, например, UTF-8, JDK примет кодировку по умолчанию это взято из
System.getProperty("file.encoding","UTF-8");
byte[] bytes=new byte[inputStream.available()];
inputStream.read(bytes);
String s = new String(bytes);
. Если массив байтов inputStream
очень велик, вы можете сделать это в цикле.
Используйте:
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
public static String readInputStreamAsString(InputStream in)
throws IOException {
BufferedInputStream bis = new BufferedInputStream(in);
ByteArrayOutputStream buf = new ByteArrayOutputStream();
int result = bis.read();
while(result != -1) {
byte b = (byte)result;
buf.write(b);
result = bis.read();
}
return buf.toString();
}
Если вы не можете использовать Commons IO (FileUtils/IOUtils/CopyUtils), вот пример использования BufferedReader для чтения файла построчно:
public class StringFromFile {
public static void main(String[] args) /*throws UnsupportedEncodingException*/ {
InputStream is = StringFromFile.class.getResourceAsStream("file.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(is/*, "UTF-8"*/));
final int CHARS_PER_PAGE = 5000; //counting spaces
StringBuilder builder = new StringBuilder(CHARS_PER_PAGE);
try {
for(String line=br.readLine(); line!=null; line=br.readLine()) {
builder.append(line);
builder.append('\n');
}
}
catch (IOException ignore) { }
String text = builder.toString();
System.out.println(text);
}
}
Или, если вам нужна высокая скорость, я бы предложил вариант, предложенный Полом де Вризом (который позволяет избежать использования StringWriter (который внутри использует StringBuffer)):
public class StringFromFileFast {
public static void main(String[] args) /*throws UnsupportedEncodingException*/ {
InputStream is = StringFromFileFast.class.getResourceAsStream("file.txt");
InputStreamReader input = new InputStreamReader(is/*, "UTF-8"*/);
final int CHARS_PER_PAGE = 5000; //counting spaces
final char[] buffer = new char[CHARS_PER_PAGE];
StringBuilder output = new StringBuilder(CHARS_PER_PAGE);
try {
for(int read = input.read(buffer, 0, buffer.length);
read != -1;
read = input.read(buffer, 0, buffer.length)) {
output.append(buffer, 0, read);
}
} catch (IOException ignore) { }
String text = output.toString();
System.out.println(text);
}
}
Если вы используете Google-Collections / Guava, вы можете сделать следующее:
InputStream stream = ...
String content = CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8));
Closeables.closeQuietly(stream);
Обратите внимание, что второй параметр (например, Charsets.UTF_8) для InputStreamReader
не является обязательным, но обычно рекомендуется указывать кодировку, если вы ее знаете (что вам следует! )