Java NIO scan through ByteBuffer for specific bytes and sectional word

Okay, so I'm trying to do something similar, that it should be pretty simple, but with these new NIO interfaces, everything confuses me! Here, what I'm trying to do, I need to scan the file as bytes until you find certain bytes! When I come across these specific bytes, I need to capture this data segment and do something with it, then go to it and do it again. I would think that with all these markers and positions and restrictions in ByteBuffer, I could do it, but I can't get it to work! That's what I still have ..

test.text:

this is a line of text a this is line 2b line 3 line 4 line etc.etc.etc. 

Test.java:

 import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; public class Test { public static final Charset ENCODING = Charset.forName("UTF-8"); public static final byte[] NEWLINE_BYTE = {0x0A, 0x0D}; public Test() { String pathString = "test.txt"; //the path to the file Path path = Paths.get(pathString); try (FileChannel fc = FileChannel.open(path, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE)) { if (fc.size() > 0) { int n; ByteBuffer buffer = ByteBuffer.allocate((int) fc.size()); do { n = fc.read(buffer); } while (n != -1 && buffer.hasRemaining()); buffer.flip(); int pos = 0; System.out.println("FILE LOADED: |" + new String(buffer.array(), ENCODING) + "|"); do { byte b = buffer.get(); if (b == NEWLINE_BYTE[0] || b == NEWLINE_BYTE[1]) { System.out.println("POS: " + pos); System.out.println("POSITION: " + buffer.position()); System.out.println("LENGTH: " + Integer.toString(buffer.position() - pos)); ByteBuffer lineBuffer = ByteBuffer.wrap(buffer.array(), pos + 1, buffer.position() - pos); System.out.println("LINE: |" + new String(lineBuffer.array(), ENCODING) + "|"); pos = buffer.position(); } } while (buffer.hasRemaining()); } } catch (IOException ioe) { ioe.printStackTrace(); } } public static void main(String args[]) { Test t = new Test(); } } 

So, the first part works, the fc.read (buffer) function works only once and pulls out the whole file in ByteBuffer. Then in the second do loop, I can execute a byte cycle by byte, just fine, and it gets into the if statement when it gets into \ n (or \ r), but then I can’t figure out how to get PORTION from bytes that I just looked into a separate byte array for work! I tried splicing and various flips, and I tried wrapping as shown in the above code, but it can't seem to make it work, both buffers always have a full file, and so I do something that I spliced ​​or wrapped!

I just need to skip the byte file by byte, looking at a specific section at a time, and then my final goal, when I looked and found the right place, I want to paste some data into a direct place! I need this lineBuffer, which is output to "LINE:", to have ONLY a part of the bytes that I have missed so far! Help and thanks!

+1
java nio bytebuffer filechannel
source share
3 answers

Here is the solution I came across using the ByteBuffer mass relative fetch function to get a chunk every time. I think I use the mark () functionality as it is intended, although I use an additional variable (pos) to track the label, since I cannot find the function in ByteBuffer to return the relative position of the label itself. In addition, I have explicit functionality to look for either \ r, \ n, or both in sequence. Keep in mind that this code will only work with UTF-8 encoded data. Hope this helps someone else.

 public class Test { public static final Charset ENCODING = Charset.forName("UTF-8"); public static final byte[] NEWLINE_BYTES = {0x0A, 0x0D}; public Test() { //test text file sequence of any strings followed by newline String pathString = "test.txt"; Path path = Paths.get(pathString); try (FileChannel fc = FileChannel.open(path, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE)) { if (fc.size() > 0) { int n; ByteBuffer buffer = ByteBuffer.allocate((int) fc.size()); do { n = fc.read(buffer); } while (n != -1 && buffer.hasRemaining()); buffer.flip(); int newlineByteCount = 0; buffer.mark(); do { //get one byte at a time byte b = buffer.get(); if (b == NEWLINE_BYTES[0] || b == NEWLINE_BYTES[1]) { newlineByteCount++; byte nextByte = buffer.get(); if (nextByte == NEWLINE_BYTES[1]) { newlineByteCount++; } else { buffer.position(buffer.position() - 1); } int pos = buffer.position(); //reset the buffer back to the mark() position buffer.reset(); //create an array just the right length and get the bytes we just measured out int length = pos - buffer.position() - newlineByteCount; byte[] lineBytes = new byte[length]; buffer.get(lineBytes, 0, length); String lineString = new String(lineBytes, ENCODING); System.out.println("LINE: " + lineString); buffer.position(buffer.position() + newlineByteCount); buffer.mark(); newlineByteCount = 0; } else if (newlineByteCount > 0) { } } while (buffer.hasRemaining()); } } catch (IOException ioe) { ioe.printStackTrace(); } } public static void main(String args[]) { new Test(); } } 
0
source share

Leaving aside I / O, as soon as you have content in ByteBuffer , it would be much easier to convert it to CharBuffer via asCharBuffer() . CharBuffer then implements CharSequence , which gives you many String and regex methods.

+1
source share

I need something similar, but more general than splitting a single buffer. In my case, I have several buffers; in fact, my code is a modification of Spring StringDecoder , which can convert Flux<DataBuffer> ( DataBuffer ) to Flux<String> .

fooobar.com/questions/847179 / ...

0
source share

All Articles