@@ -154,6 +154,7 @@ public final class CSVParser implements Iterable<CSVRecord>, Closeable {
154154 public static class Builder extends AbstractStreamBuilder <CSVParser , Builder > {
155155
156156 private CSVFormat format ;
157+ private long byteOffset = -1 ;
157158 private long characterOffset ;
158159 private long recordNumber = 1 ;
159160 private boolean trackBytes ;
@@ -171,10 +172,27 @@ public CSVParser get() throws IOException {
171172 }
172173
173174 /**
174- * Sets the lexer offset when the parser does not start parsing at the beginning of the source.
175+ * Sets the lexer byte offset when the parser does not start parsing at the beginning of the source.
176+ * <p>
177+ * By default, the value is {@code -1}, which reuses the character offset for the byte offset.
178+ * </p>
175179 *
176- * @param characterOffset the lexer offset.
180+ * @param byteOffset the lexer byte offset.
177181 * @return {@code this} instance.
182+ * @see #setCharacterOffset(long)
183+ * @since 1.15.0
184+ */
185+ public Builder setByteOffset (final long byteOffset ) {
186+ this .byteOffset = byteOffset ;
187+ return asThis ();
188+ }
189+
190+ /**
191+ * Sets the lexer character offset when the parser does not start parsing at the beginning of the source.
192+ *
193+ * @param characterOffset the lexer character offset.
194+ * @return {@code this} instance.
195+ * @see #setByteOffset(long)
178196 */
179197 public Builder setCharacterOffset (final long characterOffset ) {
180198 this .characterOffset = characterOffset ;
@@ -465,6 +483,12 @@ public static CSVParser parse(final URL url, final Charset charset, final CSVFor
465483 */
466484 private long recordNumber ;
467485
486+ /**
487+ * Lexer offset when the parser does not start parsing at the beginning of the source. Usually used in combination
488+ * with {@link #recordNumber}.
489+ */
490+ private final long byteOffset ;
491+
468492 /**
469493 * Lexer offset when the parser does not start parsing at the beginning of the source. Usually used in combination
470494 * with {@link #recordNumber}.
@@ -485,6 +509,7 @@ private CSVParser(final Builder builder) throws IOException {
485509 this .lexer = new Lexer (format , new ExtendedBufferedReader (builder .getReader (), builder .getCharset (), builder .trackBytes ));
486510 this .csvRecordIterator = new CSVRecordIterator ();
487511 this .headers = createHeaders ();
512+ this .byteOffset = builder .byteOffset != -1 ? builder .byteOffset : builder .characterOffset ;
488513 this .characterOffset = builder .characterOffset ;
489514 this .recordNumber = builder .recordNumber - 1 ;
490515 }
@@ -870,7 +895,7 @@ CSVRecord nextRecord() throws IOException {
870895 recordList .clear ();
871896 StringBuilder sb = null ;
872897 final long startCharPosition = lexer .getCharacterPosition () + characterOffset ;
873- final long startBytePosition = lexer .getBytesRead () + characterOffset ;
898+ final long startBytePosition = lexer .getBytesRead () + byteOffset ;
874899 do {
875900 reusableToken .reset ();
876901 lexer .nextToken (reusableToken );
0 commit comments