Loading data from 11 column CSV file into separate collections - c#

First off i'm a bit of a novice at C#
So I have a CSV file with 11 columns and over 20,000 rows, its just a bunch of data from a sports tracking gps. What I want to do is be able to take that data from the CSV and load each column into a seperate collection, however I can't get it to work the way I want it.
I've spent ages searching up how to do this properly, but all i've managed to muster together this janky code that does load all the data into the collections, but will only let me load each piece of data into the collection as a string (not as decimal or char, which I need for some [yes I've tried delcaring the collections as decimal or char before]).
So what I need help with is being able to actually load the data from the CSV file into the collection as the data type I want, and if there's an easy way to skip the first 8 or so lines which are just headers.
The list of data types I require are as follows (in order of declared)
decimal
decimal
char
decimal
char
decimal
string
string
decimal
decimal
string
Here is the code i'm currently using:
//Seprate class for all the collection declarations
public static class GPSdata
{
public static List<string> time = new List<string>(); //time (in seconds, advances by 0.2)
public static List<string> lat = new List<string>(); //Latitude
public static List<string> NS = new List<string>(); //North/South
public static List<string> lon = new List<string>(); //Longtitude
public static List<string> EW = new List<string>(); //East/West
public static List<string> knots = new List<string>(); //Speed in Knots
public static List<string> date = new List<string>(); //Date [ddmmyy]
public static List<string> sats = new List<string>(); //**No clue**
public static List<string> HDOP = new List<string>(); //Satelite Horizontal error
public static List<string> alt = new List<string>(); //Elevation (above msl)
public static List<string> rawSV = new List<string>(); //Space Vehicle
}
//Method for loading the CSV data into the collections
public void LoadCSV(string filepath)
{
using (StreamReader reader = new StreamReader(filepath))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
GPSdata.time.Add(values[0]);
GPSdata.lat.Add(values[1]);
GPSdata.NS.Add(values[2]);
GPSdata.lon.Add(values[3]);
GPSdata.EW.Add(values[4]);
GPSdata.knots.Add(values[5]);
GPSdata.date.Add(values[6]);
GPSdata.sats.Add(values[7]);
GPSdata.HDOP.Add(values[8]);
GPSdata.rawSV.Add(values[9]);
GPSdata.alt.Add(values[10]);
}
}
}
Also heres an example of the data from the file i'm reading off:
31350.2,3750.9188,S,14458.8652,E,7.98,50817,0,2.3,0,23
31350.4,3750.9204,S,14458.867,E,6.66,50817,0,2.3,0,23

Sounds like you are asking two questions here, parsing text into other datatypes, which is discussed in the other answer. here another question that describes that in better detail. String Parsing in C#. The second part you are asking is about skipping header information in you csv files. Use the ReadLine() method on the StreamReader to skip some lines like so:
using (StreamReader reader = new StreamReader(filepath))
{
for(int i = 0; i<8; ++i){
reader.ReadLine();
}
while (!reader.EndOfStream)
{
// the stuff you are already doing
}
}

Separate collection for each property is not the proper approach.
This may be what you are looking for:
public class GPSdata
{
public TimeSpan time { get; set; } //time (in seconds, advances by 0.2)
public int latDegrees { get; set; } //Latitude
public int latMinutes { get; set; } //Latitude
public int latSeconds { get; set; } //Latitude
public string NS { get; set; } //North/South
public int lonDegrees { get; set; } //Longtitude
public int lonMinutes { get; set; } //Longtitude
public int lonSeconds { get; set; } //Longtitude
public string EW { get; set; } //East/West
public decimal knots { get; set; } //Speed in Knots
public DateTime date { get; set; } //Date [ddmmyy]
public int sats { get; set; } //**No clue**
public decimal HDOP { get; set; } //Satelite Horizontal error
public decimal alt { get; set; } //Elevation (above msl)
public int rawSV { get; set; } //Space Vehicle
}
public static List<GPSdata> LoadCSV(string filepath)
{
List<GPSdata> data = new List<GPSdata>();
using (StreamReader reader = new StreamReader(filepath))
{
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
string[] values = line.Split(',');
GPSdata gpsdata = new GPSdata();
gpsdata.time = new TimeSpan((long)(decimal.Parse(values[0]) * (decimal)1.0E07));
int latDecimalPoint = values[1].IndexOf(".");
gpsdata.latSeconds = int.Parse(values[1].Substring(latDecimalPoint + 1));
gpsdata.latMinutes = int.Parse(values[1].Substring(latDecimalPoint - 2, 2));
gpsdata.latDegrees = int.Parse(values[1].Substring(0, latDecimalPoint - 2));
gpsdata.NS = values[2];
int lonDecimalPoint = values[3].IndexOf(".");
gpsdata.lonSeconds = int.Parse(values[3].Substring(lonDecimalPoint + 1));
gpsdata.lonMinutes = int.Parse(values[3].Substring(lonDecimalPoint - 2, 2));
gpsdata.lonDegrees = int.Parse(values[3].Substring(0, lonDecimalPoint - 2));
gpsdata.EW = values[4];
gpsdata.knots = decimal.Parse(values[5]);
int dateLen = values[6].Length;
gpsdata.date = new DateTime(int.Parse(values[6].Substring(dateLen - 2)), int.Parse(values[6].Substring(0, dateLen - 4)), int.Parse(values[6].Substring(dateLen - 4, 2)));
gpsdata.sats = int.Parse(values[7]);
gpsdata.HDOP = decimal.Parse(values[8]);
gpsdata.rawSV = int.Parse(values[9]);
gpsdata.alt = decimal.Parse(values[10]);
data.Add(gpsdata);
}
}
return data;
}

You class should look something like this. The E/W is positive or negative longitude and S/N is positive or negative latitude.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.csv";
static void Main(string[] args)
{
new GPSdata(FILENAME);
}
}
//Seprate class for all the collection declarations
public class GPSdata
{
public static List<GPSdata> data = new List<GPSdata>();
public TimeSpan time { get; set; } //time (in seconds, advances by 0.2)
public int latDegrees { get; set; } //Latitude
public int latMinutes { get; set; } //Latitude
public int latSeconds { get; set; } //Latitude
public string NS { get; set; } //North/South
public int lonDegrees { get; set; } //Longtitude
public int lonMinutes { get; set; } //Longtitude
public int lonSeconds { get; set; } //Longtitude
public string EW { get; set; } //East/West
public decimal knots { get; set; } //Speed in Knots
public DateTime date { get; set; } //Date [ddmmyy]
public int sats { get; set; } //**No clue**
public decimal HDOP { get; set; } //Satelite Horizontal error
public decimal alt { get; set; } //Elevation (above msl)
public int rawSV { get; set; } //Space Vehicle
public GPSdata() { }
public GPSdata(string filepath)
{
int lineNumber = 0;
StreamReader reader = new StreamReader(filepath);
string line = "";
while ((line = reader.ReadLine()) != null)
{
if (++lineNumber > 8)
{
try
{
string[] values = line.Split(',');
GPSdata gpsdata = new GPSdata();
GPSdata.data.Add(gpsdata);
gpsdata.time = new TimeSpan((long)(decimal.Parse(values[0]) * (decimal)1.0E07));
int latDecimalPoint = values[1].IndexOf(".");
gpsdata.latSeconds = int.Parse(values[1].Substring(latDecimalPoint + 1));
gpsdata.latMinutes = int.Parse(values[1].Substring(latDecimalPoint - 2, 2));
gpsdata.latDegrees = int.Parse(values[1].Substring(0, latDecimalPoint - 2));
gpsdata.NS = values[2];
int lonDecimalPoint = values[3].IndexOf(".");
gpsdata.lonSeconds = int.Parse(values[3].Substring(lonDecimalPoint + 1));
gpsdata.lonMinutes = int.Parse(values[3].Substring(lonDecimalPoint - 2, 2));
gpsdata.lonDegrees = int.Parse(values[3].Substring(0, lonDecimalPoint - 2));
gpsdata.EW = values[4];
gpsdata.knots = decimal.Parse(values[5]);
int dateLen = values[6].Length;
gpsdata.date = new DateTime(int.Parse(values[6].Substring(dateLen - 2)), int.Parse(values[6].Substring(0, dateLen - 4)), int.Parse(values[6].Substring(dateLen - 4, 2)));
gpsdata.sats = int.Parse(values[7]);
gpsdata.HDOP = decimal.Parse(values[8]);
gpsdata.rawSV = int.Parse(values[9]);
gpsdata.alt = decimal.Parse(values[10]);
}
catch (Exception ex)
{
Console.WriteLine("Error Line Number : '{0}', Text : '{1}'", lineNumber,line);
}
}
}
Console.ReadLine();
}
}
}

Related

How can I sort 4 seperate string arrays (with the same lenght), according to one of them in alphabetical order? (in C#)

I have read out per WMI the installed programs on a remote PC. I have read the Program Name, Program Publisher, Program Install.date and Program install.path properties and stored each of them in a separate string array. (All arrays with same length: 99)
I want to list the program informations according to the alphabetical order of Program name.
Is it possible to do that without combining the 4 arrays in one multidimensional array?
Or should I first combine the arrays to one two dimensional array ?
If yes how?
As I am new in C# I would thank you if you would make a suggestion. I have read lots of entries but I got more confused.
public string[] Programs_WMI_name = new string[99];
public string[] Programs_WMI_publisher = new string[99];
public string[] Programs_WMI_installdate = new string[99];
public string[] Programs_WMI_installlocation = new string[99];
I have tried this but get error:
In my public Class
public class TagService{
public string Programs_WMI_Name { get; set; }
public string Programs_WMI_Publisher { get; set; }
public string Programs_WMI_Installdate { get; set; }
public string Programs_WMI_Installlocation { get; set; }
public List<string> programs = new List<string>(99);
}
then
for (int i = 0; i < TagService.Programs_WMI_name.Length; i++)
{
programs.Add(new TagService
{
Programs_WMI_Name = TagService.Programs_WMI_name[i],
Programs_WMI_Publisher = TagService.Programs_WMI_publisher[i],
Programs_WMI_Installdate = TagService.Programs_WMI_installdate[i],
Programs_WMI_Installlocation = TagService.Programs_WMI_installlocation[i],
});
}
programs = programs.OrderBy(p => p.Programs_WMI_Name).ToList();
Do yourself and others a favor and use classes
public class ProgramInfo
{
public string Name { get; set; }
public string Publisher { get; set; }
public string InstallDate { get; set; }
public string InstallLocation { get; set; }
}
from arrays
var programs = new List<ProgramInfo>(Programs_WMI_name.Length);
for (int i = 0; i < Programs_WMI_name.Length; i++)
{
programs.Add(new ProgramInfo
{
Name = Programs_WMI_name[i],
Publisher = Programs_WMI_publisher[i],
InstallDate = Programs_WMI_installdate[i],
InstallLocation = Programs_WMI_installlocation[i],
});
}
better yet fill from query directly
var programs = new List<ProgramInfo>();
foreach (var row in new ManagementObjectSearcher(somequery).Get())
{
programs.Add(new ProgramInfo
{
Name = row["name"],
Publisher = row["publisher"],
InstallDate = row["installdate"],
InstallLocation = row["installlocation"],
});
}
complete example could look like this
using System;
using System.Linq;
using System.Collections.Generic;
namespace Test
{
public class ProgramInfo
{
public string Name { get; set; }
public string Publisher { get; set; }
public string InstallDate { get; set; }
public string InstallLocation { get; set; }
}
public class TagService
{
public static List<ProgramInfo> Programs { get; } = new List<ProgramInfo>();
public static void RefreshPrograms()
{
Programs.Clear();
foreach (var row in new ManagementObjectSearcher(somequery).Get())
{
programs.Add(new ProgramInfo
{
Name = row["name"],
Publisher = row["publisher"],
InstallDate = row["installdate"],
InstallLocation = row["installlocation"],
});
}
Programs.Sort((l, r) => string.Compare(l.Name, r.Name));
}
}
public Program
{
public static void Main()
{
TagService.ReadPrograms();
var properties = typeof(ProgramInfo).GetProperties();
Console.WriteLine(string.Join("|", properties.Select(p => p.Name.PaddRight(10))));
foreach (var program in TagService.Programs)
{
Console.WriteLine(string.Join("|", properties.Select(p => ((string)p.GetValue(program)).PaddRight(10))));
}
}
}
}

Passing Data From Text File to Constructor

I'm looking for a way to pass information from a text file into a constructor so that I can create an array of that constructor object with each object in the array holding information from the rows of the text file.
The constructor is formatted as follows:
public Member(string name, int number, decimal rate, double hours)
While the text file is formatted as such:
Eric Wallace, 352456, 15.88, 32.20
Clara Kell, 233424, 35.88, 18.76
Darren Price, 656795, 27.82, 20.25
etc...
and each Member will go into an array.
In the end, what I need is for each row to be split up and passed to the constructor in a way where each row becomes its own member in an array so that they can be output one after another in a loop or called individually as rows.
My approach would begin with making an interface that all my "buildable" data types will implement. I want my data models deciding how they are built from a string:
public interface IBuildableFromString
{
public IBuildableFromString Build(string str, string seperator = ",");
}
Then make Member implement it like so:
public class Member : IBuildableFromString
{
public string Name { get; set; }
public int Number { get; set; }
public decimal Rate { get; set; }
public double Hours { get; set; }
public Member() { }
public Member(string name, int number, decimal rate, double hours)
{
Name = name;
Number = number;
Rate = rate;
Hours = hours;
}
public IBuildableFromString Build(string str, string seperator = ",")
{
try
{
string[] parts = str.Split(seperator);
return new Member(parts[0], int.Parse(parts[1]),
decimal.Parse(parts[2]), double.Parse(parts[3]));
}
catch
{
return null;
}
}
}
Then the method to read the file and build the object data:
public static T[] BuildData<T>(string filePath) where T :
IBuildableFromString, new()
{
List<T> dataObjects = new List<T>();
string[] lines = File.ReadAllLines(filePath);
foreach (string line in lines)
{
if (!String.IsNullOrEmpty(line))
{
var newMember = new T().Build(line);
if (newMember != null)
dataObjects.Add((T)newMember);
}
}
return dataObjects.ToArray();
}
Lastly, call the function above like so:
static void Main(string[] args)
{
var data = BuildData<Member>(#"path_to_your_file.txt");
}
It probably needs more error checking, but this was the most extensible way I could think of doing it. Cheers!
As long as your file is well-formed, then this would work:
Member[] members =
File
.ReadLines(#"mytextfile.txt")
.Select(x => x.Split(',').Select(y => y.Trim()).ToArray())
.Select(x => new Member(x[0], int.Parse(x[1]), decimal.Parse(x[2]), double.Parse(x[3])))
.ToArray();
I will use StreamReader to read the txt file, then use replace to eliminate spaces, and then use split to split the data.
Use StreamReader to read text from a file:
StreamReader sr = new StreamReader(#"C:\demo\de.txt")
Make Member implement it like so:
public class Member {
public string Name { get; set; }
public int Number { get; set; }
public decimal Rate { get; set; }
public double Hours { get; set; }
public Member(string name, int number, decimal rate, double hours) {
Name = name;
Number = number;
Rate = rate;
Hours = hours;
}
}
Call the data like this:
foreach (var item in members) {
Console.WriteLine($"{ item.Name} { item.Number} { item.Rate} { item.Hours}");
}
Total code:
using System;
using System.Collections.Generic;
using System.IO;
namespace ConsoleApp2 {
class Program {
static void Main(string[] args) {
List<Member> members = new List<Member>();
try {
// Create an instance of StreamReader to read from a file.
// The using statement also closes the StreamReader.
using (StreamReader sr = new StreamReader(#"C:\demo\de.txt")) {
string line;
// Read and display lines from the file until the end of
// the file is reached.
while ((line = sr.ReadLine()) != null) {
line = line.Replace(" ", "");
string[] tmp = line.Split(',');
string name = tmp[0];
int number = Convert.ToInt32(tmp[1]);
decimal rate = Convert.ToDecimal(tmp[2]);
double hours = Convert.ToDouble(tmp[3]);
members.Add(new Member(name, number, rate, hours));
}
}
} catch (Exception e) {
// Let the user know what went wrong.
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
foreach (var item in members) {
Console.WriteLine($"{ item.Name} { item.Number} { item.Rate} { item.Hours}");
}
Console.ReadLine();
}
public class Member {
public string Name { get; set; }
public int Number { get; set; }
public decimal Rate { get; set; }
public double Hours { get; set; }
public Member(string name, int number, decimal rate, double hours) {
Name = name;
Number = number;
Rate = rate;
Hours = hours;
}
}
}
}
If you have questions, please add a comment.

C# receiving json string but unable to deserialize it

i have an application that has to deserialize an array of data wrapped in a "results" Root Object, using Netwonsoft.Json package from NuGet
The Json string is exactly this:
{"results":[{"Coin":"SBD","LP":0.000269,"PBV":-54.36,"MACD1M":true,"MACD30M":true,"MACD1H":true,"MACD1D":true},{"Coin":"XMR","LP":0.027135,"PBV":11.44,"MACD1M":true,"MACD30M":true,"MACD1H":true,"MACD1D":true}]}
This Json string is created from a Console App i made, i wanted it to look like this https://bittrex.com/Api/v2.0/pub/market/GetTicks?marketName=BTC-NEO&tickInterval=hour
My class looks like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WindowsFormsApp2
{
public class Result
{
public string Coins { get; set; }
public decimal LastPrice { get; set; }
public decimal PercentBuyVolume { get; set; }
}
public class RootObject
{
public List<Result> results { get; set; }
}
}
In the Main form i have a function to download from a URL that Json (i have XAMPP running Apache) and deserialize it in an array. And it looks like this:
private void DownloadBittrexData()
{
int PanelID = 0;
var Coin = new List<string>();
var LastPrice = new List<decimal>();
var PercentBuyVolume = new List<decimal>();
var MACD1M = new List<bool>();
var MACD30M = new List<bool>();
var MACD1H = new List<bool>();
var MACD1D = new List<bool>();
var client = new WebClient();
var URL = client.DownloadString("http://localhost/test.json");
Console.WriteLine("Json String from URL: " + URL);
var dataDeserialized = JsonConvert.DeserializeObject<RootObject>(URL);
foreach (var data in dataDeserialized.results)
{
Coin.Add(data.Coins);
LastPrice.Add(data.LastPrice);
PercentBuyVolume.Add(data.PercentBuyVolume);
}
int sizeOfArrayClose = Coin.Count - 1;
for (int i = 0; i <= sizeOfArrayClose; i++)
{
Console.WriteLine("Coin: " + Coin[i]);
Console.WriteLine("Lastprice: " + LastPrice[i]);
Console.WriteLine("PBV: " + PercentBuyVolume[i]);
}
}
Newtonsoft.Json is of course declared at the beginning of the form together with System.Net
using System.Net;
using Newtonsoft.Json;
The output looks like this:
Json String from URL: {"results":[{"Coin":"SBD","LP":0.000269,"PBV":-54.36,"MACD1M":true,"MACD30M":true,"MACD1H":true,"MACD1D":true},{"Coin":"XMR","LP":0.027135,"PBV":11.44,"MACD1M":true,"MACD30M":true,"MACD1H":true,"MACD1D":true}]}
Coin:
Lastprice: 0
PBV: 0
Coin:
Lastprice: 0
PBV: 0
It's like it fails to deserialize it after downloading it.
What should i do? Thank you very much.
Your property names don't map to the field names in the JSON. You could rename your C# properties to match the JSON, but it would make for unreadable downstream code.
Instead, you should map your properties (with nice, readable names) to the names that appear in the JSON, using JsonPropertyAttribute:
public class Result
{
public string Coin { get; set; } //didn't bother here: changed property name to Coin
[JsonProperty("LP")]
public decimal LastPrice { get; set; }
[JsonProperty("PBV")]
public decimal PercentBuyVolume { get; set; }
}
your model should be like this for deserialize json
public class Result
{
public string Coin { get; set; }
public double LP { get; set; }
public double PBV { get; set; }
public bool MACD1M { get; set; }
public bool MACD30M { get; set; }
public bool MACD1H { get; set; }
public bool MACD1D { get; set; }
}
public class RootObject
{
public List<Result> results { get; set; }
}
LastPrice and PercentBuyVolume are not available in your model that's the reason it's getting an error.
I tried your exact code on my system and I was able to retrieve the result as expected. Hope this helps, It's easy to understand.
Here is the main class
static void Main(string[] args)
{
RootObject configfile = LoadJson();
foreach (var tResult in configfile.results)
{
Console.WriteLine("Coin: " + tResult.Coin);
Console.WriteLine("Lastprice: " + tResult.LP);
Console.WriteLine("PBV: " + tResult.PBV);
}
Console.ReadLine();
}
LoadJson Function would be
private static RootObject LoadJson()
{
string json = "{\"results\":[{\"Coin\":\"SBD\",\"LP\":0.000269,\"PBV\":-54.36,\"MACD1M\":true,\"MACD30M\":true,\"MACD1H\":true,\"MACD1D\":true},{\"Coin\":\"XMR\",\"LP\":0.027135,\"PBV\":11.44,\"MACD1M\":true,\"MACD30M\":true,\"MACD1H\":true,\"MACD1D\":true}]}";
RootObject configs = Deserialize<RootObject>(json);
return configs;
}
and Deserialize function would be
private static T Deserialize<T>(string json)
{
T unsecureResult;
string _DateTypeFormat = "yyyy-MM-dd HH:mm:ss";
DataContractJsonSerializerSettings serializerSettings = new DataContractJsonSerializerSettings();
DataContractJsonSerializer serializer;
MemoryStream ms;
unsecureResult = default(T);
serializerSettings.DateTimeFormat = new System.Runtime.Serialization.DateTimeFormat(_DateTypeFormat);
serializer = new DataContractJsonSerializer(typeof(T));
ms = new MemoryStream(Encoding.Unicode.GetBytes(json));
unsecureResult = (T)serializer.ReadObject(ms);
return unsecureResult;
}
and Now your Datamodel would be
public class Result
{
public string Coin { get; set; }
public double LP { get; set; }
public double PBV { get; set; }
public bool MACD1M { get; set; }
public bool MACD30M { get; set; }
public bool MACD1H { get; set; }
public bool MACD1D { get; set; }
}
public class RootObject
{
public List<Result> results { get; set; }
}

EDI Fabric .ToEDI() has empty group fields

I'm using EDIFabric to build up an interchange and single message. I have a very simple format I need to output to an EDI x12 string. My code populates the interchange and group properly (viewing the local variables and collections), however when I run .ToEdi() on my interchange object I'm getting back empty message groups
My Output:
"ISA*00* *00* *IS*SenderID *IS*ReceiverID *160809*1008*^*00501*000001ISA*0*P*:~GS*FA*GS_02_SenderCode*GS_03_ReceiverCode*21160809*1008*00001GS06*X*005010~ST~AK1~AK2~IK3~IK5~AK9~SE~GE*000001*00001GS06~IEA*00001*000001ISA~"
Empty when shouldn't be
ST~AK1~AK2~IK3~IK5~AK9~SE~GE
Creation class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EdiFabric.Framework.Envelopes.X12;
using EdiFabric.Definitions.Hipaa_005010_999_X231;
using EdiFabric.Framework.Messages;
using EdiFabric.Framework.Envelopes;
namespace X12PayloadProcessing
{
public class DS_M_999
{
private DS_M_999_Interchange _Interchange;
private DS_M_999_Group _Group;
private Message _EDI_Message;
private S_ISA _EDI_ISA = new S_ISA();
private S_IEA _EDI_IEA = new S_IEA();
public Interchange _EDI_Interchange = new Interchange();
private S_GE _EDI_GE = new S_GE();
private S_GS _EDI_GS = new S_GS();
private Group _EDI_Group = new Group();
private M_999 _EDI_999 = new M_999();
private S_ST _EDI_ST = new S_ST();
private S_SE _EDI_SE = new S_SE();
private S_AK1 _EDI_AK1 = new S_AK1();
private S_AK2 _EDI_AK2 = new S_AK2();
private S_AK9 _EDI_AK9 = new S_AK9();
private S_IK3 _EDI_IK3 = new S_IK3();
private S_IK5 _EDI_IK5 = new S_IK5();
private List<G_TS999_2000> _EDI_2000_List = new List<G_TS999_2000>();
private G_TS999_2000 _EDI_2000 = new G_TS999_2000();
private G_TS999_2100 _EDI_2100 = new G_TS999_2100();
private List<G_TS999_2100> _EDI_2100_List = new List<G_TS999_2100>();
public DS_M_999(DS_M_999_Group Group, DS_M_999_Interchange Interchange)
{
_Group = Group;
_Interchange = Interchange;
_EDI_Interchange.Groups = new List<Group>();
_EDI_ISA.D_744_1 = _Interchange.ISA_01_Authorization.PadRight(2).Substring(0,2);
_EDI_ISA.D_745_2 = _Interchange.ISA_02_AuthInfo.PadRight(10).Substring(0,10);
_EDI_ISA.D_746_3 = _Interchange.ISA_03_SecurityQualifier.PadRight(2).Substring(0, 2);
_EDI_ISA.D_747_4 = _Interchange.ISA_04_Password.PadRight(10).Substring(0, 10);
_EDI_ISA.D_704_5 = _Interchange.ISA_05_SenderQualifier.PadRight(2).Substring(0, 2);
_EDI_ISA.D_705_6 = _Interchange.ISA_06_SenderId.PadRight(15).Substring(0,15);
_EDI_ISA.D_704_7 = _Interchange.ISA_07_ReceiverQualifier.PadRight(2).Substring(0, 2);
_EDI_ISA.D_706_8 = _Interchange.ISA_08_ReceiverId.PadRight(15).Substring(0, 15);
_EDI_ISA.D_373_9 = _Interchange.ISA_09_DateReceived.PadRight(6).Substring(0, 6);
_EDI_ISA.D_337_10 = _Interchange.ISA_10_TimeRecieved.PadRight(4).Substring(0, 4);
_EDI_ISA.D_726_11 = _Interchange.ISA_11_RepetitionSeparator.PadRight(1).Substring(0, 1);
_EDI_ISA.D_703_12 = _Interchange.ISA_12_X12Version.PadRight(5).Substring(0, 5);
_EDI_ISA.D_709_13 = _Interchange.ISA_13_UniqueNumberCounter.PadLeft(9,'0');
_EDI_ISA.D_749_14 = _Interchange.ISA_14_AcknoledgementRequested;
_EDI_ISA.D_748_15 = _Interchange.ISA_15_UsageIndicator;
_EDI_ISA.D_701_16 = _Interchange.ISA_16_CompElementSeparator;
_EDI_IEA.D_405_1 = _Interchange.IEA_01_FunctionalGroupCounter.PadLeft(5, '0');
_EDI_IEA.D_709_2 = _Interchange.IEA_02_UniqueNumberCounter.PadLeft(9, '0');
_EDI_Interchange.Iea = _EDI_IEA;
_EDI_Interchange.Isa = _EDI_ISA;
_EDI_GE.D_97_1 = _Interchange.GE_01_TransactionSetCounter.PadLeft(6, '0');
_EDI_GE.D_28_2 = _Interchange.GE_02_UniqueNumberCounter.PadLeft(9, '0');
_EDI_Group.Ge = _EDI_GE;
_EDI_GS.D_479_1 = _Interchange.GS_01.PadRight(2).Substring(0, 2);
_EDI_GS.D_142_2 = _Interchange.GS_02_SenderCode;
_EDI_GS.D_124_3 = _Interchange.GS_03_ReceiverCode;
_EDI_GS.D_29_4 = _Interchange.GS_04_DateReceived.PadRight(6).Substring(0, 8); //datetime.ToString("yyyyMMdd")
_EDI_GS.D_30_5 = _Interchange.GS_05_TimeReceived.PadRight(4).Substring(0, 4); //datetime.ToString("HHmm")
_EDI_GS.D_28_6 = _Interchange.GS_06_UniqueNumberCounter.PadLeft(9,'0');
_EDI_GS.D_455_7 = _Interchange.GS_07_AgencyCode.PadRight(1).Substring(0, 1);
_EDI_GS.D_480_8 = _Interchange.GS_08_X12Version.PadRight(6).Substring(0, 6);
_EDI_Group.Gs = _EDI_GS;
//Set ST Block
_EDI_ST.D_ST01 = X12_ID_143.Item999;
_EDI_ST.D_ST02 = _Group.ST_02_TransactionSetCounter;
_EDI_ST.D_ST03 = X12_ID_1705.Item005010X231A1;
_EDI_999.S_ST = _EDI_ST;
//Set AK1 Block
_EDI_AK1.D_AK101 = _Group.AK_101_FunctionalIdentifier;
_EDI_AK1.D_AK102 = _Group.AK_102_GroupControlNumber;
_EDI_AK1.D_AK103 = _Group.AK_103_VersionIdentifier;
_EDI_999.S_AK1 = _EDI_AK1;
_EDI_AK2.D_AK201 = _Group.AK_201_TransactionSetIdentifier;
_EDI_AK2.D_AK202 = _Group.AK_202_ControlNumber;
_EDI_AK2.D_AK203 = _Group.AK_203_VersionIdentifier;
_EDI_2000.S_AK2 = _EDI_AK2;
//Set IK3 Block
_EDI_IK3.D_IK301 = _Group.IK_301_MissingSegment;
_EDI_IK3.D_IK302 = _Group.IK_302_PositionInTransactionSet;
_EDI_IK3.D_IK304 = X12_ID_620.Item3; // _Group.IK_304_ErrorCode;
_EDI_2100.S_IK3 = _EDI_IK3;
//Set IK5 Block
_EDI_IK5.D_IK501 = X12_ID_717.R;
_EDI_IK5.D_IK502 = X12_ID_618.Item5;
_EDI_2000.S_IK5 = _EDI_IK5;
//Set Lists
_EDI_2100_List.Add(_EDI_2100);
_EDI_2000.G_TS999_2100 = _EDI_2100_List;
_EDI_2000_List.Add(_EDI_2000);
_EDI_999.G_TS999_2000 = _EDI_2000_List;
//AK9 Block
_EDI_AK9.D_AK901 = X12_ID_715.R;//_Group.AK_901_RejectIndicator;
_EDI_AK9.D_AK902 = _Group.AK_902_NumberOfTransactionSets;
_EDI_AK9.D_AK903 = _Group.AK_903_NumberOfTransactionSets;
_EDI_AK9.D_AK904 = _Group.AK_904_NumberAccepted;
_EDI_999.S_AK9 = _EDI_AK9;
//SE Block
_EDI_SE.D_SE01 = _Group.SE_01_SegmentCounter;
_EDI_SE.D_SE02 = _Group.SE_02_TransactionSetCounter;
_EDI_999.S_SE = _EDI_SE;
_EDI_Message = new Message(_EDI_999);
_EDI_Group.Messages.Add(new Message((object)_EDI_999));
_EDI_Interchange.Groups.Add(_EDI_Group);
}
public string GetEdiString()
{
var parsedXml = _EDI_Interchange.ToEdi();
return string.Concat(parsedXml);
}
}
public class DS_M_999_Interchange
{
public string ISA_01_Authorization { get; set; } //default 00
public string ISA_02_AuthInfo { get; set; } //defualt ""
public string ISA_03_SecurityQualifier { get; set; } //default 00
public string ISA_04_Password { get; set; } //default ""
//get from 270/276
public string ISA_05_SenderQualifier { get; set; }
public string ISA_06_SenderId { get; set; }
public string ISA_07_ReceiverQualifier { get; set; }
public string ISA_08_ReceiverId { get; set; }
public string ISA_09_DateReceived { get; set; } //default YYMMDD
public string ISA_10_TimeRecieved { get; set; } //default HHMM
public string ISA_11_RepetitionSeparator { get; set; } //default ^
public string ISA_12_X12Version { get; set; } //default 00501
public string ISA_13_UniqueNumberCounter { get; set; } //will be generated by app
public string ISA_14_AcknoledgementRequested { get; set; } //default 0
public string ISA_15_UsageIndicator { get; set; } //default P
public string ISA_16_CompElementSeparator { get; set; } //default :
//Interchange GS
public string GS_01 { get; set; } //default FA
//from 270/276
public string GS_02_SenderCode { get; set; }
public string GS_03_ReceiverCode { get; set; }
public string GS_04_DateReceived { get; set; } //default CCYYMMDD
public string GS_05_TimeReceived { get; set; } //default HHMM
public string GS_06_UniqueNumberCounter { get; set; } //will be generated by app
public string GS_07_AgencyCode { get; set; } //default "X"
public string GS_08_X12Version { get; set; } //default 00501X231A1
public string GE_01_TransactionSetCounter { get; set; } //number of transaction sets output typically 1
public string GE_02_UniqueNumberCounter { get; set; } //same as GS06
public string IEA_01_FunctionalGroupCounter { get; set; } //number of functional groups typically 1
public string IEA_02_UniqueNumberCounter { get; set; } //same as ISA_13
public DS_M_999_Interchange()
{
ISA_01_Authorization = "00";
ISA_02_AuthInfo = "";
ISA_03_SecurityQualifier = "00";
ISA_04_Password = "";
ISA_09_DateReceived = DateTime.Now.ToString("yyMMdd");
ISA_10_TimeRecieved = DateTime.Now.ToString("HHMM");
ISA_11_RepetitionSeparator = "^";
ISA_12_X12Version = "005010";
ISA_13_UniqueNumberCounter = "1ISA"; //Need to generate/track
ISA_14_AcknoledgementRequested = "0";
ISA_15_UsageIndicator = "P";
ISA_16_CompElementSeparator = ":";
GS_01 = "FA";
GS_04_DateReceived = (DateTime.Now.Year / 100 + 1).ToString() + DateTime.Now.ToString("yyMMdd");
GS_05_TimeReceived = DateTime.Now.ToString("HHMM");
GS_06_UniqueNumberCounter = "1GS06"; //Need to generate/track
GS_07_AgencyCode = "X";
GS_08_X12Version = "005010X231A1";
GE_01_TransactionSetCounter = "1";
GE_02_UniqueNumberCounter = GS_06_UniqueNumberCounter;
IEA_01_FunctionalGroupCounter = "1";
IEA_02_UniqueNumberCounter = ISA_13_UniqueNumberCounter;
}
}
public class DS_M_999_Group
{
public string ST_01_TransactionSetIdentifier { get; set; } //default 999
public string ST_02_TransactionSetCounter { get; set; } //will be generated by app startiing at 0001 (always 0001 in our instance)
public string ST_03_X12Version { get; set; } //default 005010x231a1
//from 270 /276
public string AK_101_FunctionalIdentifier { get; set; }
public string AK_102_GroupControlNumber { get; set; }
public string AK_103_VersionIdentifier { get; set; }
public string AK_201_TransactionSetIdentifier { get; set; }
public string AK_202_ControlNumber { get; set; }
public string AK_203_VersionIdentifier { get; set; }
public string IK_301_MissingSegment { get; set; } //set from x12ParserHelper MissingFields
public string IK_302_PositionInTransactionSet { get; set; } //need to figure this out by parsing incoming edi
public string IK_304_ErrorCode { get; set; } //default 3
public string IK_501_RejectIndicator { get; set; } //default R
public string IK_502_RejectCode { get; set; } //default 5
public string AK_901_RejectIndicator { get; set; } //default R
//from 270/276
public string AK_902_NumberOfTransactionSets { get; set; }
public string AK_903_NumberOfTransactionSets { get; set; }
public string AK_904_NumberAccepted { get; set; } //default 0
public string SE_01_SegmentCounter { get; set; } //#of segments in tx set ST to SE
public string SE_02_TransactionSetCounter { get; set; } //same as ST02
public DS_M_999_Group()
{
ST_01_TransactionSetIdentifier = "999";
ST_02_TransactionSetCounter = "0001";
ST_03_X12Version = "005010X231A1";
IK_304_ErrorCode = "3";
IK_501_RejectIndicator = "R";
IK_502_RejectCode = "5";
AK_901_RejectIndicator = "R";
AK_904_NumberAccepted = "0";
SE_01_SegmentCounter = "1";
SE_02_TransactionSetCounter = ST_02_TransactionSetCounter;
}
}
}
Test Class:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X12PayloadProcessing;
namespace X12PayloadProcessing.Tests
{
[TestClass]
public class DS_M_999_Tests
{
[TestMethod]
public void DSM999_ToEdiStringShouldBeValid()
{
DS_M_999_Interchange Interchange = new DS_M_999_Interchange();
Interchange.ISA_05_SenderQualifier = "ISA_05_SenderQualifier";
Interchange.ISA_06_SenderId = "SenderID"; //15 space padded
Interchange.ISA_07_ReceiverQualifier = "ISA_06_ReciverQualifier";
Interchange.ISA_08_ReceiverId = "ReceiverID"; //15 space padded
Interchange.GS_02_SenderCode = "GS_02_SenderCode";
Interchange.GS_03_ReceiverCode = "GS_03_ReceiverCode";
DS_M_999_Group Group = new DS_M_999_Group();
Group.AK_101_FunctionalIdentifier = "AK_101_FunctionalIdentifier";
Group.AK_102_GroupControlNumber = "AK_102_GroupControlNumber";
Group.AK_103_VersionIdentifier = "AK_103_VersionIdentifier";
Group.AK_201_TransactionSetIdentifier = "AK_201_TransactionSetIdentifier";
Group.AK_202_ControlNumber = "AK_202_ControlNumber";
Group.AK_203_VersionIdentifier = "AK_203_VersionIdentifier";
Group.IK_301_MissingSegment = "IK_301_MissingSegment";
Group.IK_302_PositionInTransactionSet = "IK_302_PositionInTransactionSet";
Group.AK_902_NumberOfTransactionSets = "AK_902_NumberOfTransactionSets";
Group.AK_903_NumberOfTransactionSets = "AK_903_NumberOfTransactionSets";
DS_M_999 DS_M_999 = new DS_M_999(Group, Interchange);
string ediString = DS_M_999.GetEdiString();
var x = DS_M_999._EDI_Interchange.ToEdi();
Assert.IsNotNull(ediString);
}
}
}
The test will pass as is, but it's not generating the expected EDI output. Obewon Kenobe Please help, your our only hope.
The problem seems to be in the creation of the GS, where in D_480_8 the full version number needs to be set, so that this:
_EDI_GS.D_480_8 = _Interchange.GS_08_X12Version.PadRight(6).Substring(0, 6);
should be changed to this:
_EDI_GS.D_480_8 = _Interchange.GS_08_X12Version;
It's the way the parser determines the correct type - it pulls out the X231A1 part (or the Origin) from the GS instead of the ST or MessageContext.
I found the issue to be lying in the SDK code that got translated into my own code base. The GS.D_480_8 SHOULD NOT be padded as in
_EDI_GS.D_480_8 = _Interchange.GS_08_X12Version.PadRight(6).Substring(0, 6);
The SDK File in question is GRP.cs code:
public void Version(string versionNo)
{
versionNo = versionNo.PadRight(6);
Group.Gs.D_480_8 = versionNo.Substring(0, 6);
}
My particular file was a GS08 version of 12 chars long which when not all present the EDIFabric framework was not handling.

protobuf-net Sub-message not read correctly

I'm currently testing protobuf-net (latest version), but intermittently I'm getting "Sub-message not read correctly" exception while deserializing. So far there's no apparent pattern to reproduce this error, and the data is always the same.
I googled this error and so far people reported this error only when dealing with big data (>20MB), which I'm not doing.
Can anyone point out whether this is a bug (and if it is, any possible solution to fix/circumvent this?), or am I missing some steps? Below is the code I'm using:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using ProtoBuf;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
const string message = "Cycle {0}: {1:N2} ms - avg: {2:N2} ms - min: {3:N2} - max: {4:N2}";
const int loop = 1000;
var counter = new Stopwatch();
var average = 0d;
var min = double.MaxValue;
var max = double.MinValue;
for (int i = 0;; i++)
{
var classThree = Create();
counter.Reset();
counter.Start();
Parallel.For(0, loop, j =>
{
using (var ms = new MemoryStream())
{
Serializer.Serialize(ms, classThree);
using (var ms2 = new MemoryStream(ms.ToArray()))
{
var des = Serializer.Deserialize<ClassThree>(ms2);
var aaa = des;
}
}
});
counter.Stop();
var elapsed = counter.Elapsed.TotalMilliseconds;
average += elapsed;
min = Math.Min(min, elapsed);
max = Math.Max(max, elapsed);
var currentAverage = average / (i + 1);
Console.Clear();
Console.WriteLine(message, i, elapsed, currentAverage, min, max);
Thread.Sleep(0);
}
}
private static ClassThree Create()
{
var classOne = new ClassSix()
{
// properties
p_i1 = -123,
p_i2 = 456,
p_l1 = -456,
p_l2 = 123,
p_s = "str",
p_f = 12.34f,
p_d = 56.78d,
p_bl = true,
p_dt = DateTime.Now.AddMonths(-1),
p_m = 90.12m,
p_b1 = 12,
p_b2 = -34,
p_c = 'c',
p_s1 = -21,
p_s2 = 43,
p_ts = new TimeSpan(12, 34, 56),
p_id = Guid.NewGuid(),
p_uri = new Uri("http://www.google.com"),
p_ba = new[] { (byte)1, (byte)3, (byte)2 },
p_t = typeof(ClassTwo),
p_sa = new[] { "aaa", "bbb", "ccc" },
p_ia = new[] { 7, 4, 9 },
p_e1 = EnumOne.Three,
p_e2 = EnumTwo.One | EnumTwo.Two,
p_list = new List<ClassFive>(new[]
{
new ClassFive()
{
i = 1,
s = "1"
},
new ClassFive()
{
i = 2,
s = "2"
}
}),
// fields
f_i1 = -123,
f_i2 = 456,
f_l1 = -456,
f_l2 = 123,
f_s = "str",
f_f = 12.34f,
f_d = 56.78d,
f_bl = true,
f_dt = DateTime.Now.AddMonths(-1),
f_m = 90.12m,
f_b1 = 12,
f_b2 = -34,
f_c = 'c',
f_s1 = -21,
f_s2 = 43,
f_ts = new TimeSpan(12, 34, 56),
f_id = Guid.NewGuid(),
f_uri = new Uri("http://www.google.com"),
f_ba = new[] { (byte)1, (byte)3, (byte)2 },
f_t = typeof(ClassTwo),
f_sa = new[] { "aaa", "bbb", "ccc" },
f_ia = new[] { 7, 4, 9 },
f_e1 = EnumOne.Three,
f_e2 = EnumTwo.One | EnumTwo.Two,
f_list = new List<ClassFive>(new[]
{
new ClassFive()
{
i = 1,
s = "1"
},
new ClassFive()
{
i = 2,
s = "2"
}
})
};
var classThree = new ClassThree()
{
ss = "333",
one = classOne,
two = classOne
};
return classThree;
}
}
public enum EnumOne
{
One = 1,
Two = 2,
Three = 3
}
[Flags]
public enum EnumTwo
{
One = 1,
Two = 2,
Three = 4
}
[ProtoContract, ProtoInclude(51, typeof(ClassSix))]
public class ClassOne
{
// properties
[ProtoMember(1)]
public int p_i1 { set; get; }
[ProtoMember(2)]
public uint p_i2 { set; get; }
[ProtoMember(3)]
public long p_l1 { set; get; }
[ProtoMember(4)]
public ulong p_l2 { set; get; }
[ProtoMember(5)]
public string p_s { set; get; }
[ProtoMember(6)]
public float p_f { set; get; }
[ProtoMember(7)]
public double p_d { set; get; }
[ProtoMember(8)]
public bool p_bl { set; get; }
[ProtoMember(9)]
public DateTime p_dt { set; get; }
[ProtoMember(10)]
public decimal p_m { set; get; }
[ProtoMember(11)]
public byte p_b1 { set; get; }
[ProtoMember(12)]
public sbyte p_b2 { set; get; }
[ProtoMember(13)]
public char p_c { set; get; }
[ProtoMember(14)]
public short p_s1 { set; get; }
[ProtoMember(15)]
public ushort p_s2 { set; get; }
[ProtoMember(16)]
public TimeSpan p_ts { set; get; }
[ProtoMember(17)]
public Guid p_id { set; get; }
[ProtoMember(18)]
public Uri p_uri { set; get; }
[ProtoMember(19)]
public byte[] p_ba { set; get; }
[ProtoMember(20)]
public Type p_t { set; get; }
[ProtoMember(21)]
public string[] p_sa { set; get; }
[ProtoMember(22)]
public int[] p_ia { set; get; }
[ProtoMember(23)]
public EnumOne p_e1 { set; get; }
[ProtoMember(24)]
public EnumTwo p_e2 { set; get; }
[ProtoMember(25)]
public List<ClassFive> p_list { set; get; }
// fields
[ProtoMember(26)]
public int f_i1 = 0;
[ProtoMember(27)]
public uint f_i2 = 0;
[ProtoMember(28)]
public long f_l1 = 0L;
[ProtoMember(29)]
public ulong f_l2 = 0UL;
[ProtoMember(30)]
public string f_s = string.Empty;
[ProtoMember(31)]
public float f_f = 0f;
[ProtoMember(32)]
public double f_d = 0d;
[ProtoMember(33)]
public bool f_bl = false;
[ProtoMember(34)]
public DateTime f_dt = DateTime.MinValue;
[ProtoMember(35)]
public decimal f_m = 0m;
[ProtoMember(36)]
public byte f_b1 = 0;
[ProtoMember(37)]
public sbyte f_b2 = 0;
[ProtoMember(38)]
public char f_c = (char)0;
[ProtoMember(39)]
public short f_s1 = 0;
[ProtoMember(40)]
public ushort f_s2 = 0;
[ProtoMember(41)]
public TimeSpan f_ts = TimeSpan.Zero;
[ProtoMember(42)]
public Guid f_id = Guid.Empty;
[ProtoMember(43)]
public Uri f_uri = null;
[ProtoMember(44)]
public byte[] f_ba = null;
[ProtoMember(45)]
public Type f_t = null;
[ProtoMember(46)]
public string[] f_sa = null;
[ProtoMember(47)]
public int[] f_ia = null;
[ProtoMember(48)]
public EnumOne f_e1 = 0;
[ProtoMember(49)]
public EnumTwo f_e2 = 0;
[ProtoMember(50)]
public List<ClassFive> f_list = null;
}
[ProtoContract]
public class ClassSix : ClassOne
{
}
[ProtoContract]
public class ClassTwo
{
}
[ProtoContract]
public interface IClass
{
[ProtoMember(1)]
string ss
{
set;
get;
}
[ProtoMember(2)]
ClassOne one
{
set;
get;
}
}
[ProtoContract]
public class ClassThree : IClass
{
[ProtoMember(1)]
public string ss { set; get; }
[ProtoMember(2)]
public ClassOne one { set; get; }
[ProtoMember(3)]
public ClassSix two { set; get; }
}
[ProtoContract]
public class ClassFour
{
[ProtoMember(1)]
public string ss { set; get; }
[ProtoMember(2)]
public ClassOne one { set; get; }
}
[ProtoContract]
public class ClassFive
{
[ProtoMember(1)]
public int i { set; get; }
[ProtoMember(2)]
public string s { set; get; }
}
}
Updated to rev. 669 and so far haven't encounter the error again. So I'm reporting this as fixed for now.

Categories

Resources