Reputation: 91
I have two files (fileA.txt and fileB.txt) that I need to use to create polygons on a map. FileA contains the list of reference numbers that refer to fileB. I am able to get that list from A and find the corresponding file in B using streamreader. What I can not seem to grab is the data that I need from that file.
FileA looks like:
|ADV|170613/0448|170613/0600|KRIW||0|1
WYZ023 500230 Star_Valley
WYZ013 500130 Jackson_Hole
I take the number in bold, 500230, and look for it in fileB which looks like this:
|FIPS|500230|
8 59.094 59.091 -138.413 -138.425 59.091 -138.413 59.092 -138.425 59.094 -138.415 59.091 -138.413
8 59.101 59.099 -138.397 -138.413 59.099 -138.405
59.101 -138.413 59.100 -138.397 59.099 -138.405
|FIPS|500231|
Each line that starts with 8 after the |FIPS| line is one polygon. The number 8 represents the number of lat long pairs AFTER the numbers in bold. This 8 can be anywhere from 4 to 20. I can also have anywhere from 1 to 20 of these "groups" of lat long pairs within each |FIPS|.
In the end, I'm trying to get a list of lat long pairs for each |FIPS| that equals the |FIPS| that is looked up.
or an array of arrays. Any thoughts?
UPDATE: this is what I came up with but Im getting stuck on mainListLoop. The streamReader only reads to the end of the line but I need it to read to the next FIPS. Any suggestions?
[HttpGet]
public ActionResult GetWinterData()
{
var winterFilePaths = HostingEnvironment.MapPath(ConfigurationManager.AppSettings["WatchWarnFilePath"] + "/wstm.txt");
var stringData = new List<string>();
var mainList = new List<WinterModel>();
using (var reader = new StreamReader(winterFilePaths))
{
while (!reader.EndOfStream)
{
var data = reader.ReadLine().Trim();
if (!string.IsNullOrEmpty(data))
stringData.Add(data);
}
reader.Close();
}
WinterModel temp = null;
stringData.ForEach(line =>
{
if (line.StartsWith("|"))
{
if (temp != null)
{
mainList.Add(temp);
}
string[] rawData = line.Split('|');
temp = new WinterModel
{
Type = rawData[0],
PolyBorderColor = GetBorderColor(rawData[0], types.WINTER),
PolyBorderThickness = GetPolyBorderThickness(rawData[0], types.WINTER),
StartDateTime = rawData[1],
EndDateTime = rawData[2],
innerData = new List<tempInnerWinterModel>(),
InfoboxTitle = GetInfoboxTitle(rawData[0], types.WINTER)
};
}
else
{
string[] tempLine = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
temp.innerData.Add(new tempInnerWinterModel
{
param1 = tempLine[0],
FIPS = tempLine[1],
Location = tempLine[2],
latLongs = new List<lat_longPairs>()
});
}
});
mainList.Add(temp);
getWinterLatLongPairs2(mainList);
var tempJson = (from item in stringData
select item.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
into rawData
select new WatchPolygons
{
Type = rawData[0],
PolyBorderColor = GetBorderColor(rawData[0], types.WINTER),
StartDateTime = rawData[1],
EndDateTime = rawData[2],
//Lat_Long_Pairs = getWinterLatLongPairs2(rawData[5])
//Metadata = "Watch Type: " + rawData[0] + "< /br>" + "Watch Start: " + rawData[1] + ' ' + rawData[2]
// + "< /br>" + "Watch End: " + rawData[3] + ' ' + rawData[4]
});
return Json((from item in stringData
select item.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
into rawData
select new WatchPolygons
{
Type = rawData[0],
PolyBorderColor = GetBorderColor(rawData[0], types.WINTER),
StartDateTime = rawData[1],
EndDateTime = rawData[2],
//Lat_Long_Pairs = getWinterLatLongPairs2(rawData[5])
//Metadata = "Watch Type: " + rawData[0] + "< /br>" + "Watch Start: " + rawData[1] + ' ' + rawData[2]
// + "< /br>" + "Watch End: " + rawData[3] + ' ' + rawData[4]
}).ToList(), JsonRequestBehavior.AllowGet);
}
private static void getWinterLatLongPairs2(List<WinterModel> inputFips)
{
var searchFips = inputFips;
var fipFilePath = HostingEnvironment.MapPath(ConfigurationManager.AppSettings["WatchWarnFilePath"] + "/pfzbnds.tbl");
var stringInnerData = new List<string>();
using (var reader = new StreamReader(fipFilePath))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine().Trim();
if (!string.IsNullOrEmpty(line) && line.Contains("<FIPS>"))
{
MainListLoop(inputFips, line, reader);
if (inputFips.Last().innerData.Last().latLongs.Count > 0)
{
return;
}
}
}
reader.Close();
}
return;
}
private static void MainListLoop(List<WinterModel> inputFips, string line, StreamReader reader)
{
inputFips.ForEach(main =>
{
main.innerData.ForEach(fips =>
{
if (line.Contains(fips.FIPS))
{
var line2 = reader.ReadLine().Trim();
fips.param1 = "CHANGE";
string[] tempLine = line2.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
string numLatLongPairs = tempLine[0];
var latLonPairsWint = new List<lat_longPairs>();
int endIndex = ((Int16.Parse(numLatLongPairs) * 2) + 3 - 1);
//grab each pair of lat/longs starting at the 5th and add them to the array
for (int i = 5; i < endIndex; i += 2)
{
fips.latLongs.Add(new lat_longPairs { latitude = decimal.Parse(tempLine[i]), longitude = decimal.Parse(tempLine[i + 1]) });
}
return;
}
});
});
}
Upvotes: 0
Views: 60
Reputation: 18052
Not 100% clear on the file format of A, but if fileB isn't massive, I would recommend parsing fileB first into a dictionary where the key is the fips code and the value is a array of array of lat,long pairs, or whatever coordinate object you have in your application (numbers work fine too). From there when parsing fileA, when ever you come across a fips value, check the dictionary. This would be the easiest implementation.
If however fileB is massive, then memory on your computer or server (where you are parsing this), may be an issue. Or if fileA only references a small subset of data in fileB, then parsing all the data in fileB likely isn't the greatest. In these case, parse fileA and get a list of fips code. Next, scan through fileB until you find a fips code and see if it is in your list from fileA. If it is, parse that data from fileB and remove that value from your fileA list. Continue this until all fips in the filaA list are removed or you reach the end of fileB. For scanning fileB, you can write a custom stream reader, or if the file isn't massive, read the whole thing as a string, then use the index and substring to skip through fileB looking for fips.
Upvotes: 1