1 2 3 4 5 6 7 ... 38

Hudební tvorba / 3. 2. 2016 / Bambësch

Skladba inspirovaná lesem na severu města. Nechtěl jsem, aby zněla tak temně, ale co se dá dělat. Minimálně v noci to tam určitě trochu temnější je.

Programování / 1. 2. 2016 / Náhodné čtení a zápis binárních souborů v Javě

V dnešním příspěvku představím, jak v Javě číst a zapisovat binární soubory po blocích. To se může hodit například při stahování jednoho souboru po částech z více zdrojů. K tomuto účelu je vhodná třída SeekableByteChannel, kterou lze vytvořit tovární metodou Files.newByteChannel. Její nejdůležitější metody jsou:

  • position = přesune kurzor na zadanou pozici v souboru (udává se v bajtech)
  • read = naplní buffer bajty přečtenými ze souboru (od aktuální pozice až do rezervované délky bufferu)
  • write = zapíše celý obsah bufferu do souboru (od aktuální pozice až do délky bufferu)

A tady je ukázka jednoduché služby pro náhodný zápis bloků (chunků) binárních dat, která by se dala využít třeba v nějakém druhu jednoduchého torrent klienta:

  1. public class BasicInputOutputService {
  2.     private final Logger log = LoggerFactory.getLogger(getClass());
  3.  
  4.     public byte[] readBinaryChunk(final Path path, final long fileSize, final int chunkIndex, final int chunkSize) throws ErrorReadingChunkException {
  5.         final long offset = calculateOffset(chunkIndex, chunkSize);
  6.         final int chunkSizeAdjusted = adjustChunkSize(offset, chunkSize, fileSize);
  7.         log.info("Reading bytes {} .. {} from {}...", offset, offset + chunkSizeAdjusted - 1, path);
  8.  
  9.         try (SeekableByteChannel channel = createReadableChannel(path)) {
  10.             final ByteBuffer buffer = ByteBuffer.allocate(chunkSizeAdjusted);
  11.             channel.position(offset);
  12.             channel.read(buffer);
  13.             return buffer.array();
  14.         } catch (final IOException e) {
  15.             log.error("Error while reading binary chunk.", e);
  16.             throw new ErrorReadingChunkException(path, offset, chunkSizeAdjusted, e);
  17.         }
  18.     }
  19.  
  20.     public void writeBinaryChunk(final Path path, final long fileSize, final int chunkIndex, final int chunkSize, final byte[] data) throws ErrorWritingChunkException {
  21.         final long offset = calculateOffset(chunkIndex, chunkSize);
  22.         final int chunkSizeAdjusted = adjustChunkSize(offset, chunkSize, fileSize);
  23.         log.info("Writing bytes {} .. {} to {}...", offset, offset + chunkSizeAdjusted - 1, path);
  24.  
  25.         try (SeekableByteChannel channel = createWritableChannel(path)) {
  26.             final ByteBuffer buffer = ByteBuffer.wrap(data, 0, chunkSizeAdjusted);
  27.             channel.position(offset);
  28.             channel.write(buffer);
  29.         } catch (final IOException e) {
  30.             log.error("Error while writing binary chunk.", e);
  31.             throw new ErrorWritingChunkException(path, offset, chunkSizeAdjusted, e);
  32.         }
  33.     }
  34.  
  35.     private SeekableByteChannel createWritableChannel(final Path path) throws IOException {
  36.         return Files.newByteChannel(path, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
  37.     }
  38.  
  39.     private SeekableByteChannel createReadableChannel(final Path path) throws IOException {
  40.         return Files.newByteChannel(path, StandardOpenOption.READ);
  41.     }
  42.  
  43.     private int adjustChunkSize(final long offset, final int chunkSize, final long fileSize) {
  44.         if (offset + chunkSize > fileSize) {
  45.             // last chunk: its size must be truncated
  46.             return (int) (fileSize % chunkSize);
  47.         } else {
  48.             return chunkSize;
  49.         }
  50.     }
  51.  
  52.     private long calculateOffset(final int chunkIndex, final int chunkSize) {
  53.         return chunkIndex * chunkSize;
  54.     }
  55. }

Hudební tvorba / 18. 1. 2016 / Innovation

1 2 3 4 5 6 7 ... 38