php
iphone
css
ajax
python
mysql
database
android
ruby-on-rails
multithreading
eclipse
perl
algorithm
facebook
oracle
cocoa
tsql
apache
dom
You could do this with a 3-element array.
Whenever you encounter an A, check if the first element of the array is empty -- if not, flush the array to the output file -- then store the new A to the first element of the array.
Whenever you encounter a B, check if the second element of the array is empty but the first element is full -- if not, flush the array to the output file along with the new B. Otherwise (that is, if the first element is full but the 2nd is empty) you'll store the new B as the 2nd element of the array.
For C, repeat the logic for B, incremented by one: Whenever you encounter a C, check if the third element of the array is empty but the 2nd element is full -- if not, flush the array to the output file along with the new C. Otherwise (that is, if the 2nd element is full but the 3rd is empty) you'll store the new C as the 3rd element of the array.
When you encounter neither A nor B nor C, flush any existing array elements to the output file, then write the new line directly to the output file.
The main trick here is that you're defining explicit rules for filling each slot of the buffer array, and using this to avoid re-checking any line matches, while flushing the buffer to the output and resetting the sequence whenever you break pattern.
Granted, you admit that your actual ruleset is somewhat more complicated, but the same type of approach should work.
You could use mark and reset on your stream to "rewind"
I'm assuming your lines are more complex than just "A", "B" and "C", but there is some way to pick an "A" from a "B" from a "C".
(If they really are A, B anc C then you don't need to store anything)
I'd make a little state machine type program.
state = Base; while(there are more lines) { line = read_a_line() switch(state) { case Base: if (line.isTypeA()) { storedLines.add(line); state = GotA; } else { ouput(line); } break; case GotA: if (line.isTypeB()) { storedLines.add(line); state = gotB; } else { output(storedLines); output(line); state = Base; } break; case GotB: if (line.isTypeC()) { storedLines.clear(); } else { output(storedLines); output(line); } state = Base; break; } // TODO: special case handling to make sure you write everything at the end of the // file.