String.split uses a regular expression and discards trailing empty fields when called without an explicit limit.
Java String.split: preserve empty trailing fields in a record
A missing field is data
A line ending in a delimiter may mean that the final field was supplied but left blank. The one-argument split method behaves like split(regex, 0), so that field disappears. For a fixed three-field import, split(regex, -1) keeps the trailing empty value and makes validation possible. The code rejects the incomplete record before it can enter the ledger.
The delimiter is a regex. A literal vertical bar therefore needs escaping as \| in the regex, represented as \\| in a Java string literal. Regex matching explains this second parsing layer; strict UTF-8 decoding belongs before any text split of input bytes.
Declare the format limit
This is an internal delimiter format with no quoted fields or escaped delimiters. If a sender can put the delimiter inside a field, split is the wrong parser. Use a format whose escaping rules are specified and a parser that implements those rules. Validate the exact field count, blank policy, and maximum record length before accepting a row.
Splitting creates an array and field strings proportional to input length. For large files, process one bounded line at a time instead of reading the whole file into memory; streaming file reads covers the resource boundary.
Working program
public class ReceiptFieldBoundary {
static String readReceiptId(String line) {
if (line == null || line.length() > 256) throw new IllegalArgumentException("record length");
String[] fields = line.split("\\|", -1);
if (fields.length != 3 || fields[0].isEmpty() || fields[1].isEmpty() || fields[2].isEmpty())
throw new IllegalArgumentException("three populated fields required");
return fields[0];
}
public static void main(String[] args) {
String incomplete = "receipt-47|settled|";
System.out.println(incomplete.split("\\|").length);
System.out.println(incomplete.split("\\|", -1).length);
try { readReceiptId(incomplete); }
catch (IllegalArgumentException rejected) { System.out.println("record rejected"); }
System.out.println(readReceiptId("receipt-82|settled|check-15"));
}
}Output
2
3
record rejected
receipt-82Cost and ownership
For a bounded line of n characters, splitting scans O(n) input and allocates O(n) total field content plus the array. The 256-character cap here is a teaching policy, not a universal protocol limit. Choose an application-specific cap before allocating for untrusted input.
Common Mistakes
- Do not rely on the default split limit when an empty final field has meaning.
- Do not treat a regex delimiter as a literal string.
- Do not call a delimiter split a CSV parser when quoted fields are allowed.
Read next
Java regular expressions: full matches, searches and capture boundaries, Java UTF-8 decoding: reject malformed bytes before parsing, Java file I/O: UTF-8, streaming reads, and path ownership, Java console input: Scanner tokens, lines and validation.
Text matching boundaries
Continue with Java String.split limit: retain trailing empty fields in records, Java Pattern.quote: match a supplied token literally.
