Input
Every
Pnyx works on an input, typically from
Stream, but can be any thing that
implements
IProcessor. All input done for a
Pnyx is done during the
process state (see
State Machine for details). Some of the details for reading
input are documented below.
Encoding
Pnyx uses the file's "Byte Order Mark" (
BOM) to determine its encoding. If file does not
contain BOM, then encoding defaults to
Settings.defaultEncoding. Use the
Settings, either globally or for specific
Pnyx
to control how files are decoded. The following example shows reading UTF-8 files.
Specific Encoding
await using (Pnyx p = new Pnyx())
{
p.setSettings(defaultEncoding: Encoding.UTF8, detectEncodingFromByteOrderMarks: false);
p.read("myfile.txt");
p.writeStdout();
}
// Reads a UTF-8 file regardless of BOM (or lack thereof)
Newlines
When reading from a
Stream, newlines can be either in Unix, Mac or Windows format, or even mixed together in the same file. Stream parsing
uses the first newline character(s) to write to output, in an attempt to maintain the source's original newlines. Finally, parsing keeps track of
whether the file is terminated by a newline or not. If so, then the output will also be terminated by a newline.
Newline Parsing
const String input = "1\n2\r\n3\r4";
await using (Pnyx p = new Pnyx())
{
p.readString(input);
p.writeStdout();
}
// outputs: 1\n2\n3\n4
Custom Sources
To build a custom source, implement
IProcessor and at least one of
ILinePart,
IRowPart,
IObjectPart or
INameValuePairPart.
The
process method should read or generate all data in one call. Data is pushed to the next
IProcessor as
it becomes available. On every loop,
StreamInformation.active should be checked, to determine if process should terminate
prior to exhausting input.
Finally, any clean up of resources should be handled by implementing
IAsyncDisposable. The following example
illustrates these points with a custom source to generate
Row data.
rowPart
public class CustomRowSource : IProcessor, IRowPart
{
private readonly StreamInformation streamInformation;
private int countDown;
private IRowProcessor? processor;
public CustomRowSource(StreamInformation streamInformation, int countDown)
{
this.streamInformation = streamInformation;
this.countDown = countDown;
}
public async Task process()
{
DateTime date = new DateTime(2013, 4, 2);
while (countDown >= 0 && streamInformation.active)
{
String columnA = countDown.ToString();
String columnB = date.ToString(DateUtil.FORMAT_MDYYYY);
List<String?> row = new List<String?> { columnA, columnB };
await processor!.processRow(row);
countDown--;
date = date.AddDays(-7);
}
await processor!.endOfFile(); // flushes buffering and output
}
public void setNextRowProcessor(IRowProcessor next)
{
processor = next;
}
}
await using (Pnyx p = new Pnyx())
{
p.readRow(new CustomRowSource(p.streamInformation, 40), new CsvRowConverter());
p.head(3);
p.writeStdout();
}
// outputs:
// 40,4/2/2013
// 39,3/26/2013
// 38,3/19/2013
Next
Suggested next steps:
- Line, learn more about Line operations
- Row, learn more about Row operations
- Object, examples of Object operations
- NameValuePair, examples of Name-Value Pair operations
- Output, learn more about Output operations
- Settings, learn more about settings