InputStream
UTF-8のリストをラップする方法はありますかString
?私は次のようなことをしたいと思います:
InputStream in = new XyzInputStream( List<String> lines )
すべての行を連結して文字列を作成し、String#getBytes
を使用してバイト配列に変換し、 ByteArrayInputStream に渡すことができます。ただし、これは最も効率的な方法ではありません。
ByteArrayOutputStream
から読み取ることができ、ByteArrayInputStream
を使用してソースbyte[]
配列を作成できます。
したがって、次のように配列を作成します。
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 を実装することはできます。
編集:デイブウェブは上記の答えを持っています、それは私が行く方法だと思います。再利用可能なクラスが必要な場合は、次のようになります。
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
用のアダプターです。
ある種の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);
この方法でシリアル化可能なリストを作成することもできます
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);
}
あなたはこれに似た何かをすることができます:
InputStreamのread()メソッドを実装するだけで、連結しているInputStreamのリストがあります。 EOFを読み取ると、次のInputStreamから読み取りを開始します。文字列をByteArrayInputStreamsに変換するだけです。