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

org.simpleflatmapper.lightningcsv.CsvReader Maven / Gradle / Ivy

Go to download

Java library to map flat record - ResultSet, csv - to java object with minimum configuration and low footprint.

There is a newer version: 9.0.2
Show newest version
package org.simpleflatmapper.lightningcsv;

import org.simpleflatmapper.lightningcsv.impl.CellConsumerCapture;
import org.simpleflatmapper.lightningcsv.impl.CellConsumerFixLengthToCheckConsumer;
import org.simpleflatmapper.lightningcsv.parser.AbstractCharConsumer;
import org.simpleflatmapper.lightningcsv.parser.CellConsumer;
import org.simpleflatmapper.lightningcsv.parser.CharBuffer;
import org.simpleflatmapper.lightningcsv.parser.NullCellConsumer;
import org.simpleflatmapper.lightningcsv.parser.StringArrayCellConsumer;
import org.simpleflatmapper.util.CheckedConsumer;
import org.simpleflatmapper.util.ErrorHelper;
import org.simpleflatmapper.util.Function;

import java.io.EOFException;
import java.io.IOException;
import java.util.Iterator;
import java.util.NoSuchElementException;
//IFJAVA8_START
import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
//IFJAVA8_END



public final class CsvReader implements Iterable {

	private final AbstractCharConsumer consumer;

	private final Function cellConsumerWrapper;

	public CsvReader(AbstractCharConsumer charConsumer) {
		this(charConsumer, null);
	}

	public CsvReader(AbstractCharConsumer charConsumer, Function cellConsumerWrapper) {
		this.consumer = charConsumer;
		this.cellConsumerWrapper = cellConsumerWrapper;
	}

	/**
	 * parse cvs
     * @param cellConsumer the consumer that the parser will callback
	 * @param  the cell consumer type
     * @throws java.io.IOException if an io error occurs
     * @return the cell consumer
	 */
	public  CC parseAll(CC cellConsumer)
			throws IOException {
		_parseAll(wrapConsumer(cellConsumer), false);

		return cellConsumer;
	}

	private  void _parseAll(CC cellConsumer, boolean keepRow) throws IOException {
		do {
			consumer.consumeAllBuffer(cellConsumer);
		} while(consumer.shiftAndRead(keepRow));

		consumer.finish(cellConsumer);
	}


	/**
	 * parse cvs
	 * @param cellConsumer the cell consumer
     * @return true if there was data consumed
	 * @throws IOException if io error occurs
	 */
	public boolean parseRow(CellConsumer cellConsumer)
			throws IOException {
		return rawParseRow(wrapConsumer(cellConsumer), false);
	}

	public boolean rawParseRow(CellConsumer cellConsumer, boolean keepRow) throws IOException {
		do {
			if (consumer.consumeToNextRow(cellConsumer)) {
				return true;
			}
		} while(consumer.shiftAndRead(keepRow));

		consumer.finish(cellConsumer);
		return false;
	}


	public void skipRows(int n) throws IOException {
		_parseRows(NullCellConsumer.INSTANCE, n);
	}

	public  CC  parseRows(CC cellConsumer, int limit) throws IOException {
		_parseRows(wrapConsumer(cellConsumer), limit);
		return cellConsumer;
	}

	private  void _parseRows(CC cellConsumer, int limit) throws IOException {
		for(int i = 0; i < limit; i++) {
			rawParseRow(cellConsumer, false);
		}
	}

	public > RH read(RH consumer) throws IOException {
		parseAll(toCellConsumer(consumer));
		return consumer;
	}

	public > RH read(RH consumer, int limit) throws IOException {
		parseRows(toCellConsumer(consumer), limit);
		return consumer;
	}

	private CellConsumer toCellConsumer(CheckedConsumer consumer) {
		return StringArrayCellConsumer.newInstance(consumer);
	}

	public CellConsumer wrapConsumer(CellConsumer cellConsumer) {
		if (cellConsumerWrapper == null) return cellConsumer;
		return cellConsumerWrapper.apply(cellConsumer);
	}

	public CharBuffer charBuffer() {
		return consumer.charBuffer();
	}

	@Override
	public Iterator iterator() {
		return new CsvStringArrayIterator(this);
	}
	
	public Iterator rowIterator() throws IOException {
		return new CsvRowArrayIterator(this);
	}

	//IFJAVA8_START
	public Stream stream() {
		return StreamSupport.stream(new CsvStringArraySpliterator(this), false);
	}


	private static class CsvStringArraySpliterator implements Spliterator {
		private final CsvReader reader;

		public CsvStringArraySpliterator(CsvReader csvReader) {
			this.reader = csvReader;
		}

		@Override
		public boolean tryAdvance(Consumer action) {
			try {
				return reader.parseRow(reader.toCellConsumer(action::accept));
			} catch (IOException e) {
               return ErrorHelper.rethrow(e);
			}
		}

		@Override
		public void forEachRemaining(Consumer action) {
			try {
				reader.parseAll(reader.toCellConsumer(action::accept));
			} catch (IOException e) {
                ErrorHelper.rethrow(e);
			}
		}

		@Override
		public Spliterator trySplit() {
			return null;
		}

		@Override
		public long estimateSize() {
			return Long.MAX_VALUE;
		}

		@Override
		public int characteristics() {
			return Spliterator.ORDERED | Spliterator.NONNULL;
		}
	}

	public Stream rowStream() {
		return StreamSupport.stream(new CsvRowSpliterator(this), false);
	}

	private static class CsvRowSpliterator implements Spliterator {
		private final CsvReader reader;
		
		private Row.Headers headers;

		public CsvRowSpliterator(CsvReader csvReader) {
			this.reader = csvReader;
		}

		@Override
		public boolean tryAdvance(Consumer action) {
			try {
				if (headers == null) {
					headers = headers(reader);
				}
				return reader.parseRow(new CellConsumerFixLengthToCheckConsumer(headers.size(), values -> action.accept(new Row(headers, values))));
			} catch (IOException e) {
				return ErrorHelper.rethrow(e);
			}
		}

		@Override
		public void forEachRemaining(Consumer action) {
			try {
				if (headers == null) {
					headers = headers(reader);
				}
				reader.parseAll(new CellConsumerFixLengthToCheckConsumer(headers.size(), values -> action.accept(new Row(headers, values))));
			} catch (IOException e) {
				ErrorHelper.rethrow(e);
			}
		}

		@Override
		public Spliterator trySplit() {
			return null;
		}

		@Override
		public long estimateSize() {
			return Long.MAX_VALUE;
		}

		@Override
		public int characteristics() {
			return Spliterator.ORDERED | Spliterator.NONNULL;
		}
		
		
	}
	//IFJAVA8_END

    private static class CsvStringArrayIterator implements Iterator {

        private final CsvReader reader;
        private final CellConsumer cellConsumer;

        private boolean isFetched;
        private String[] value;
        @SuppressWarnings("unchecked")
        public CsvStringArrayIterator(CsvReader csvReader) {
            cellConsumer = csvReader.toCellConsumer(new CheckedConsumer() {
                @Override
                public void accept(String[] strings)  {
                    value = strings;
                }
            });
            reader = csvReader;
        }

        @Override
        public boolean hasNext() {
            fetch();
            return value != null;
        }

        private void fetch() {
            if (!isFetched) {
                try {
                    value = null;
                    reader.parseRow(cellConsumer);
                } catch (IOException e) {
                    ErrorHelper.rethrow(e);
                }
                isFetched = true;
            }
        }

        @Override
        public String[] next() {
            fetch();
            if (value == null) throw new NoSuchElementException();
            isFetched = false;
            return value;
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

	private static class CsvRowArrayIterator implements Iterator {

		private final CsvReader reader;
		private final CellConsumerFixLengthToCheckConsumer cellConsumer;
		private Row.Headers headers;

		private Row value;
		private boolean isFetched;
		

		public CsvRowArrayIterator(CsvReader csvReader) throws IOException {
			reader = csvReader;
			headers = headers(csvReader);
			cellConsumer = new CellConsumerFixLengthToCheckConsumer(headers.size(), new org.simpleflatmapper.util.Consumer() {
				@Override
				public void accept(String[] strings) {
					value = new Row(headers, strings);
				}
			});
		}

		@Override
		public boolean hasNext() {
			fetch();
			return value != null;
		}

		private void fetch() {
			if (!isFetched) {
				try {
					value = null;
					reader.parseRow(cellConsumer);
				} catch (IOException e) {
					ErrorHelper.rethrow(e);
				}
				isFetched = true;
			}
		}

		@Override
		public Row next() {
			fetch();
			if (value == null) throw new NoSuchElementException();
			isFetched = false;
			return value;
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException();
		}
	}
	
	private static Row.Headers headers(CsvReader reader) throws IOException {
		CellConsumerCapture cellConsumer = new CellConsumerCapture();
		reader.parseRow(cellConsumer);
		if (!cellConsumer.hasData()) {
			throw new EOFException("No headers");
		}
		return Row.headers(cellConsumer.values());
	} 
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy