Picking specific numbers out of text file and assign to variable - c#

Someone here at works needs some calculations done from some numbers within a text file. I know how to do the calculation but I haven't worked with text file before. So I spent the night reading and wrote a little something for the first number I needed but it doesn't work.
So here is an example of the file.
So that first number that comes after FSD: 0.264 I need to read that number and save to a variable. The number will always be different per file. Then I need the first 3.4572 number read to a variable. and the last number of that column as well which you don't see here but for the example it can be the last one shown in the image of 3.3852 read and saved to a variable.
Maybe I'm making this much harder than it needs to be but this is what I was playing around with
public partial class FrmTravelTime : Form
{
string file = "";
public FrmTravelTime()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK)
{
file = openFileDialog1.FileName;
}
}
private void button2_Click(object sender, EventArgs e)
{
var sLines = File.ReadAllLines(file)
.Where(s => !s.StartsWith("FSD:"))
.Where(s => !string.IsNullOrWhiteSpace(s))
.Select(s => new
{
SValue = Regex.Match(s, "(?<=S)[\\d.]*").Value,
})
.ToArray();
string Value = "";
for (int i = 0; i < sLines.Length; i++)
{
if (sLines[i].SValue == "")
{
Value = (sLines[i].SValue);
}
}
}
}
EDIT FOR #Ramankingdom
So if you see here all lines have an ending column of 0.00 until we get to
3.0164 7793 1 0 0.159 0.02
So what I'd like to do, is edit what we did to skip everything that has a column with 0.00 in that last column and make the first non 0.00 the info.firstvalue so in this case 3.0164
Now I tried this on my own and used
var data = lines.Where(line => (!line.Contains(Data_Start_Point_Identifier) && !line.Contains(FSD__Line_Identifier) && !line.EndsWith("0.00"))).ToList();
But that breaks info.startvalue and data = dataWithAvgVolts[dataWithAvgVolts.Count - 1].Split(splitter);
So I'd figured I'd check with you.
So I tried this but I keep getting invalid data error on info.startvalue
FileInfo info = new FileInfo();
var lines = File.ReadAllLines(row.Cells["colfilelocation"].Value.ToString());
var fsdLine = lines.FirstOrDefault(line =>
line.Contains(FSD__Line_Identifier));
info.FSD = fsdLine.Substring(fsdLine.IndexOf(FSD_Identifier) + FSD_Identifier.Length, 7);
var dataWithAvgVolts = lines.SkipWhile(line => !line.Contains(Data_Start_Point_Identifier)).ToList();
int index =1;
while(index < dataWithAvgVolts.Count())
{
var data = dataWithAvgVolts[index].Split(splitter);
if(data.Count() >1)
{
if(!Convert.ToDouble(data[data.Count()-1]) == 0)
{
//set start info
break;
}
}
index++;
}
the reverse loop you can run to set the end value

Here is the code
class Program
{
const string FSD_Identifier = "FSD:";
const string FSD__Line_Identifier = "Drilling Data";
const string Data_Start_Point_Identifier = "AVG_VOLTS";
static readonly char[] splitter = {' ','\t'};
static void Main(string[] args)
{
var result = GetFileInfo("c:\\sample.txt");
}
private static MyFileInfo GetFileInfo(string path)
{
MyFileInfo info = new MyFileInfo();
try
{
var lines = File.ReadAllLines(path);
var fsdLine = lines.FirstOrDefault(line => line.Contains(FSD__Line_Identifier));
info.FSD = fsdLine.Substring(fsdLine.IndexOf(FSD_Identifier) + FSD_Identifier.Length, 10); // take lenght you can specify or your own logic
var dataWithAvgVolts = lines.SkipWhile(line => !line.Contains(Data_Start_Point_Identifier)).ToList<string>();
if (dataWithAvgVolts.Count() > 1)
{
var data = dataWithAvgVolts[1].Split(splitter);
info.startvalue = Convert.ToDouble(data[0]);
data = dataWithAvgVolts[dataWithAvgVolts.Count-1].Split(splitter);
info.endvalue = Convert.ToDouble(data[0]);
}
}
catch (Exception ex)
{
//logging here
}
return info;
}
}
public class MyFileInfo
{
public string FSD;
public double startvalue;
public double endvalue;
}

Related

read multiple values from file and place in the right place

I have this code, which does this
click on label object
run the MouseTracker method to get the mouse position
another method (WriteToConfig) is runned
here I check if there is any result then do some work with regex to update or write a new line with values
public partial class Settings : Form
{
public int xTemp;
public int yTemp;
const string ConfigFile = "config.ini";
public string? ConfigRead;
public Settings()
{
InitializeComponent();
}
private void MouseTracker(string name)
{
DialogResult result = MessageBox.Show($"Move your cursor to \"{name}\" slot in your tab \n and press ENTER");
if (result == DialogResult.OK)
{
xTemp = MousePosition.X;
yTemp = MousePosition.Y;
}
}
private void WriteToConfig(string labelName, int number)
{
ConfigRead = File.ReadAllText(ConfigFile);
try
{
string PATTERN = #$"{labelName} = (?<value>[0-9]+)";
Match match = Regex.Match(ConfigRead, PATTERN, RegexOptions.IgnoreCase);
if (match.Success)
{
int index = match.Groups["value"].Index;
int length = match.Groups["value"].Length;
ConfigRead = ConfigRead.Remove(index, length);
ConfigRead = ConfigRead.Insert(index, number.ToString());
File.WriteAllText(ConfigFile, ConfigRead);
}
else
{
string result = $"{labelName} = {number} \n";
ConfigRead = ConfigRead.Insert(ConfigRead.Length, result);
File.WriteAllText(ConfigFile, ConfigRead);
}
}
catch
{
MessageBox.Show($"{labelName} error");
}
}
private void ReadFromConfig()
{
ConfigRead = File.ReadAllText(ConfigFile);
string PATTERN = #"(?<labelName>[a-zA-Z]+) = (?<value>[0-9]+)";
Match match = Regex.Match(ConfigRead, PATTERN, RegexOptions.IgnoreCase);
}
private void orbTransLabel_Click(object sender, EventArgs e)
{
MouseTracker(orbTransLabel.Text.Remove(orbTransLabel.Text.Length - 1, 1));
orbTransXPos.Text = xTemp.ToString();
orbTransYPos.Text = yTemp.ToString();
WriteToConfig("orbTransXPos", int.Parse(orbTransXPos.Text));
WriteToConfig("orbTransYPos", int.Parse(orbTransYPos.Text));
}
now after I open the form, I would like the to read the file and update all the values from form
I started a ReadFromConfig method to read all the data and I'm thinking to match those results with every label and get the value from file with regex and put in the form.
I could need some help if anyone is willing to :D
the config.ini looks like this
orbTransXPos = 717
orbTransYPos = 1225
orbAltXPos = 717
orbAltYPos = 1267
orbAugXPos = 675
orbAugYPos = 1256
orbChanceXPos = 1874
orbChanceYPos = 1620
jewellersXPos = 1363
jewellersYPos = 488
orbFusingXPos = 13
orbFusingYPos = 193
chromXPos = 364
chromYPos = 1562
orbAlchXPos = 2359
orbAlchYPos = 628
chaosOrbXPos = 1125
chaosOrbYPos = 1772
regalOrbXPos = 1292
regalOrbYPos = 367
chiselXPos = 1398
chiselYPos = 1793
scouringXPos = 1074
scouringYPos = 339
wisdomXPos = 1315
wisdomYPos = 1683

Modifying and validating fields in a DataTable c#

I have the following datatable:
the field "court_case" has a different format and is not compact, the expected format would be: XXXX/XX ("4 digits" / "2 digits" )
For example:
12/13 -> 0012/13
2/1 -> 0002/10
/18 -> 0000/18
45/ -> 0045/00
I.e. complete with leading zeros if it is the case for the first part before the "/" and with leading zeros if it is the case after the "/".
private void bt_showDataTable_Click(object sender, EventArgs e)
{
Cursor.Current = Cursors.WaitCursor;
dataGridView2.DataSource = getDataTable();
}
public DataTable getDataTable()
{
DataTable dtTabla = new DataTable();
try
{
MySqlConnection connection = new MySqlConnection();
connection.ConnectionString = configuracion.conexion;
connection.Open();
string query = "SELECT * FROM CC_T.CONSIGNATION WHERE ACCOUNT IN ('error');"; //query from the image above
MySqlCommand mycmd = new MySqlCommand(query, connection);
mycmd.Connection = connection;
MySqlDataReader reader = mycmd.ExecuteReader();
dtTabla.Load(reader);
}
catch (MySqlException ex)
{
MessageBox.Show(ex.Message);
}
return dtTabla;
}
// METHOD TO VALIDATE COURT CASE
public static bool Validar_Cc(string CourtCase)
{
int i = 0;
string part1 = "";
string part2 = "";
bool result1 = false;
bool result2 = false;
if (CourtCase.Contains("/"))
{
part1 = CourtCase.Substring(0, CourtCase.IndexOf('/'));
part2 = CourtCase.Substring(CourtCase.IndexOf('/') + 1, CourtCase.Length - CourtCase.IndexOf('/') - 1);
result1 = int.TryParse(part1, out i);
result2 = int.TryParse(part2, out i);
}
if (!result1 || !result2)
{
return false;
}
else return true;
}
with this validation I only check that what comes for court_case is of type integer. but I do not check a validation of the format like: "XXXX/XX".
here I have to pass the method to validate:
private void btnCORRECT_ERROR_COURTCASE_Click(object sender, EventArgs e)
{
string reply = "";
foreach(DataColumn column in dataGridView2.Rows)
{
//
}
}
I know this is wrong but I don't know how to continue. Any help??
Well technically you want to split the string to 2 parts, handle each separately and add it together with added zeroes. Like:
var inputArray = new string[4] { "12/13", "2/1", "/18", "45/" };
var results = new List<string>();
foreach (var str in inputArray)
{
var parts = str.Split(new string[] { "/" }, StringSplitOptions.None);
var result = parts[0].PadLeft(4, '0') + "/" + parts[1].PadLeft(2, '0');
results.Add(result);
}
You can use string.PadLeft method to append leading zeros 0 (or other char) to some string:
static string AddLeadingZeros(string s, int amount)
{
return s.PadLeft(amount, '0');
}
Usage example:
void FixCourtCases()
{
string[] courtCases = new string[]
{
"6906/2",
"9163/2",
"504/",
"3/",
"9/4",
"4311/",
"0/",
"/6",
"193/0",
"0/2",
};
for (int i = 0; i < courtCases.Length; i++)
{
// Split left and right numbers by '/'
string[] courtCase = courtCases[i].Split(new string[] { "/" }, StringSplitOptions.None);
// Add leading zeros to left and right numbers
string fixedLeftNumber = AddLeadingZeros(courtCase[0], 4);
string fixedRightNumber = AddLeadingZeros(courtCase[1], 2)
// Reassign value with fixed one
courtCases[i] = fixedLeftNumber + "/" + fixedRightNumber;
}
}
it will give you that kind of result:
If you just want to check if the input (CourtCase) has the expected format (xxxx/xx) then you could change the Validar_Cc in this way.
public static bool Validar_Cc(string CourtCase)
{
// First check, the string should be 7 character long, if not then fast exit
if (CourtCase.Length != 7)
return false;
// Second check, try to split at /, if you get back an array with more or
// less than two elements then fast exit
string[] parts = CourtCase.Split('/');
if(parts.Length != 2)
return false;
// Now check if the two elements are numbers or not.
// Again fast exit in case of error
if(!Int32.TryParse(parts[0], out int number1))
return false;
if(!Int32.TryParse(parts[1], out int number2))
return false;
// If you reach this point then the data is correct
return true;
}
This example assumes that you consider correct inputs like '0000/00' or '1234/00' or '0000/88'. If this is not the case then one more checks is needed. Just add these lines after the TryParse block
if(number1 == 0 || number2 == 0)
return false;
And you could call the Validar_CC inside the loop over the grid rows
private void btnCORRECT_ERROR_COURTCASE_Click(object sender, EventArgs e)
{
string reply = "";
foreach(DataGridRow row in dataGridView2.Rows)
{
bool result = Validar_Cc(row.Cells["COURT_CASE"].Value.ToString());
.... do whatever you need to do with false/true results
}
}

Skipping lines of text file

So I had some assistance with this yesterday but now I needed to make a change and my change doesn't seem to work. Wanted to see if someone would help me with what I'm doing wrong.
So here is an example of the file read in
Now originally this was reading the FSD number of 0.264 then reading the first number in the first column of 3.4572 and the last number of that column. This worked fine. But now I know longer need that FSD number and I no longer need the first number 3.4572. Instead I need the first number that doesn't have 0.00 in the last column, and then the last number still. So this is what I have but it isn't grabbing anything at all, if (dataWithAvgVolts.Count() > 1) is skipped.
public partial class FrmTravelTime : Form
{
const string FSD__Line_Identifier = "Drilling Data";
const string Data_Start_Point_Identifier = "AVG_VOLTS";
const string Spark_Point_Identifier = "0.00";
static readonly char[] splitter = { ' ', '\t' };
public FrmTravelTime()
{
InitializeComponent();
}
private void btnCalculate_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow row in DGV_Hidden.Rows)
{
FileInfo info = new FileInfo();
{
var lines = File.ReadAllLines(row.Cells["colfilelocation"].Value.ToString());
var fsdLine = lines.FirstOrDefault(line => line.Contains(FSD__Line_Identifier));
var dataWithAvgVolts = lines.SkipWhile(line => line.Contains(Data_Start_Point_Identifier + Spark_Point_Identifier + FSD__Line_Identifier)).ToList();
if (dataWithAvgVolts.Count() > 1)
{
var data = dataWithAvgVolts[1].Split(splitter);
info.startvalue = Convert.ToDouble(data[0]);
data = dataWithAvgVolts[dataWithAvgVolts.Count - 1].Split(splitter);
info.endvalue = Convert.ToDouble(data[0]);
}
info.finalnum = info.startvalue - info.endvalue;
}
}
}
public class FileInfo
{
public double startvalue;
public double endvalue;
public double firstnum;
public double finalnum;
}
So you see here the first line that finally does not have 0.00 is
3.0164 7793 1 0 0.159 0.02
So my info.startvalue will be 3.0164
This goes down a good 100ish lines until the last line of
2.7182 8089 0 0 0.015 22.19
So my info.endvalue should be 2.7182
#Amit
var lines = File.ReadAllLines(row.Cells["colfilelocation"].Value.ToString());
var fsdLine = lines.FirstOrDefault(line => line.Contains(FSD__Line_Identifier));
info.FSD = fsdLine.Substring(fsdLine.IndexOf(FSD_Identifier) + FSD_Identifier.Length, 7);
var dataWithAvgVolts = lines.SkipWhile(line => !line.Contains(Data_Start_Point_Identifier)).ToList();
var data = lines.Where(line => (!line.Contains(Data_Start_Point_Identifier) && !line.Contains(FSD__Line_Identifier) && !line.EndsWith("0.00"))).ToList();
if (data.Count > 1)
{
var line = data[0];
var tempdata = data[0].Split(splitter);
info.startvalue = Convert.ToDouble(tempdata[0]);
var thisdata = data[data.Count - 1].Split(splitter);
info.endvalue = Convert.ToDouble(thisdata[0]);
}
Your SkipWhile condition is incorrect.
line => !line.Contains(Data_Start_Point_Identifier + Spark_Point_Identifier + FSD__Line_Identifier)
Will mean AVG_VOLTS0.00Drilling Data . You are saying, skip the text file till the line does not contain AVG_VOLTS0.00Drilling Data. You do not have this is one line anywhere. So, basically, you seem to be skipping the entire file. Put up a else condition, that will work.
This line returns all rows which do not have "Drilling Data" word, "AVG_VOLTS" word, and do not end with "0.00".
var data = lines.Where(line=>(!line.Contains(Data_Start_Point_Identifier) && !line.Contains(FSD__Line_Identifier) && !line.EndsWith("0.00"))).ToList();
Then, take the rows, and process.
If condition can be
if (data.Count > 1)
{
var line = data[0];
var tempdata = data[0].Split(splitter);
info.startvalue = Convert.ToDouble(tempdata[0]);
var thisdata = data[data.Count - 1].Split(splitter);
info.endvalue = Convert.ToDouble(thisdata[0]);
}

Text file to two string arrays in wpf using streamreader

I'm trying to read a text file to two string arrays. Array1 is to be all the odd lines, array2 all the even lines. I then add all the items of array1 to a combobox and when that is selected, or as it gets typed, outputs array2 to a textbox.
So far, I have tried a few methods from here, but the big issue seems to be creating the arrays. I tried to get help here before, but the answers didn't actually answer my question. They must be arrays, not lists (which I tried and worked well). I am really confused by this whole thing and my attempted code is now rubbish:
private void ReadFile(string filePath, string customerPhone, string customerName)
{
string line = string.Empty;
var fileSR = new StreamReader(filePath);
bool number = true;
while((line = fileSR.ReadLine()) != null)
{
if (number)
{
customerPhone(line);
number = false;
}
else
{
customerName(line);
number = true;
}
}
fileSR.Close();
}
I'm losing confidence in this whole process, but I need to find a way to make it work, then I can learn why it does.
You are almost there, just use the List<string>.
private void ReadFile(string filePath, string customerPhone, string customerName)
{
string line = string.Empty;
using (var fileSR = new StreamReader(filePath))
{
bool number = true;
List<string> customerPhone = new List<string>();
List<string> customerName = new List<string>();
while((line = fileSR.ReadLine()) != null)
{
if (number)
{
customerPhone.Add(line);
number = false;
}
else
{
customerName.Add(line);
number = true;
}
}
fileSR.Close();
}
}
If you are interested only in Arrays, you could simply call customerName.ToArray() to convert it to an array.
Linq Solution
Alternatively you could use Linq and do this.
var bothArrays = File.ReadLines("filepath") // Read All lines
.Select((line,index) => new {line, index+1}) // index each line
.GroupBy(x=> x/2) // Convert into two groups
.SelectMany(x=> x.Select(s=>s.line).ToArray()) // Convert it to array
.ToArray();
You should use collections to return data, say IList<String>:
private static void ReadFile(String filePath,
IList<String> oddLines,
IList<String> evenLines) {
oddLines.Clear();
evenLines.Clear();
int index = 1; //TODO: start with 0 or with 1
foreach (String line in File.ReadLines(filePath)) {
if (index % 2 == 0)
evenLines.Add(line);
else
oddLines.Add(line);
index += 1;
}
}
using
List<String> names = new List<String>();
List<String> phones = new List<String>();
ReadFile(#"C:\MyDate.txt", names, phones);
// If you want array representation
String[] myNames = names.ToArray();
String[] myPhones = phones.ToArray();
// Let's print out names
Console.Write(String.Join(Envrironment.NewLine, names));
Please, notice, that using File.ReadLines usually more convenient than StreamReader which should be wrapped in using:
// foreach (String line in File.ReadLines(filePath)) equals to
using (var fileSR = new StreamReader(filePath)) {
while ((line = fileSR.ReadLine()) != null) {
...
}
}
This worked! I have these class level strings:
string cFileName = "customer.txt";
string[] cName = new string[0];
string[] cPhone = new string[0];
And then this in the Window Loaded event, but could be used in it's own method:
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
//read file on start
int counter = 0;
string line;
StreamReader custSR = new StreamReader(cFileName);
line = custSR.ReadLine();
while (custSR.Peek() != -1)
{
Array.Resize(ref cPhone, cPhone.Length + 1);
cPhone[cPhone.Length - 1] = line;
counter++;
line = custSR.ReadLine();
Array.Resize(ref cName, cName.Length + 1);
cName[cName.Length - 1] = line;
counter++;
line = custSR.ReadLine();
phoneComboBox.Items.Add(cPhone[cPhone.Length - 1]);
}
custSR.Close();
//focus when program starts
phoneComboBox.Focus();
}

Doing a search function on a txt file

I am trying to create a search function, so that when I search for White, it should return me "#FFFFFF". Also, it should be case insensitive and support partial name input. The text file that I have contains all the color coding information in the following format:
"#FFFFFF"#White: "#FF0000"#Red:
What I have managed to understand, and done so far is as below; which is basically mapping to the text file and instructing it to write to line till the end of the document. What I do not understand is how to implement the above requirements.
I know it is not a lot, but I don't understand the concept behind the search function.
protected void search_Click(object sender, EventArgs e)
{
StreamReader sr = new StreamReader("colorCode.txt");
string line = null;
while((line =sr.ReadLine()) !=null)
{
}
In this example the colorCode stores the the match for the colorToSearch
protected void search_Click(object sender, EventArgs e)
{
StreamReader sr = new StreamReader("colorCode.txt");
string line = null;
char []colorSeparator = { ':' } ;
string []colors ;
char []colorCodeSeparator = { '#' } ;
string []codeAndColor ;
bool found ;
string colorToSearch ;
string colorCode ;
colorToSearch = "White" ;
found = false ;
while(!found && (line =sr.ReadLine()) !=null)
{
//separate the content of the file "#FFFFFF"#White: "#FF0000"#Red: using ":" as separator
colors = line.Split(colorSeparator) ;
foreach(string color in colors)
{
codeAndColor = colors.Split(colorCodeSeparator) ;
//codeAndColor[0] now contains the colorCode "#FFFFFF"
//codeAndColor[1] contains the name of the color "White"
//check if the name of the color in the file contains the colorToSearch allowing for case insensitive
if(codeAndColor[1].ToUpper().Contains(colorToSearch.ToUpper()))
{
colorCode = codeAndColor[0].Substring(1,7) ; //the 1 is to skip the initial double quote, 7 is the number of caracter to take
found = true ;
//stop the foreach loop
break ;
}
}
}
}
If you are going to do more searches I suggest that you load the colors in a Dictionary<string,string> only once from the file and perform the search on the Dictionary
Instead of opening the file every time, if the file is not huge and it is not updated while your program is running, perhaps you can read it just once and create a lookup table that can be searched, like in the example below. If you need case insensitive comparisons, or a more complicated way to do partial color matching, you will need to add that.
public class ColorLookUpTable
{
private readonly IDictionary<string, string> _colorTable;
private ColorLookUpTable(IDictionary<string, string> colorTable)
{
_colorTable = colorTable;
}
public static ColorLookUpTable LoadFromFile(string fileName)
{
var colorTable = new Dictionary<string, string>();
using (var reader = File.OpenText(fileName))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var colorPairs = line
.Split(new [] { ':' }, StringSplitOptions.RemoveEmptyEntries)
.Where(f => !string.IsNullOrWhiteSpace(f))
.Select(f => f.Trim());
foreach (var colorPair in colorPairs)
{
var fields = colorPair.Split(new [] { '#' }, StringSplitOptions.RemoveEmptyEntries).ToArray();
if (fields.Length == 2)
colorTable[fields[1]] = colorTable[fields[0]];
}
}
}
return new ColorLookUpTable(colorTable);
}
public string FindColorCodeExactMatch(string colorName)
{
string colorCode = null;
if (_colorTable.TryGetValue(colorName, out colorCode))
return colorCode;
return null;
}
public string FindColorCodePartialMatch(string colorName)
{
var colorCode = FindColorCodeExactMatch(colorName);
if (colorCode == null) // No exact match. Need to do work
// very simple partial mathching.
colorCode = _colorTable.Keys.Where(k => k.Contains(colorName)).FirstOrDefault();
return colorCode;
}
}
Usage:
var myColorLookupTable = ColorLookUpTable.LoadFromFile("colorCode.txt");
var colorCode = myColorLookupTable.FindColorCodeExactMatch("White");
var another = myColorLookupTable.FindColorCodePartialMatch("ack");

Categories