All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sfm.csv.parser.ReaderCsvParser Maven / Gradle / Ivy

package org.sfm.csv.parser;

import java.io.IOException;
import java.io.Reader;

public final class ReaderCsvParser {

	private char[] buffer;

	private int bufferLength;
	private CsvParserState currentState = CsvParserState.NONE;

	private int currentStart = 0;
	private int bufferOffset = 0;

	public ReaderCsvParser(final int bufferSize) {
		buffer = new char[bufferSize];
	}

	/**
	 * parse cvs from input stream assumes character encoding for '"', ',' and
	 * '\n' match utf8
	 * 
	 * @param is
	 * @param handler
	 * @return
	 * @throws IOException
	 */
	public void parse(final Reader is, final CharsCellHandler handler)
			throws IOException {
		while ((bufferLength = is.read(buffer, bufferOffset, buffer.length
				- bufferOffset)) != -1) {
			bufferLength += bufferOffset;

			if (!consumeBytes(handler)) {
				return;
			}
			shiftBuffer();
		}

		if (bufferOffset > 0) {
			handler.newCell(buffer, 0, bufferOffset);
		}
		handler.end();
	}

	private boolean consumeBytes(final CharsCellHandler handler) {
		for (int i = 0; i < bufferLength; i++) {
			char c = buffer[i];
			if (!handleChar(handler, c, i)) {
				return false;
			}
		}
		return true;
	}

	private boolean handleChar(final CharsCellHandler handler, final char c,
			final int i) {
		if (c == '"') {
			quote(i);
		} else if (c == ',') {
			if (currentState != CsvParserState.IN_QUOTE) {
				newCell(handler, i);
			}
		} else if (c == '\n') {
			if (currentState != CsvParserState.IN_QUOTE) {
				newCell(handler, i);
				return handler.endOfRow();
			}
		}
		return true;
	}

	public void quote(final int i) {
		if (currentStart == i) {
			currentState = CsvParserState.IN_QUOTE;
		} else {
			if (currentState == CsvParserState.IN_QUOTE) {
				currentState = CsvParserState.QUOTE;
			} else if (currentState == CsvParserState.QUOTE) {
				currentState = CsvParserState.IN_QUOTE;
			}
		}
	}

	public void newCell(final CharsCellHandler handler, final int i) {
		handler.newCell(buffer, currentStart, i - currentStart);
		currentStart = i + 1;
		currentState = CsvParserState.NONE;
	}

	private void shiftBuffer() {
		// shift buffer consumer data
		bufferOffset = bufferLength - currentStart;

		// if buffer tight double the size
		if (bufferOffset > bufferLength >> 1) {
			// double buffer size
			char[] newbuffer = new char[buffer.length << 1];
			System.arraycopy(buffer, currentStart, newbuffer, 0, bufferOffset);
			buffer = newbuffer;
		} else {
			System.arraycopy(buffer, currentStart, buffer, 0, bufferOffset);
		}
		currentStart = 0;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy