Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have txt file which contains number that I want to grab. This number has prefix which can be used to identify location inside file.
GeneratedNumber="120"
Number can be of any Int32 length value.
p.s. format of the file is .txt, one line contains more this key value pairs for example:
<Output Change="12.13" GeneratedNumber="120" Total="99.21" />
You can use the following code. Not very elegant or the best but tested and works fine.
string[] lines = File.ReadAllLines(Path.Combine(Application.StartupPath, "test.txt"));
foreach (string s in lines)
{
if (s.ToLowerInvariant().Contains("generatednumber"))
{
string temp = s.Substring(s.ToLowerInvariant().IndexOf("generatednumber"));
temp = temp.Substring(temp.IndexOf("\"") + 1);
temp = temp.Substring(0,temp.IndexOf("\""));
int yournumber;
if (int.TryParse(temp, out yournumber))
{
Console.WriteLine("Generated Number = ", yournumber);
}
}
}
I've only tested this as far as the xml side but this should work (You may wish to add error handling and the conversion to integers)
var values = new List<string>();
using(var sr = new StreamReader(fileName))
{
string line;
XmlDocument x = new XmlDocument();
while((line = sr.ReadLine()) != null)
{
x.LoadXml(line);
foreach(var node in x.GetElementsByTagName("Output"))
values.Add(node.Attributes["GeneratedNumber"].Value);
}
}
Tested using:
XmlDocument x = new XmlDocument();
x.LoadXml("<Output Change=\"12.13\" GeneratedNumber=\"120\" Total=\"99.21\" />");
Console.WriteLine(x.GetElementsByTagName("Output")[0]
.Attributes["GeneratedNumber"].Value);
Console.ReadLine();
you can use this code
// Read each line of the file into a string array. Each element
// of the array is one line of the file.
string[] lines = System.IO.File.ReadAllLines(#"C:\yourFile.txt");
foreach (string line in lines)
{
string sub = line.Substring(line.IndexOf("GeneratedNumber=") + 1);
int num = int.Parse(sub.IndexOf("\""));
// whatever you want to do with the integer
}
to read the text file lines and parse the lines after the "=" sign to integers.
depend on the look of the file you might use XmlDocument. please read about Xml here
string filePath = "your_file_path";
var match = System.Text.RegularExpressions.Regex.Match(
System.IO.File.ReadAllText(filePath),
#"GeneratedNumber=""(\d+)""",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
int num = match.Success ? int.Parse(match.Groups[1].Value) : 0;
Assuming there's only one instance of that number in the file or you want to grab only the first one even if there are multiple.
string[] lines = File.ReadAllLines("path to file");
Hashtable values = new Hashtable();
foreach (string line in lines)
{
if (line.Contains("=\""))
{
string[] split = line.Split('=');
values.Add(split[0], split[1].Replace("\"",""));
}
}
// GeneratedNumber is the value of GeneratedNumber in the file.
int GeneratedNumber = Int32.Parse(values["GeneratedNumber"].ToString());
This code should match your needs:
private static int GetNumber(string fileName)
{
string line;
string key = "GeneratedNumber=\"";
using (StreamReader file = new StreamReader(fileName))
{
while ((line = file.ReadLine()) != null)
{
if (line.Contains(key))
{
int startIndex = line.IndexOf(key) + key.Length;
int endIndex = line.IndexOf("\"", startIndex);
return int.Parse(line.Substring(startIndex, endIndex - startIndex));
}
}
}
return 0;
}
Also you may be interested in these articles:
Using of StreamReader
String methods
Int32.Parse method
Related
This question already has answers here:
Reading CSV files using C#
(12 answers)
Closed 3 years ago.
The code below reads a CSV file and looks for a line containing the serial number which is the first column of the file. Then copies that line to another file. The code works fine.
I need to read the text in the second and third fields of the row (there are 12 fields) and assign them to string variables (for other uses).
Can you help me, Please.
I am a novice.
List<string> found = new List<string>();
string line;
using(StreamReader file = new StreamReader(input_filename))
{
while((line=file.ReadLine())!=null)
{
if(line.Contains("XA2345")) // Serial Number
{
found.Add(line);
using(StreamWriter w = File.AppendText(output_filename))
{
// Console.WriteLine(line);
w.WriteLine(line);
w.Flush();
}
}
}
}
I'd start with some best practices for parsing CSV files with the post Parsing CSV files in C#, with header.
I've also noticed you've got that "found" variable. Are you trying to avoid duplicate lines in your output file but the code is incomplete? I've written the following code under that assumption.
Here are the using statements:
using Microsoft.VisualBasic.FileIO;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Here's the main code:
List<string> foundLines = new List<string>();
using (TextFieldParser parser = new TextFieldParser(inputFilename))
{
// Set up the parser for CSV files
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
using (StreamWriter writer = new StreamWriter(outputFilename, false))
{
while (!parser.EndOfData)
{
string[] values = parser.ReadFields();
string serialNumber = values[0];
if (string.Equals(serialNumber, "XA2345"))
{
string line = string.Join(",", values.Select(Escape));
if (foundLines.Contains(line))
continue; // Skip writing this line more than once
else
foundLines.Add(line); // Remember this line for later
writer.WriteLine(line);
// Do what you need to with the individual column values
string secondValue = values[1];
string thirdValue = values[2];
// ... Etc. ...
}
}
}
}
And here's a CSV helping method for escaping values as needed at Good CSV writer for C#:
static private string Escape(string s)
{
const string QUOTE = "\"";
const string ESCAPED_QUOTE = "\"\"";
char[] CHARACTERS_THAT_MUST_BE_QUOTED = { ',', '"', '\n' };
if (s.Contains(QUOTE))
s = s.Replace(QUOTE, ESCAPED_QUOTE);
if (s.IndexOfAny(CHARACTERS_THAT_MUST_BE_QUOTED) > -1)
s = QUOTE + s + QUOTE;
return s;
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Hi I have a report file that has a lot of data and I need to split it up but report name.
So each report is labeled “Report1” then there is some data and then “Report1End” then the next report label “Report2” for example starts this repeats till the end of the file.
I would like to be able to have method that I could pass the file location, Report1, and Report1End to and then have it create a new file with Report1’s data.
Example of the file now
random junk
Report1
some stuff
some stuff
some stuff
some stuff
Report1End
random junk
Report2
some stuff
some stuff
some stuff
some stuff
Report2End
random junk random junk
Example of what I would like the output file to be
Report2
some stuff
some stuff
some stuff
some stuff
Report2End
Thanks for the help I used the example below and changed it a bit seems to work 100% for what I needed.
static IList<string> LinesBetween(string path, string start, string end)
{
var lines = new List<string>();
var foundStart = false;
foreach (var line in File.ReadLines(path))
{
Match SMatch = Regex.Match(line, start, RegexOptions.IgnoreCase);
if (!foundStart && SMatch.Success)
{ foundStart = true; }
if (foundStart)
{
Match EMatch = Regex.Match(line, end, RegexOptions.IgnoreCase);
if (EMatch.Success)
{ lines.Add(line); break; }
else { lines.Add(line); }
}
}
return lines;
}
static List<string> LinesBetween(string path, string start, string end)
{
var lines = new List<string>();
var foundStart = false;
foreach (var line in File.ReadLines(path))
{
if (!foundStart && line == start)
foundStart = true;
if(foundStart)
if (line == end) break;
else lines.Add(line);
}
return lines;
}
Sounds like a simple StreamReader/StreamWriter combination:
using (var reader = new StreamReader(inputFile))
{
using (var writer = new StreamWriter(outputFile))
{
string textLine;
while ((textline = reader.ReadLine()) != null)
{
// Check for your particular needs, and write
// to the output file if applicable
}
}
}
Invoke function like--> Fn("abc.txt", "Report2", "Report2End");
static string[] Fn(string path, string Start, string End) {
string[] vc = File.ReadAllLines(path);
int nStart= Array.IndexOf(vc,Start);
int nEnd =Array.IndexOf(vc,End);
return vc.Skip(nStart).Take((nEnd+1) - nStart).ToArray<string>();
}
I'm working on a small app which should read a file (ANSI 835) and replace data at certain positions with generic data. Basically I'm trying to scrub a person's first and last name from the file.
The line I'm searching for that contains the name looks like this:
NM1*QC*1*Doe*John*R***MI*010088307 01~
My code looks like this:
string[] input_file = (string[])(e.Data.GetData(DataFormats.FileDrop));
string output_file = #"c:\scrubbed.txt";
foreach (string file in input_file)
{
string[] lines = File.ReadAllLines(file);
foreach (string line in lines)
{
if (line.StartsWith("NM1*QC"))
{
line.Split('*')[1] = "Lastname";
line.Split('*')[2] = "Firstname";
}
}
File.WriteAllLines(output_file, lines);
}
The File.WriteAllLines works, but the data isn't being changed. I'm trying to get any line that starts with NM1*QC to look like this:
NM1*QC*1*Lastname*Firstname*R***MI*010088307 01~
There are many lines in the file that start with NM1*QC. What's the proper way to 'find and replace' and then create a new file in this situation?
As always, thanks for your time!
The calls to String.Split return variables that you neither capture, nor use, they do not change the underlying string. So your code equates to this:
if (line.StartsWith("NM1*QC"))
{
string[] split1 = line.Split('*')[1] = "Lastname";
string[] split2 = line.Split('*')[2] = "Firstname";
}
You would need to take the results of split1 and split2 and use those to recreate your string. Here is how I would re-write your code:
string[] input_file = (string[])(e.Data.GetData(DataFormats.FileDrop));
string output_file = #"c:\scrubbed.txt";
foreach (string file in input_file)
{
string[] lines = File.ReadAllLines(file);
for (int i=0; i < lines.length; i++)
{
string line = lines[i];
if (line.StartsWith("NM1*QC"))
{
string[] values = line.Split('*');
values[1] = "Lastname";
values[2] = "Firstname";
lines[i] = String.Join("*", values);
}
}
File.WriteAllLines(output_file, lines);
}
Notice I am recombining the individual values using the String.Join method, and inserting the new string back into the array of lines. That will then get written out as you expect.
Here you are creating a temporary array:
line.Split('*')
And you are changing its contents:
line.Split('*')[1] = "Lastname";
After the line has been executed the reference to this temporary array is lost and along with it go your changes.
In order to persist the changes you need to write directly to lines:
for (var i = 0; i < lines.Length; ++i)
{
var line = lines[i];
if (!line.StartsWith("NM1*QC"))
{
continue;
}
var parts = line.Split('*');
parts[3] = "Lastname";
parts[4] = "Firstname";
lines[i] = string.Join("*", parts);
}
I have a log file that is not more than 10KB (File size can go up to 2 MB max) and I want to find if atleast one group of these strings occurs in the files. These strings will be on different lines like,
ACTION:.......
INPUT:...........
RESULT:..........
I need to know atleast if one group of above exists in the file. And I have do this about 100 times for a test (each time log is different, so I have reload and read the log), so I am looking for fastest and bets way to do this.
I looked up in the forums for finding the fastest way, but I dont think my file is too big for those silutions.
Thansk for looking.
I would read it line by line and check the conditions. Once you have seen a group you can quit. This way you don't need to read the whole file into memory. Like this:
public bool ContainsGroup(string file)
{
using (var reader = new StreamReader(file))
{
var hasAction = false;
var hasInput = false;
var hasResult = false;
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if (!hasAction)
{
if (line.StartsWith("ACTION:"))
hasAction = true;
}
else if (!hasInput)
{
if (line.StartsWith("INPUT:"))
hasInput = true;
}
else if (!hasResult)
{
if (line.StartsWith("RESULT:"))
hasResult = true;
}
if (hasAction && hasInput && hasResult)
return true;
}
return false;
}
}
This code checks if there is a line starting with ACTION then one with INPUT and then one with RESULT. If the order of those is not important then you can omit the if () else if () checks. In case the line does not start with the strings replace StartsWith with Contains.
Here's one possible way to do it:
StreamReader sr;
string fileContents;
string[] logFiles = Directory.GetFiles(#"C:\Logs");
foreach (string file in logFiles)
{
using (StreamReader sr = new StreamReader(file))
{
fileContents = sr.ReadAllText();
if (fileContents.Contains("ACTION:") || fileContents.Contains("INPUT:") || fileContents.Contains("RESULT:"))
{
// Do what you need to here
}
}
}
You may need to do some variation based on your exact implementation needs - for example, what if the word spans two lines, does the line need to start with the word, etc.
Added
Alternate line-by-line check:
StreamReader sr;
string[] lines;
string[] logFiles = Directory.GetFiles(#"C:\Logs");
foreach (string file in logFiles)
{
using (StreamReader sr = new StreamReader(file)
{
lines = sr.ReadAllLines();
foreach (string line in lines)
{
if (line.Contains("ACTION:") || line.Contains("INPUT:") || line.Contains("RESULT:"))
{
// Do what you need to here
}
}
}
}
Take a look at How to Read Text From a File. You might also want to take a look at the String.Contains() method.
Basically you will loop through all the files. For each file read line-by-line and see if any of the lines contains 1 of your special "Sections".
You don't have much of a choice with text files when it comes to efficiency. The easiest way would definitely be to loop through each line of data. When you grab a line in a string, split it on the spaces. Then match those words to your words until you find a match. Then do whatever you need.
I don't know how to do it in c# but in vb it would be something like...
Dim yourString as string
Dim words as string()
Do While objReader.Peek() <> -1
yourString = objReader.ReadLine()
words = yourString.split(" ")
For Each word in words()
If Myword = word Then
do stuff
End If
Next
Loop
Hope that helps
This code sample searches for strings in a large text file. The words are contained in a HashSet. It writes the found lines in a temp file.
if (File.Exists(#"temp.txt")) File.Delete(#"temp.txt");
String line;
String oldLine = "";
using (var fs = File.OpenRead(largeFileName))
using (var sr = new StreamReader(fs, Encoding.UTF8, true))
{
HashSet<String> hash = new HashSet<String>();
hash.Add("house");
using (var sw = new StreamWriter(#"temp.txt"))
{
while ((line = sr.ReadLine()) != null)
{
foreach (String str in hash)
{
if (oldLine.Contains(str))
{
sw.WriteLine(oldLine);
// write the next line as well (optional)
sw.WriteLine(line + "\r\n");
}
}
oldLine = line;
}
}
}
I need to delete an exact line from a text file but I cannot for the life of me workout how to go about doing this.
Any suggestions or examples would be greatly appreciated?
Related Questions
Efficient way to delete a line from a text file (C#)
If the line you want to delete is based on the content of the line:
string line = null;
string line_to_delete = "the line i want to delete";
using (StreamReader reader = new StreamReader("C:\\input")) {
using (StreamWriter writer = new StreamWriter("C:\\output")) {
while ((line = reader.ReadLine()) != null) {
if (String.Compare(line, line_to_delete) == 0)
continue;
writer.WriteLine(line);
}
}
}
Or if it is based on line number:
string line = null;
int line_number = 0;
int line_to_delete = 12;
using (StreamReader reader = new StreamReader("C:\\input")) {
using (StreamWriter writer = new StreamWriter("C:\\output")) {
while ((line = reader.ReadLine()) != null) {
line_number++;
if (line_number == line_to_delete)
continue;
writer.WriteLine(line);
}
}
}
The best way to do this is to open the file in text mode, read each line with ReadLine(), and then write it to a new file with WriteLine(), skipping the one line you want to delete.
There is no generic delete-a-line-from-file function, as far as I know.
One way to do it if the file is not very big is to load all the lines into an array:
string[] lines = File.ReadAllLines("filename.txt");
string[] newLines = RemoveUnnecessaryLine(lines);
File.WriteAllLines("filename.txt", newLines);
Hope this simple and short code will help.
List linesList = File.ReadAllLines("myFile.txt").ToList();
linesList.RemoveAt(0);
File.WriteAllLines("myFile.txt"), linesList.ToArray());
OR use this
public void DeleteLinesFromFile(string strLineToDelete)
{
string strFilePath = "Provide the path of the text file";
string strSearchText = strLineToDelete;
string strOldText;
string n = "";
StreamReader sr = File.OpenText(strFilePath);
while ((strOldText = sr.ReadLine()) != null)
{
if (!strOldText.Contains(strSearchText))
{
n += strOldText + Environment.NewLine;
}
}
sr.Close();
File.WriteAllText(strFilePath, n);
}
You can actually use C# generics for this to make it real easy:
var file = new List<string>(System.IO.File.ReadAllLines("C:\\path"));
file.RemoveAt(12);
File.WriteAllLines("C:\\path", file.ToArray());
This can be done in three steps:
// 1. Read the content of the file
string[] readText = File.ReadAllLines(path);
// 2. Empty the file
File.WriteAllText(path, String.Empty);
// 3. Fill up again, but without the deleted line
using (StreamWriter writer = new StreamWriter(path))
{
foreach (string s in readText)
{
if (!s.Equals(lineToBeRemoved))
{
writer.WriteLine(s);
}
}
}
Read and remember each line
Identify the one you want to get rid
of
Forget that one
Write the rest back over the top of
the file
I cared about the file's original end line characters ("\n" or "\r\n") and wanted to maintain them in the output file (not overwrite them with what ever the current environment's char(s) are like the other answers appear to do). So I wrote my own method to read a line without removing the end line chars then used it in my DeleteLines method (I wanted the option to delete multiple lines, hence the use of a collection of line numbers to delete).
DeleteLines was implemented as a FileInfo extension and ReadLineKeepNewLineChars a StreamReader extension (but obviously you don't have to keep it that way).
public static class FileInfoExtensions
{
public static FileInfo DeleteLines(this FileInfo source, ICollection<int> lineNumbers, string targetFilePath)
{
var lineCount = 1;
using (var streamReader = new StreamReader(source.FullName))
{
using (var streamWriter = new StreamWriter(targetFilePath))
{
string line;
while ((line = streamReader.ReadLineKeepNewLineChars()) != null)
{
if (!lineNumbers.Contains(lineCount))
{
streamWriter.Write(line);
}
lineCount++;
}
}
}
return new FileInfo(targetFilePath);
}
}
public static class StreamReaderExtensions
{
private const char EndOfFile = '\uffff';
/// <summary>
/// Reads a line, similar to ReadLine method, but keeps any
/// new line characters (e.g. "\r\n" or "\n").
/// </summary>
public static string ReadLineKeepNewLineChars(this StreamReader source)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
char ch = (char)source.Read();
if (ch == EndOfFile)
return null;
var sb = new StringBuilder();
while (ch != EndOfFile)
{
sb.Append(ch);
if (ch == '\n')
break;
ch = (char)source.Read();
}
return sb.ToString();
}
}
Are you on a Unix operating system?
You can do this with the "sed" stream editor. Read the man page for "sed"
What?
Use file open, seek position then stream erase line using null.
Gotch it? Simple,stream,no array that eat memory,fast.
This work on vb.. Example search line culture=id where culture are namevalue and id are value and we want to change it to culture=en
Fileopen(1, "text.ini")
dim line as string
dim currentpos as long
while true
line = lineinput(1)
dim namevalue() as string = split(line, "=")
if namevalue(0) = "line name value that i want to edit" then
currentpos = seek(1)
fileclose()
dim fs as filestream("test.ini", filemode.open)
dim sw as streamwriter(fs)
fs.seek(currentpos, seekorigin.begin)
sw.write(null)
sw.write(namevalue + "=" + newvalue)
sw.close()
fs.close()
exit while
end if
msgbox("org ternate jua bisa, no line found")
end while
that's all..use #d