Index: src/java/org/apache/lucene/benchmark/byTask/tasks/WriteLineDocTask.java
===================================================================
--- src/java/org/apache/lucene/benchmark/byTask/tasks/WriteLineDocTask.java	(revision 1080130)
+++ src/java/org/apache/lucene/benchmark/byTask/tasks/WriteLineDocTask.java	(working copy)
@@ -55,12 +55,40 @@
 
   public final static char SEP = '\t';
   
+  // fields to be written by default
+  public static final String[] DEFAULT_FIELDS = new String[] {
+    DocMaker.TITLE_FIELD,
+    DocMaker.DATE_FIELD,
+    DocMaker.BODY_FIELD,
+  };
+  
   private int docSize = 0;
   private PrintWriter lineFileOut = null;
   private DocMaker docMaker;
   private ThreadLocal<StringBuilder> threadBuffer = new ThreadLocal<StringBuilder>();
   private ThreadLocal<Matcher> threadNormalizer = new ThreadLocal<Matcher>();
+  private volatile String[] fieldsToWrite = fields();
   
+  /**
+   * Fields that should be written by this task, in required order.
+   * Override this to write more/less/other fields.
+   */
+  public String[] fields() {
+    return DEFAULT_FIELDS;
+  }
+  
+  /**
+   * Check if specified field is sufficient justification to write a line for the input ddocument.
+   * Default implementation requires non empty fields 0 or 2 (body or title).
+   * Override this method to require other fields to be non empty.
+   * For example, to always emit a line also for empty docs, always return true.
+   * @param idx index of the checked field (as in {@link #fields()})
+   * @param text text of the checked field
+   */
+  protected boolean sufficientFields(int idx, String text) {
+    return (idx==0 || idx==2) && text.length()>0; // by default require non empty body or title
+  }
+  
   public WriteLineDocTask(PerfRunData runData) throws Exception {
     super(runData);
     Config config = runData.getConfig();
@@ -106,27 +134,32 @@
       threadNormalizer.set(matcher);
     }
     
-    Field f = doc.getField(DocMaker.BODY_FIELD);
-    String body = f != null ? matcher.reset(f.stringValue()).replaceAll(" ") : "";
+    StringBuilder sb = threadBuffer.get();
+    if (sb == null) {
+      sb = new StringBuilder();
+      threadBuffer.set(sb);
+    }
+    sb.setLength(0);
+
+    Field f = doc.getField(fieldsToWrite[0]);
+    String text = f == null ? "" : matcher.reset(f.stringValue()).replaceAll(" ").trim();
+    boolean sufficient = sufficientFields(0, text);
+    sb.append(text);
     
-    f = doc.getField(DocMaker.TITLE_FIELD);
-    String title = f != null ? matcher.reset(f.stringValue()).replaceAll(" ") : "";
-    
-    if (body.length() > 0 || title.length() > 0) {
-      
-      f = doc.getField(DocMaker.DATE_FIELD);
-      String date = f != null ? matcher.reset(f.stringValue()).replaceAll(" ") : "";
-      
-      StringBuilder sb = threadBuffer.get();
-      if (sb == null) {
-        sb = new StringBuilder();
-        threadBuffer.set(sb);
-      }
-      sb.setLength(0);
-      sb.append(title).append(SEP).append(date).append(SEP).append(body);
+    for (int i=1; i<fieldsToWrite.length; i++) {
+      f = doc.getField(fieldsToWrite[i]);
+      text = f == null ? "" : matcher.reset(f.stringValue()).replaceAll(" ").trim();
+      sb
+      .append(SEP)
+      .append(text);
+      sufficient |= sufficientFields(i,text);
+    }
+
+    if (sufficient) {
       // lineFileOut is a PrintWriter, which synchronizes internally in println.
       lineFileOut.println(sb.toString());
     }
+
     return 1;
   }
 
Index: src/java/org/apache/lucene/benchmark/byTask/feeds/LineDocSource.java
===================================================================
--- src/java/org/apache/lucene/benchmark/byTask/feeds/LineDocSource.java	(revision 1080130)
+++ src/java/org/apache/lucene/benchmark/byTask/feeds/LineDocSource.java	(working copy)
@@ -44,12 +44,23 @@
  */
 public class LineDocSource extends ContentSource {
 
-  private final static char SEP = WriteLineDocTask.SEP;
+  private final static String SEP = Character.toString(WriteLineDocTask.SEP);
 
   private File file;
   private BufferedReader reader;
   private int readCount;
 
+  private volatile String[] feilds = fields();
+
+  /**
+   * Fields expected to be read from each line, in required order.
+   * Override this to read more/less/other fields.
+   * Default specification matches that of {@link WriteLineDocTask#fields()}
+   */
+  protected String[] fields() {
+    return WriteLineDocTask.DEFAULT_FIELDS;
+  }
+  
   private synchronized void openFile() {
     try {
       if (reader != null) {
@@ -89,24 +100,32 @@
     }
     
     // A line must be in the following format. If it's not, fail !
+    // field_0 <TAB> field_1 <TAB> ... <TAB> field_n
+    // by default fields specification the format is: 
     // title <TAB> date <TAB> body <NEWLINE>
-    int spot = line.indexOf(SEP);
-    if (spot == -1) {
+    String[] f = line.split(SEP);
+    if (f.length != feilds.length) {
       throw new RuntimeException("line: [" + line + "] is in an invalid format !");
     }
-    int spot2 = line.indexOf(SEP, 1 + spot);
-    if (spot2 == -1) {
-      throw new RuntimeException("line: [" + line + "] is in an invalid format !");
-    }
+
     // The date String was written in the format of DateTools.dateToString.
     docData.clear();
     docData.setID(myID);
-    docData.setBody(line.substring(1 + spot2, line.length()));
-    docData.setTitle(line.substring(0, spot));
-    docData.setDate(line.substring(1 + spot, spot2));
+    fillDocData(docData, f);
     return docData;
   }
 
+  /**
+   * Fill doc data with texts of the fields.
+   * The field names and their order are defined in {@link #fields()}
+   * @see #fields() 
+   */
+  protected void fillDocData(DocData docData, String[] fieldsTexts) {
+    docData.setTitle(fieldsTexts[0]);
+    docData.setDate(fieldsTexts[1]);
+    docData.setBody(fieldsTexts[2]);
+  }
+
   @Override
   public void resetInputs() throws IOException {
     super.resetInputs();
