Есть ли способ, которым InputStream
обертывает список String
UTF-8? Я хотел бы сделать что-то вроде:
InputStream in = new XyzInputStream( List<String> lines )
Есть ли способ, которым InputStream
обертывает список String
UTF-8? Я хотел бы сделать что-то вроде:
InputStream in = new XyzInputStream( List<String> lines )
Вы можете объединить все строки вместе, чтобы создать String, а затем преобразовать его в массив байтов, используя String#getBytes
и передать его в ByteArrayInputStream. Однако это не самый эффективный способ сделать это.
Вы можете читать из ByteArrayOutputStream
и создавать свой исходный массив byte[]
с помощью ByteArrayInputStream
.
Итак, создайте массив следующим образом:
List<String> source = new ArrayList<String>();
source.add("one");
source.add("two");
source.add("three");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (String line : source) {
baos.write(line.getBytes());
}
byte[] bytes = baos.toByteArray();
И читать из него так же просто, как:
InputStream in = new ByteArrayInputStream(bytes);
Кроме того, в зависимости от того, что вы пытаетесь сделать, StringReader
может быть лучше.
Короче говоря, нет, нет никакого способа сделать это, используя существующие классы JDK. Однако вы могли бы реализовать свой собственный InputStream, который читается из списка строк.
EDIT: у Dave Web есть ответ выше, и я думаю, что это путь. Если вам нужен многоразовый класс, то что-то вроде этого может сделать:
public class StringsInputStream<T extends Iterable<String>> extends InputStream {
private ByteArrayInputStream bais = null;
public StringsInputStream(final T strings) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
for (String line : strings) {
outputStream.write(line.getBytes());
}
bais = new ByteArrayInputStream(outputStream.toByteArray());
}
@Override
public int read() throws IOException {
return bais.read();
}
@Override
public int read(byte[] b) throws IOException {
return bais.read(b);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return bais.read(b, off, len);
}
@Override
public long skip(long n) throws IOException {
return bais.skip(n);
}
@Override
public int available() throws IOException {
return bais.available();
}
@Override
public void close() throws IOException {
bais.close();
}
@Override
public synchronized void mark(int readlimit) {
bais.mark(readlimit);
}
@Override
public synchronized void reset() throws IOException {
bais.reset();
}
@Override
public boolean markSupported() {
return bais.markSupported();
}
public static void main(String[] args) throws Exception {
List source = new ArrayList();
source.add("foo ");
source.add("bar ");
source.add("baz");
StringsInputStream<List<String>> in = new StringsInputStream<List<String>>(source);
int read = in.read();
while (read != -1) {
System.out.print((char) read);
read = in.read();
}
}
}
Это в основном адаптер для ByteArrayInputStream
.
вы также можете сделать это, создав Сериализуемый список
List<String> quarks = Arrays.asList(
"up", "down", "strange", "charm", "top", "bottom"
);
//serialize the List
//note the use of abstract base class references
try{
//use buffering
OutputStream file = new FileOutputStream( "quarks.ser" );
OutputStream buffer = new BufferedOutputStream( file );
ObjectOutput output = new ObjectOutputStream( buffer );
try{
output.writeObject(quarks);
}
finally{
output.close();
}
}
catch(IOException ex){
fLogger.log(Level.SEVERE, "Cannot perform output.", ex);
}
//deserialize the quarks.ser file
//note the use of abstract base class references
try{
//use buffering
InputStream file = new FileInputStream( "quarks.ser" );
InputStream buffer = new BufferedInputStream( file );
ObjectInput input = new ObjectInputStream ( buffer );
try{
//deserialize the List
List<String> recoveredQuarks = (List<String>)input.readObject();
//display its data
for(String quark: recoveredQuarks){
System.out.println("Recovered Quark: " + quark);
}
}
finally{
input.close();
}
}
catch(ClassNotFoundException ex){
fLogger.log(Level.SEVERE, "Cannot perform input. Class not found.", ex);
}
catch(IOException ex){
fLogger.log(Level.SEVERE, "Cannot perform input.", ex);
}
Вы можете сделать что-то похожее на это:
Он просто реализует метод read() InputStream и имеет список InputStreams, который он объединяет. Когда он читает EOF, он начинает считывать из следующего InputStream. Просто преобразуйте строки в ByteArrayInputStreams.
Вы можете создать какой-то IterableInputStream
public class IterableInputStream<T> extends InputStream {
public static final int EOF = -1;
private static final InputStream EOF_IS = new InputStream() {
@Override public int read() throws IOException {
return EOF;
}
};
private final Iterator<T> iterator;
private final Function<T, byte[]> mapper;
private InputStream current;
public IterableInputStream(Iterable<T> iterable, Function<T, byte[]> mapper) {
this.iterator = iterable.iterator();
this.mapper = mapper;
next();
}
@Override
public int read() throws IOException {
int n = current.read();
while (n == EOF && current != EOF_IS) {
next();
n = current.read();
}
return n;
}
private void next() {
current = iterator.hasNext()
? new ByteArrayInputStream(mapper.apply(iterator.next()))
: EOF_IS;
}
}
Использовать его
public static void main(String[] args) throws IOException {
Iterable<String> strings = Arrays.asList("1", "22", "333", "4444");
try (InputStream is = new IterableInputStream<String>(strings, String::getBytes)) {
for (int b = is.read(); b != -1; b = is.read()) {
System.out.print((char) b);
}
}
}
В моем случае мне пришлось преобразовать список строк в эквивалентный файл (с переводом строки для каждой строки).
Это было мое решение:
List<String> inputList = Arrays.asList("line1", "line2", "line3");
byte[] bytes = inputList.stream().collect(Collectors.joining("\n")).getBytes();
InputStream inputStream = new ByteArrayInputStream(bytes);