WriterExamples.java
/*******************************************************************************
* Copyright 2014 Univocity Software Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.univocity.parsers.examples;
import com.univocity.parsers.common.processor.*;
import com.univocity.parsers.conversions.*;
import com.univocity.parsers.csv.*;
import com.univocity.parsers.fixed.*;
import com.univocity.parsers.tsv.*;
import org.testng.annotations.*;
import java.io.*;
import java.math.*;
import java.util.*;
import static org.testng.Assert.*;
public class WriterExamples extends Example {
List<Object[]> rows = Arrays.asList(
new Object[][]{
{"1997", "Ford", "E350", "ac, abs, moon", "3000.00"},
{"1999", "Chevy", "Venture \"Extended Edition\"", "", "4900.00"},
{"1996", "Jeep", "Grand Cherokee", "MUST SELL!\nair, moon roof, loaded", "4799.00"},
{},
{"1999", "Chevy", "Venture \"Extended Edition, Very Large\"", null, "5000.00"},
{null, "", "Venture \"Extended Edition\"", null, "4900.00"},
});
@Test
public void example001WriteSimpleCsv() {
// Writing to an in-memory byte array. This will be printed out to the standard output so you can easily see the result.
ByteArrayOutputStream csvResult = new ByteArrayOutputStream();
// CsvWriter (and all other file writers) work with an instance of java.io.Writer
Writer outputWriter = new OutputStreamWriter(csvResult);
//##CODE_START
// All you need is to create an instance of CsvWriter with the default CsvWriterSettings.
// By default, only values that contain a field separator are enclosed within quotes.
// If quotes are part of the value, they are escaped automatically as well.
// Empty rows are discarded automatically.
CsvWriter writer = new CsvWriter(outputWriter, new CsvWriterSettings());
// Write the record headers of this file
writer.writeHeaders("Year", "Make", "Model", "Description", "Price");
// Here we just tell the writer to write everything and close the given output Writer instance.
writer.writeRowsAndClose(rows);
//##CODE_END
// Let's just print the resulting CSV
printAndValidate(csvResult.toString());
}
@Test
public void example002WriteCsvOneByOne() {
// Writing to an in-memory byte array. This will be printed out to the standard output so you can easily see the result.
ByteArrayOutputStream csvResult = new ByteArrayOutputStream();
// CsvWriter (and all other file writers) work with an instance of java.io.Writer
Writer outputWriter = new OutputStreamWriter(csvResult);
//##CODE_START
CsvWriterSettings settings = new CsvWriterSettings();
// Sets the character sequence to write for the values that are null.
settings.setNullValue("?");
//Changes the comment character to -
settings.getFormat().setComment('-');
// Sets the character sequence to write for the values that are empty.
settings.setEmptyValue("!");
// writes empty lines as well.
settings.setSkipEmptyLines(false);
// Creates a writer with the above settings;
CsvWriter writer = new CsvWriter(outputWriter, settings);
// writes the file headers
writer.writeHeaders("a", "b", "c", "d", "e");
// Let's write the rows one by one (the first row will be skipped)
for (int i = 1; i < rows.size(); i++) {
// You can write comments above each row
writer.commentRow("This is row " + i);
// writes the row
writer.writeRow(rows.get(i));
}
// we must close the writer. This also closes the java.io.Writer you used to create the CsvWriter instance
// note no checked exceptions are thrown here. If anything bad happens you'll get an IllegalStateException wrapping the original error.
writer.close();
//##CODE_END
// Let's just print the resulting CSV
printAndValidate(csvResult.toString());
}
@Test
public void example003WriteCsvWithFieldSelection() {
// Writing to an in-memory byte array. This will be printed out to the standard output so you can easily see the result.
ByteArrayOutputStream csvResult = new ByteArrayOutputStream();
// CsvWriter (and all other file writers) work with an instance of java.io.Writer
Writer outputWriter = new OutputStreamWriter(csvResult);
//##CODE_START
CsvWriterSettings settings = new CsvWriterSettings();
// when writing, nulls are printed using the empty value (defaults to "").
// Here we configure the writer to print ? to describe null values.
settings.setNullValue("?");
// if the value is not null, but is empty (e.g. ""), the writer will can be configured to
// print some default representation for a non-null/empty value
settings.setEmptyValue("!");
// Encloses all records within quotes even when they are not required.
settings.setQuoteAllFields(true);
// Sets the file headers (used for selection, these values won't be written automatically)
settings.setHeaders("Year", "Make", "Model", "Description", "Price");
// Selects which fields from the input should be written. In this case, fields "make" and "model" will be empty
// The field selection is not case sensitive
settings.selectFields("description", "price", "year");
// Creates a writer with the above settings;
CsvWriter writer = new CsvWriter(outputWriter, settings);
// Writes the headers specified in the settings
writer.writeHeaders();
// writes each row providing values for the selected fields (note the values and field selection order must match)
writer.writeRow("ac, abs, moon", 3000.00, 1997);
writer.writeRow("", 4900.00, 1999); // NOTE: empty string will be replaced by "!" as per configured emptyQuotedValue.
writer.writeRow("MUST SELL!\nair, moon roof, loaded", 4799.00, 1996);
writer.close();
//##CODE_END
// Let's just print the resulting CSV
printAndValidate(csvResult.toString());
}
@Test
public void example004WriteFixedWidthUsingConversions() {
// Writing to an in-memory byte array. This will be printed out to the standard output so you can easily see the result.
ByteArrayOutputStream fixedWidthResult = new ByteArrayOutputStream();
// CsvWriter (and all other file writers) work with an instance of java.io.Writer
Writer outputWriter = new OutputStreamWriter(fixedWidthResult);
//##CODE_START
FixedWidthFields lengths = new FixedWidthFields(15, 10, 35);
FixedWidthWriterSettings settings = new FixedWidthWriterSettings(lengths);
// Any null values will be written as 'nil'
settings.setNullValue("nil");
settings.getFormat().setPadding('_');
settings.setIgnoreLeadingWhitespaces(false);
settings.setIgnoreTrailingWhitespaces(false);
// Creates an ObjectRowWriterProcessor that handles annotated fields in the TestBean class.
ObjectRowWriterProcessor processor = new ObjectRowWriterProcessor();
settings.setRowWriterProcessor(processor);
// Converts objects in the "date" field using the yyyy-MMM-dd format.
processor.convertFields(Conversions.toDate(Locale.ENGLISH," yyyy MMM dd "), Conversions.trim()).add("date");
// Trims Strings at position 2 of the input row.
processor.convertIndexes(Conversions.trim(), Conversions.toUpperCase()).add(2);
// Sets the file headers so the writer knows the correct order when writing values taken from a TestBean instance
settings.setHeaders("date", "quantity", "comments");
// Creates a writer with the above settings;
FixedWidthWriter writer = new FixedWidthWriter(outputWriter, settings);
// Writes the headers specified in the settings
writer.writeHeaders();
// writes a Fixed Width row with the values set in "bean". Notice that there's no annotated
// attribute for the "date" column, so it will just be null (an then converted to ? a )
writer.processRecord(new Date(0), null, " a comment ");
writer.processRecord(null, 1000, "");
writer.close();
//##CODE_END
// Let's just print the resulting fixed width output
printAndValidate(fixedWidthResult.toString());
}
@Test
public void example005WriteFixedWidthUsingAnnotatedBean() {
// Writing to an in-memory byte array. This will be printed out to the standard output so you can easily see the result.
ByteArrayOutputStream fixedWidthResult = new ByteArrayOutputStream();
// CsvWriter (and all other file writers) work with an instance of java.io.Writer
Writer outputWriter = new OutputStreamWriter(fixedWidthResult);
//##CODE_START
FixedWidthFields lengths = new FixedWidthFields(10, 10, 35, 10, 40);
FixedWidthWriterSettings settings = new FixedWidthWriterSettings(lengths);
// Any null values will be written as ?
settings.setNullValue("?");
// Creates a BeanWriterProcessor that handles annotated fields in the TestBean class.
settings.setRowWriterProcessor(new BeanWriterProcessor<TestBean>(TestBean.class));
// Sets the file headers so the writer knows the correct order when writing values taken from a TestBean instance
settings.setHeaders("amount", "pending", "date", "quantity", "comments");
// Creates a writer with the above settings;
FixedWidthWriter writer = new FixedWidthWriter(outputWriter, settings);
// Writes the headers specified in the settings
writer.writeHeaders();
// writes a fixed width row with empty values (as nothing was set in the TestBean instance).
writer.processRecord(new TestBean());
TestBean bean = new TestBean();
bean.setAmount(new BigDecimal("500.33"));
bean.setComments("Blah,blah");
bean.setPending(false);
bean.setQuantity(100);
// writes a Fixed Width row with the values set in "bean". Notice that there's no annotated
// attribute for the "date" column, so it will just be null (an then converted to ?, as we have settings.setNullValue("?");)
writer.processRecord(bean);
// you can still write rows passing in its values directly.
writer.writeRow(BigDecimal.ONE, true, "1990-01-10", 3, null);
writer.close();
//##CODE_END
// Let's just print the resulting fixed width output
printAndValidate(fixedWidthResult.toString());
}
@Test
public void example006WriteSimpleTsv() {
// Writing to an in-memory byte array. This will be printed out to the standard output so you can easily see the result.
ByteArrayOutputStream tsvResult = new ByteArrayOutputStream();
// TsvWriter (and all other file writers) work with an instance of java.io.Writer
Writer outputWriter = new OutputStreamWriter(tsvResult);
//##CODE_START
// As with the CsvWriter, all you need is to create an instance of TsvWriter with the default TsvWriterSettings.
TsvWriter writer = new TsvWriter(outputWriter, new TsvWriterSettings());
// Write the record headers of this file
writer.writeHeaders("Year", "Make", "Model", "Description", "Price");
// Here we just tell the writer to write everything and close the given output Writer instance.
writer.writeRowsAndClose(rows);
//##CODE_END
// Let's just print the resulting TSV
printAndValidate(tsvResult.toString());
}
@Test
public void example007WriteValues() {
// Writing to an in-memory byte array. This will be printed out to the standard output so you can easily see the result.
ByteArrayOutputStream tsvResult = new ByteArrayOutputStream();
// TsvWriter (and all other file writers) work with an instance of java.io.Writer
Writer outputWriter = new OutputStreamWriter(tsvResult);
// As with the CsvWriter, all you need is to create an instance of TsvWriter with the default TsvWriterSettings.
//##CODE_START
TsvWriter writer = new TsvWriter(outputWriter, new TsvWriterSettings());
writer.writeHeaders("A", "B", "C", "D", "E");
//writes a value to the first column
writer.addValue(10);
//writes a value to the second column
writer.addValue(20);
//writes a value to the fourth column (index 3 represents the 4th column - the one with header "D")
writer.addValue(3, 40);
//overrides the value in the first column. "A" indicates the header name.
writer.addValue("A", 100.0);
//flushes all values to the output, creating a row.
writer.writeValuesToRow();
//##CODE_END
// Here we just tell the writer to close the given output Writer instance.
writer.close();
// Let's just print the resulting TSV
printAndValidate(tsvResult.toString());
}
@Test
public void example008WriteWithHeaderAnnotation() {
//##CODE_START
TsvWriterSettings settings = new TsvWriterSettings();
settings.setRowWriterProcessor(new BeanWriterProcessor<AnotherTestBean>(AnotherTestBean.class));
// We didn't provide a java.io.Writer here, so all we can do is write to Strings (streaming)
TsvWriter writer = new TsvWriter(settings);
// Let's write the headers declared in @Headers annotation of AnotherTestBean
String headers = writer.writeHeadersToString();
// Now, let's create an instance of our bean
AnotherTestBean bean = new AnotherTestBean();
bean.setPending(true);
bean.setDate(2012, Calendar.AUGUST, 5);
// Calling processRecordToString will write the contents of the bean in a TSV formatted String
String row1 = writer.processRecordToString(bean);
// You can write whatever you need as well
String row2 = writer.writeRowToString("Random", "Values", "Here");
// Let's change our bean and produce another String
bean.setPending(false);
String row3 = writer.processRecordToString(bean);
//##CODE_END
println(headers);
println(row1);
println(row2);
println(row3);
printAndValidate();
}
@Test
public void example009WriteMapWithTypeConversion() {
CsvWriterSettings settings = new CsvWriterSettings();
// Using the object row writer processor, we can apply conversions to be applied by default over specific types/
//##CODE_START
ObjectRowWriterProcessor processor = new ObjectRowWriterProcessor();
//Strings are trimmed and lower cased by default
processor.convertType(String.class, Conversions.trim(), Conversions.toLowerCase());
// If a null is written to our boolean column, we want to print "N/A", otherwise Y and N for true and false.
// Note that column-specific conversions also prevent the type-conversions to be applied.
// The lower case conversion applied over Strings won't execute on this column.
processor.convertFields(Conversions.toBoolean(null, "N/A", "Y", "N")).add("Boolean column");
settings.setRowWriterProcessor(processor);
settings.setHeaderWritingEnabled(true);
//Let's create a CSV writer
CsvWriter writer = new CsvWriter(settings);
//Creating a map of rows to write our data. Keys will be used as the headers
//Each entry contains the values of a column
Map<String, Object[]> rows = new LinkedHashMap<String, Object[]>();
rows.put("String column", new Object[]{" Paid ", " PAID", "\npaid"});
rows.put("Boolean column", new Object[]{null, true, false});
rows.put("Last column", new Object[]{199, 288, 11});
//Let's write everything into a list of Strings. Each element of the list will be a new row
List<String> writtenRows = writer.processObjectRecordsToString(rows);
for (String row : writtenRows) {
println(row);
}
//##CODE_END
printAndValidate();
}
@Test
public void example010MultiSchemaWrite() {
//##CODE_START
//creates a switch that will use a different row processor for writing a row, based on values at column 0.
OutputValueSwitch writerSwitch = new OutputValueSwitch("type");
// If the value is "SUPER", we want to use an ObjectRowWriterProcessor.
// Field names "type", "field1" and "field2" will be associated with this row processor
writerSwitch.addSwitchForValue("SUPER", new ObjectRowWriterProcessor(), "type", "field1", "field2");
// If the value is "DUPER", another ObjectRowWriterProcessor will be used.
// Field names "type", "A", "B" and "C" will be used here
writerSwitch.addSwitchForValue("DUPER", new ObjectRowWriterProcessor(), "type", "A", "B", "C");
CsvWriterSettings settings = new CsvWriterSettings();
// configure the writer to use the switch
settings.setRowWriterProcessor(writerSwitch);
//rows with less values than expected will be expanded, i.e. empty columns will be written
settings.setExpandIncompleteRows(true);
settings.getFormat().setLineSeparator("\n");
settings.setHeaderWritingEnabled(false);
StringWriter output = new StringWriter();
CsvWriter writer = new CsvWriter(output, settings);
Map<String, Object> duperValues = new HashMap();
duperValues.put("type", "DUPER");
duperValues.put("A", "value A");
duperValues.put("B", "value B");
duperValues.put("C", "value C");
writer.processRecord(new Object[]{"SUPER", "Value 1", "Value 2"}); //writing an array
writer.processRecord(duperValues); //writing a map
duperValues.remove("A"); //no data for column "A"
duperValues.put("B", 5555); //updating the value of B
duperValues.put("D", null); //not included, will be ignored
writer.processRecord(duperValues);
writer.processRecord(new Object[]{"SUPER", "Value 3"}); //no value for column "field2", an empty column will be written
writer.close();
print(output.toString());
//##CODE_END
printAndValidate();
}
@Test
public void example011MultiSchemaWriteWithBeans() {
//##CODE_START
//creates a switch that will use a different row processor for writing a row, based on values at column 0.
OutputValueSwitch writerSwitch = new OutputValueSwitch("type");
// If the value is "SUPER", we want to use an ObjectRowWriterProcessor.
// Field names "type", "field1" and "field2" will be associated with this row processor
writerSwitch.addSwitchForValue("SUPER", new ObjectRowWriterProcessor(), "type", "field1", "field2");
//we are going to write instances of Car
writerSwitch.addSwitchForType(Car.class); //you can also define specific fields to write by giving a list of header names/column indexes.
CsvWriterSettings settings = new CsvWriterSettings();
// configure the writer to use the switch
settings.setRowWriterProcessor(writerSwitch);
settings.getFormat().setLineSeparator("\n");
settings.setHeaderWritingEnabled(false);
StringWriter output = new StringWriter();
CsvWriter writer = new CsvWriter(output, settings);
writer.processRecord(new Object[]{"SUPER", "Value 1", "Value 2"}); //writing an array
//Here's our car
Car car = new Car();
car.setYear(2012);
car.setMake("Toyota");
car.setModel("Camry");
car.setPrice(new BigDecimal("10000"));
writer.processRecord(car);
//And another car
car.setYear(2014);
car.setPrice(new BigDecimal("12000"));
writer.processRecord(car);
writer.processRecord(new Object[]{"SUPER", "Value 3"}); //no value for column "field2", an empty column will be written
writer.close();
print(output.toString());
//##CODE_END
printAndValidate();
}
@Test
public void example012WriteMapWithHeaderMapping() {
StringWriter output = new StringWriter();
TsvWriterSettings settings = new TsvWriterSettings();
//##CODE_START
settings.setHeaderWritingEnabled(true);
TsvWriter writer = new TsvWriter(output, settings);
//Creating a map of rows to write our data.
//Each entry contains the values of a column
Map<Long, Object> values = new HashMap<Long, Object>();
values.put(5L, "value @ 5");
values.put(7L, "value @ 7");
values.put(10L, "value @ 10");
//we want to write the data stored in the map above, but the keys don't make any sense as column headers.
//This can be easily solved with a map of headers:
Map<Long, String> headerMapping = new HashMap<Long, String>();
headerMapping.put(5L, "Header 5");
headerMapping.put(7L, "Header 7");
headerMapping.put(10L, "Header 10");
writer.writeRow(headerMapping, values);
values.put(5L, "other @ 5");
values.put(10L, "other @ 10");
values.put(11L, "something else entirely"); //will be ignored
writer.writeRow(headerMapping, values);
writer.close();
println(output.toString());
//##CODE_END
printAndValidate();
}
}