web-dev-qa-db-ja.com

Java:InputStreamとして文字列のリストにアクセスする

InputStreamUTF-8のリストをラップする方法はありますかString?私は次のようなことをしたいと思います:

InputStream in = new XyzInputStream( List<String> lines )
15
Marc Polizzi

すべての行を連結して文字列を作成し、String#getBytesを使用してバイト配列に変換し、 ByteArrayInputStream に渡すことができます。ただし、これは最も効率的な方法ではありません。

4
benmmurphy

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 の方がよい場合があります。

9
Dave Webb

要するに、いいえ、既存の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用のアダプターです。

4
Jon

ある種の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);
        }
    }
}    
1
Mike Shauneu

私の場合、同等のファイル内の文字列のリストを変換する必要がありました(各行に改行が含まれています)。

これが私の解決策でした:

List<String> inputList = Arrays.asList("line1", "line2", "line3");

byte[] bytes = inputList.stream().collect(Collectors.joining("\n")).getBytes();

InputStream inputStream = new ByteArrayInputStream(bytes);
0
freedev

この方法でシリアル化可能なリストを作成することもできます

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);
}
0

あなたはこれに似た何かをすることができます:

https://commons.Apache.org/sandbox/flatfile/xref/org/Apache/commons/flatfile/util/ConcatenatedInputStream.html

InputStreamのread()メソッドを実装するだけで、連結しているInputStreamのリストがあります。 EOFを読み取ると、次のInputStreamから読み取りを開始します。文字列をByteArrayInputStreamsに変換するだけです。

0
benmmurphy