0

I am not quite understanding why you would ever want to pass a offset param to Java BufferedOutputStream.write via the method public void write(byte[] b, int off, int len) ? What is a use-case where you might want to start from a non-Zero offset of the b parameter? Even though you can do it, I don't see why you would want to. From what I can tell, using it is un-necessary 99% of the time?

djangofan
  • 28,471
  • 61
  • 196
  • 289
  • 4
    When the data in the byte array that needs to be written is *not* at the beginning of the array. – Andreas Jun 30 '17 at 22:06
  • 2
    When you've used the [`BufferedInputStream.read(byte[], int, int)`](https://docs.oracle.com/javase/7/docs/api/java/io/BufferedInputStream.html#read(byte[],%20int,%20int)) method, with a non-zero second parameter to put the data into the array. – Andy Turner Jun 30 '17 at 22:13
  • 1
    If you're asking because you're a C/C++ programmer, a corresponding method would take a `char*` and the `len`, but no offset, because offsetting is easily done with `ptr + offset`. That cannot be done in Java, so to prevent need for *copying* the bytes to another buffer, most methods in the JDK that accepts a `byte[]` will have an overload accepting `byte[], offset, len`. – Andreas Jun 30 '17 at 22:15

2 Answers2

2

Let's say I have a 20M byte array containing an image and I want to send the data for that image over the network. (Say I'm writing an HTTP server.) A network buffer is only so large - I'm probably going to want to write that image data to the TCP pipe in more manageable chucks. (4k?)

By having that offset it prevents me from having to do a bunch of array copies. So I can use it like this:

byte[] image = loadImage();
int chunkSize = 4096; // 4k
int chunks = image.length / chunkSize;
for (int i=0; i<chucks; ++i) {
  os.write(image, i*chunkSize, chunkSize);
}

Note you're passing in the same byte array each call to write. It's just reading a different part of it.

DISCLAIMER: This example is overly simplified, ignoring dealing w/ the end of the image where it doesn't line up w/ the chucks, but that's immaterial to the point.

keredson
  • 3,019
  • 1
  • 17
  • 20
  • 1
    The other case you would want to do this is if you are able to flush out some of the processed data. So, for example, if you are zipping up a 10gb file, you probably only need and want to have 1M of it in memory at a time. You could bring in some of it, start DEFLATE, and start sending out the results while you are still processing. Removing the need to store the full 10g in memory. – Cogman Jun 30 '17 at 22:34
  • You would definitely not want to do this. You should just write the entire array in one call. TCP will do all the management necessary. – user207421 Jun 30 '17 at 22:54
  • @keredson Ok, I think I get the gist of what your saying although your use-case would already be handled by TCP layer wouldn't it? For example, this guy used a non-0 offset: https://stackoverflow.com/questions/1169739/java-tcp-socket-data-transfer-is-slow I hope you understand where my question still lies? – djangofan Jun 30 '17 at 23:05
  • @djangofan That is exactly my point. The example is artificial and poor practice. The fact that network buffers even exist is irrelevant to the operation of `OutputStream.write()`: it is defined to block until everything has been written. Writing your own loop to accomplish what it already does is completely pointless, and can be counterproductive. – user207421 Jun 30 '17 at 23:08
  • @EJP I hear you but still wondering about an answer to my question, in general. Studying for my OCP exam. – djangofan Jun 30 '17 at 23:12
  • 1
    @djangofan The other answer is sufficient, but I will add that the `offset` parameter is zero in 99% of the Java I/O code I have ever written, if not 99.99%, over a period of twenty years. It's there because it has to be there for completeness, but in practice it is rarely used. – user207421 Jun 30 '17 at 23:16
  • @EJP Thanks, I thought as much. That pretty much answers my question. – djangofan Jun 30 '17 at 23:17
  • Obviously it's a contrived example. The question was why you would ever do it, and this is a fairly common pattern in Java and other languages. – keredson Jul 03 '17 at 17:33
1

I have actually used this API, which was for a high speed I/O that reused a single byte[] buffer to read in data then wrote it out, but certain parts of the payload were skipped.

Bohemian
  • 412,405
  • 93
  • 575
  • 722