I know this has been asked a few times, but I'm need a fast way to do this in files with different size (small and large files).
I need to edit scale factor in sat(txt) file. This is a first number in third line:
700 104 1 0 16 Autodesk AutoCAD 19 ASM 221.0.0.1871 NT 24 Tue
Aug 16 09:02:14 2016
1000 9.9999999999999995e-007 1e-010
I suggest extracting a method and Linq:
private static String MyEditLine(string value) {
var items = value.Split(new char[] { ' ' }, 2);
items[0] = "2000"; // let's change 1000 into 2000
return string.Join(" ", items);
}
...
var target = File
.ReadLines(#"C:\MyFile.txt")
.Select((line, index) => index != 2
? line
: MyEditLine(line))
.ToList();
File.WriteAllLines(#"C:\MyFile.txt", target);
assume you read your file and get a String[] called file and the number, you want to modify, is represented as float.
Than you can use the following code to first extract the line, you want. After this you get the number through float.TryParse(..)
int lineWithParam = 3;
String[] splittedLine = (file[lineWithParam-1]).Split(new char[] { ' ' }, 2);
if(splittedLine.Length == 2)
{
float fact = 0.0f;
String newFact = splittedLine[0];
// or how ever you want to modify your factor
if(float.TryParse(splittedLine[0], out fact))
{
newFact = "" + (fact * 12.3f);
}
file[lineWithParam-1] = newFact + " " + splittedLine[1];
}
Here an executable example: https://dotnetfiddle.net/NVgETo
after this you can write the String[] file back to the real file.
Note: this will not modify the file, if in the given line the first parameter isn't a valid float!
Related
I am attempting to read a log file in this format:
date | cost
date | cost
..ect
Using the following code to read the file in to an array:
string[] lines = File.ReadAllLines("log.txt");
My question is how do I slice the array in to 2 parts per line so that I can add them to a list view of 2 columns? I was thinking perhaps a dictionary would be a good start..
Assuming this is C# rather than C, the following may do what you're looking for:
public class LogEntry{
public string Date;
public string Cost;
public LogEntry(string date,string cost){
Date=date;
Cost=cost;
}
}
...
// Grab the lines from the file:
string[] lines = File.ReadAllLines("log.txt");
// Create our output set:
LogEntry[] logEntries=new LogEntry[lines.Length];
// For each line in the file:
for(int i=0;i<lines.Length;i++){
// Split the line:
string[] linePieces=lines[i].Split('|');
// Safety check - make sure this is a line we want:
if(linePieces.Length!=2){
// No thanks!
continue;
}
// Create the entry:
logEntries[i]=new LogEntry( linePieces[0] , linePieces[1] );
}
// Do something with logEntries.
Note that this sort of processing should only be done with a relatively small log file. File.ReadAllLines("log.txt") becomes very inefficient with large files, at which point using a raw FileStream is more suitable.
var lines = File.ReadAllLines("log.txt").Select(l=> l.Split('|'));
var dictionary= lines.ToDictionary(x => x[0], y => y[1]);
Use a 2D array and string.Split('-')
string[] lines = File.ReadAllLines("log.txt");
//Create an array with lines.Length rows and 2 columns
string[,] table = new string[lines.Length,2];
for (int i = 0; i < lines.Length; i++)
{
//Split the line in 2 with the | character
string[] parts = lines[i].Split('|');
//Store them in the array, trimming the spaces off
table[i,0] = parts[0].Trim();
table[i,1] = parts[1].Trim();
}
Now you will have an array that looks like this:
table[date, cost]
You could use a dictionary so you only have to look up the date if you want to improve it. EDIT: As #Damith has done
Additionally, with LINQ you could simplify this into:
var table = File.ReadAllLines("log.txt").Select(s => s.Split('|')).ToDictionary(k => k[0].TrimEnd(' '), v => v[1].TrimStart(' '));
Which you can now easily get the results from the LINQ expression with:
foreach (KeyValuePair<string, string> kv in table)
{
Console.WriteLine("Key: " + kv.Key + " Value: " + kv.Value);
}
Also note if you do not need the spaces in your file you can omit the Trim()s
And just because this post was originally tagged C :)
Here is a C example:
With a data file (I called it temp.txt) that looks like this:
3/13/56 | 13.34
3/14/56 | 14.14
3/15/56 | 15.00
3/16/56 | 16.56
3/17/56 | 17.87
3/18/56 | 18.34
3/19/56 | 19.31
3/20/56 | 20.01
3/21/56 | 21.00
This code will read it, parse it into a single 2 dim string array, char col[2][80][20];
#include <ansi_c.h>
int main()
{
int i;
char *buf;
char line[260];
char col[2][80][20];
FILE *fp;
fp = fopen("c:\\dev\\play\\temp.txt", "r");
i=-1;
while(fgets(line, 260, fp))
{
i++;
buf = strtok(line, "|");
if(buf) strcpy(col[0][i], buf);
buf = strtok(NULL, "|");
if(buf) strcpy(col[1][i], buf);
}
fclose(fp);
return 0;
}
Let's say I have text file like this
<pre>----------------
hPa m C
---------------------
1004.0 28 13.6
1000.0 62 16.2
998.0 79 17.2
992.0 131 18.0
<pre>----------------
Sometext here
1000.0 10 10.6
1000.0 10 11.2
900.0 10 12.2
900.0 100 13.0
<aaa>----------------
How Can I Create Array in C# that reads text file from line number 5 (1004.0) to just before line that starts with string <pre>-
I used string[] lines = System.IO.File.ReadAllLines(Filepath);
To make each line in the array
The problem is I want only numbers of first section in the array in order to separate them later to another 3 arrays (hPa, m, C) .
Here's a possible solution. It's probably way more complicated than it should be, but that should give you an idea of possible mechanisms to further refine your data.
string[] lines = System.IO.File.ReadAllLines("test.txt");
List<double> results = new List<double>();
foreach (var line in lines.Skip(4))
{
if (line.StartsWith("<pre>"))
break;
Regex numberReg = new Regex(#"\d+(\.\d){0,1}"); //will find any number ending in ".X" - it's primitive, and won't work for something like 0.01, but no such data showed up in your example
var result = numberReg.Matches(line).Cast<Match>().FirstOrDefault(); //use only the first number from each line. You could use Cast<Match>().Skip(1).FirstOrDefault to get the second, and so on...
if (result != null)
results.Add(Convert.ToDouble(result.Value, System.Globalization.CultureInfo.InvariantCulture)); //Note the use of InvariantCulture, otherwise you may need to worry about , or . in your numbers
}
Do you mean this?
System.IO.StreamReader file = new System.IO.StreamReader(FILE_PATH);
int skipLines = 5;
for (int i = 0; i < skipLines; i++)
{
file.ReadLine();
}
// Do what you want here.
This question already has answers here:
2d Array from text file c# [closed]
(3 answers)
Closed 9 years ago.
How can I loop through a text file to create six arrays from the content of the text file.
For example, the text file will look like this but with more lines(without title) maybe 200 of them
top_speed average_speed cadence altitude heart_rate power
84 73 0 -124 0 50
86 179 84 -125 121 3893
It would be nice to have an array for each. So, for example
top_speed = 84 + 86 : average_speed = 73 + 179 ... (and so on)
What's the best way to do this?
Anyway, if that is homework, following code will not help you :) But if it is not homework, you will understand how to parse such files with LINQ
var items =
File.ReadAllLines(filename) // read lines from file
.Select(line => line.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries)
.Select(Int32.Parse)
.ToArray()) // convert each line to array of integers
.Select(values => new {
TopSpeed = values[0],
AverageSpeed = values[1],
Cadence = values[2],
Altitude = values[3],
HeartRate = values[4],
Power = values[5]
}); // create anonymous object with nice strongly-typed properties
int[] topSpeeds = items.Select(i => i.TopSpeed).ToArray();
You could create a Record class and then use a simple LINQ query:
var records = File.ReadLines("file.txt")
.Select(line =>
{
string[] parts = line.Split('\t');
return new Record
{
TopSpeed = int.Parse(parts[0]),
AverageSpeed = int.Parse(parts[1]),
Cadence = int.Parse(parts[2]),
Altitude = int.Parse(parts[3]),
HeartRate = int.Parse(parts[4]),
Power = int.Parse(parts[5])
};
}).ToArray();
This will give you a bunch of Records, one per line in the original file. If you wanted to then check all of HeartRates for building a histogram or graphing or whatever, you could grab them like this:
var allHeartRates = records.Select(rec => rec.HeartRate);
This is a similar question I asked earlier, except different in the fact that I am taking multiple files and calculating the total sums off of those files. I have it to the point where I am reading all the files from a specific directory, but for some reason its not grouping correctly.
Here is the code that I have:
public void CalculateMonthlyStatistics(string monthlyFiles)
{
string monthlyFileName = monthlyFiles + ".log";
var statistics = File.ReadLines(monthlyFileName)
.GroupBy(items => items[0])
.Select(g =>
new
{
Division = g.Key,
ZipFiles = g.Sum(i => Convert.ToInt32(i[1])),
Conversions = g.Sum(i => Convert.ToInt32(i[2])),
ReturnedFiles = g.Sum(i => Convert.ToInt32(i[3])),
TotalEmails = g.Sum(i => Convert.ToInt32(i[4]))
});
statistics
.ToList()
.ForEach(d => Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}",
d.Division,
d.ZipFiles,
d.Conversions,
d.ReturnedFiles,
d.TotalEmails));
Console.Read();
//.ForEach(d => Log.Open(tempFileName.TrimEnd(charsToTrim), d.Division, d.ZipFiles, d.Conversions, d.ReturnedFiles, d.TotalEmails));
}
}
}
The log files that I am putting into it look like the following:
Division Zip Files Conversions Returned Files Total E-Mails
Corporate 0 5 0 5
Energy 0 1 0 5
Global Operations 0 3 0 3
Oil & Gas 1 5 0 5
Capital 5 18 0 12
So what I am trying to do, is group by "Corporate", "Energy", etc. Then calculate the totals for ALL of the files being read, to create a Monthly Statistics file. I am getting totals currently, however I think its got something to do with the header that I am passing in, and I am not sure how to tell it to skip that line.
Thanks in advance
EDIT
Here is my processor, which originally reads the directory, etc.
public void ProcessMonthlyLogFiles()
{
DateTime currentTime = DateTime.Now;
int month = currentTime.Month - 1;
int year = currentTime.Year;
string path = Path.GetDirectoryName(Settings.DailyPath + year + #"\" + month + #"\");
foreach (string monthlyFileNames in Directory.GetFiles(path))
{
string monthlyFiles = path + #"\" + Path.GetFileNameWithoutExtension(monthlyFileNames);
new MonthlyReader().CalculateMonthlyStatistics(monthlyFiles);
}
}
The processor finds the proper directory to search through in order to get the files from. It uses the current date, and finds last month.
Skipping the header is straightforward:
File.ReadLines(monthlyFileName).Skip(1).<rest of your chain>
However, it seems as though you're reading one file at a time, when you want to be reading all files then calculating the statistics?
How about first:
public IEnumerable<String> ReadLinesInDirectory(string path)
{
return Directory.EnumerateFiles(path)
.SelectMany(f =>
File.ReadLines(f)
.AsEnumerable()
.Skip(1));
}
And replace ReadLines with that (ensuring you're pointing to the right path etc).
OK here's the full explanation, but I think you may need to study C# some more. First, define the ReadLinesInDirectory function I wrote above.
Then replace ProcessMonthlyLogFiles with this instead:
public void ProcessMonthlyLogFiles()
{
DateTime currentTime = DateTime.Now;
int month = currentTime.Month - 1;
int year = currentTime.Year;
string path = Path.GetDirectoryName(Settings.DailyPath + year + #"\" + month + #"\");
CalculateMonthlyStatistics(path);
}
And in CalculateMonthlyStatistics have the first three lines (before the GroupBy) as follows:
public void CalculateMonthlyStatistics(string path)
{
var statistics = ReadLinesInDirectory(path)
// .GroupBy etc...
hi i'm trying to extract values from this tagged file
here is the file
0
LINE
5
1C1CBD
330
1C1ADB
100
AcDbEntity
8
0-FD
62
9
370
-2
100
AcDbLine
10
53740.73468153231
20
-190253.3098529756
30
0.0
11
53690.49919802765
21
-190166.2994431953
31
0.0
0
you can see that there is a hexadecimal number below "LINE", is there anyway i can extract it into some list?
like
VALUE = 1C1CBD
NOTE: the file consist more than one of this kind of pattern
and then how can i get the maximum value?
EDIT 1
i see that "5" can be found by using regex "\s\s5" can i use this?
Thank you for your feedback i have been able to complete what i want
here is the code
string[] handle = originalString.Split(new string[] { "\r\n" }, StringSplitOptions.None);
List<string> hexa = new List<string>();
for (var a = 1; a <= handle.Count() - 1; a++)
{
if (Regex.IsMatch(handle[a], #"^\s\s5"))
{
hexa.Add(handle[a + 1]);
}
}
List<int> HexaToInt = new List<int>();
foreach (string valueHexa in hexa)
{
int intHexaValue = int.Parse(valueHexa, System.Globalization.NumberStyles.HexNumber);
HexaToInt.Add(intHexaValue);
}
int maximumHexa = HexaToInt.Max();
string hexValue = maximumHexa.ToString("X");
it is possible afterall to extract the hexadecimal value from the handle group codes
It is totally impossible.
No way to catch characters and extract what you need.
You have to organize the structure of this file better.