BufferedReader for large ByteBuffer?

后端 未结 3 1244
悲哀的现实
悲哀的现实 2021-01-20 05:37

Is there a way to read a ByteBuffer with a BufferedReader without having to turn it into a String first? I want to read through a fairly large ByteBuffer as lines of text an

相关标签:
3条回答
  • 2021-01-20 05:54

    It's not clear why you're using a byte buffer to start with. If you've got an InputStream and you want to read lines for it, why don't you just use an InputStreamReader wrapped in a BufferedReader? What's the benefit in getting NIO involved?

    Calling toString() on a ByteArrayOutputStream sounds like a bad idea to me even if you had the space for it: better to get it as a byte array and wrap it in a ByteArrayInputStream and then an InputStreamReader, if you really have to have a ByteArrayOutputStream. If you really want to call toString(), at least use the overload which takes the name of the character encoding to use - otherwise it'll use the system default, which probably isn't what you want.

    EDIT: Okay, so you really want to use NIO. You're still writing to a ByteArrayOutputStream eventually, so you'll end up with a BAOS with the data in it. If you want to avoid making a copy of that data, you'll need to derive from ByteArrayOutputStream, for instance like this:

    public class ReadableByteArrayOutputStream extends ByteArrayOutputStream
    {
        /**
         * Converts the data in the current stream into a ByteArrayInputStream.
         * The resulting stream wraps the existing byte array directly;
         * further writes to this output stream will result in unpredictable
         * behavior.
         */
        public InputStream toInputStream()
        {
            return new ByteArrayInputStream(array, 0, count);
        }
    }
    

    Then you can create the input stream, wrap it in an InputStreamReader, wrap that in a BufferedReader, and you're away.

    0 讨论(0)
  • 2021-01-20 05:57

    You can use NIO, but there's no real need here. As Jon Skeet suggested:

    public byte[] read(InputStream istream)
    {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      byte[] buffer = new byte[1024]; // Experiment with this value
      int bytesRead;
    
      while ((bytesRead = istream.read(buffer)) != -1)
      {
        baos.write(buffer, 0, bytesRead);
      }
    
      return baos.toByteArray();
    }
    
    
    // after the process is run, we call this method with the String
    public void readLines(byte[] data)
    {
      BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(data)));
      String line;
    
      while ((line = reader.readLine()) != null)
      {
        // do stuff with line
      }
    }
    
    0 讨论(0)
  • 2021-01-20 05:57

    This is a sample:

    public class ByteBufferBackedInputStream extends InputStream {
    
        ByteBuffer buf;
    
        public ByteBufferBackedInputStream(ByteBuffer buf) {
            this.buf = buf;
        }
    
        public synchronized int read() throws IOException {
            if (!buf.hasRemaining()) {
                return -1;
            }
            return buf.get() & 0xFF;
        }
    
        @Override
        public int available() throws IOException {
            return buf.remaining();
        }
    
        public synchronized int read(byte[] bytes, int off, int len) throws IOException {
            if (!buf.hasRemaining()) {
                return -1;
            }
    
            len = Math.min(len, buf.remaining());
            buf.get(bytes, off, len);
            return len;
        }
    }
    

    And you can use it like this:

        String text = "this is text";   // It can be Unicode text
        ByteBuffer buffer = ByteBuffer.wrap(text.getBytes("UTF-8"));
    
        InputStream is = new ByteBufferBackedInputStream(buffer);
        InputStreamReader r = new InputStreamReader(is, "UTF-8");
        BufferedReader br = new BufferedReader(r);
    
    0 讨论(0)
提交回复
热议问题