Getting data from xml file and comparing it to a text file - c#

So I have two files: a mot file and an xml file. What I need to do with these files is to read data from the xml file and compare it to the mot file if it exists. That's the general idea.
Before anything else, for those who are unfamiliar with what a mot
file is (I don't also have much knowledge about it, just the basics)...
(From Wikipedia) A mot file (or a Motorola S-Record
file) is a file format that conveys binary information in ASCII Hex text form.
(from another source) An S-record file consists of a
sequence of specially formatted ASCII character strings. An S-record
will be less than or equal to 78 bytes in length.
The format of a S-Record is:
S | Type | Record Length | Address (starting address) | Data | Checksum
(e.g. S21404200047524D5354524D0000801410AA5AA555F9)
([parsed] S2 14 042000 47524D5354524D0000801410AA5AA555 F9)
The specific idea is that I have data AA BB CC DD and so on allocated in addresses 0x042000 ~ 0x04200F. What’s written in the xml would be:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<data-set xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<record>
<File name="Test.mot">
<Address id="042000">
<Data>AA</Data>
</Address>
</File>
</record>
<record>
<File name="Test.mot">
<Address id="042001">
<Data>BB CC DD</Data>
</Address>
</File>
</record>
<record>
<File name="Test.mot">
<Address id="042004">
<Data>EE FF</Data>
</Address>
</File>
</record>
Then the program would get the data and address from he XML and search the .mot file for any hits. So if a mot file has a record S214042000AABBCCDDEEFF01234567891A2B3C4D5EF9, then this is supposed to bring a match with what's in the xml. Result to true, or 1. If anything in the xml doesn't have a match, then it would return with false or 0.
The problem now would be I’m not well-versed with C# much less with XML although I did have a tiny bit of experience with both. I initially thought it would be something like this:
using (StreamReader sr = new StreamReader("Test.mot"))
{
String line =String.Empty;
while ((line = sr.ReadLine()) != null)
{
if (line.Contains("042004") & line.Contains("EE FF"))
{
Console.WriteLine("Success");
}
else
{
Console.WriteLine("Failure");
}
}
}
But obviously, it didn't result with what I expected. And Failure keeps popping up. Am I right to use StreamReader to read the .mot file? And with regards to the XML file, will XMLDocument work? How do I get data from the xml and compare it with the .mot file? Could someone walk me through how to get this done or provide guides how to properly start with this.
Let me know if I'm not clear on anything.
EDIT:
I thought of an idea. I'm not sure if it's doable, though. Let's say the program will read the mot S-Record file, and it will identify the type of the record. From there every record line listed in the file would be broken down as shown in the sample below:
sample record line: "S214042000AABBCCDDEEFF01234567891A2B3C4D5EF9"
S2 - type w/c means there would be a 3-byte address
14 - record length
F9 - checksum
042000 - AA
042001 - BB
042002 - CC
042003 - DD
...
04200F - 5E
With this new list, I think or I hope it would be easier for the program to use the data in the XML to locate it in the mot file.
Tell me if this will work, or if there are any alternatives.

Correct me when i'm wrong as it is full of assumptions:
the XML only gives the starting values of the data package under the mot file:
||||||||||||
S214042000AABBCCDDEEFF01234567891A2B3C4D5EF9
AABBCCDDEEFF
You could read out the xml and place each record in a record class
public class Record
{
string FileName{get;set;}
string Id {get;set;}
string Data {get;set;}
public Record(){} //default constructor
}
with the XmlDocument class you could read out the xml.
something like:
var document = new XmlDocument();
document.LoadXml("your.xml");
var records = document.SelectNodes("record");
var recordList = new List<Record>();
foreach(var r in records)
{
var file = r.SelectSingleNode("file");
var fileName = file.Attributes["name"].Value;
var address = file.SelectSingleNode("Address");
var id = address.Attributes["id"].Value;
var data = address.SelectSingleNode("Data").InnerText.Replace(" ", "");
recordList.Add(new Record{FileName = fileName, Id = id, Data = data});
}
Afterwards you can then readout everyline of the mot file by position:
since the location of the 042000 always be the 5 - 10 character
var fn = "Test.mot";
using (StreamReader sr = new StreamReader(fn))
{
var record = recordList.Single(r=> r.FileName);
String line =String.Empty;
while ((line = sr.ReadLine()) != null)
{
if (line.SubString(4,6) == record.Id && line.SubString(10, record.Data.Length) == record.Data)
{
Console.WriteLine("Success");
}
else
{
Console.WriteLine("Failure");
}
}
}
Let me know if it helped you out a bit

Related

How to get only xml from file in c#?

I have a problem with parsing file with XmlReader. I have a file containing info like this:
<Users>
<User>
<Email>email</Email>
<Key>23456</Key>
</User>
</Users>
asdfsof48f43uf489f3yf3y39fh3f489f3hf94[t]45.54tv,]5t
File contains xml values and then encrypted data from byte[] array.
The problem I've encountered is when i use:
using (var reader = XmlReader.Create(fileName))
{
while (reader.Read())
{
//parsing
}
}
I got 'System.Xml.XmlException' at line where encrypted bytes begin.
My question is: how to retrieve only xml part and only byte[] part?
If in case the encrypted data is always the last line you can use below snippet to read only XML part of data given that the XML data is limited in size
var fileLines = File.ReadAllLines(#"c:\temp\file.txt");
var xmlFromFile = string.Join("", fileLines, 0, fileLines.Length - 1);
using (var reader = XmlReader.Create(new StringReader(xmlFromFile)))
{
// Your logic goes here
}
you can do string parsing...
int start, end;
string myFile = File.ReadAllText("...");
start = myFile .IndexOf("<Users>");
end = myFile .IndexOf("</Users>") + 8;
myFile = myFile.Substring(start, end-start);
At that point you can load it into a xml document if you want. This all depends on you being 100% sure about the file format. This is a pretty fragile answer, so don't use it if you don't have a total trust in your input file.

How to perform text matching in text file and then move that next line after text into csv file?

I need to read the text file and then check the input text in contents in text file.
If input text exists then move nextline(after input text) into csv file.
Sample Input: input.txt
Hi
Hello
-------------------------------------------------------------------------------
Code Name ID Customers CID Time. %
==================== ========= =========== ============ ===== =================
Harish SM 1001 Tower India 44.58
Siva DM 2310 Cata China 56.78
No Name ID Customers
==================== ========= ===========
MS Norway 1001 UNIBIC
Datas are inside the csv file.
THanks
If I give input "Code Name" then those 2 rows behind the CodeName will be saved in csv file upto newline.
If give input "No Name" then one row after No Name will be stored in another csv file.
Need to write code in c# only.
I'm little bit knowledge about c# console application
How can I write code to perform text file read and content into csv?.
Since the format of the input file isn't the nicest setup, we need to do a read ahead in order to get it to work. The following procedure should work to extract the lines after the given ID code into an array of strings, the first containing the identifier line.
public string[] GetDataLinesFromFile(string filename, string searchString)
{
List<string> dataEntries = new List<string>();
using (System.IO.StreamReader stream = new System.IO.StreamReader(filename))
{
System.IO.TextReader tr = stream;
bool foundSearchString = false;
string lastLine = string.Empty;
string line = string.Empty;
while (!stream.EndOfStream)
{
lastLine = line;
line = tr.ReadLine();
if (lastLine.Trim().StartsWith(searchString) && line.Contains("===================="))
{
foundSearchString = true;
continue;
}
if (foundSearchString)
{
// Start after the divider line
if (lastLine.Contains("===================="))
continue;
// If the current line read is a marker line, then our last line is actually a new identifier line
if (line.Contains("===================="))
{
// Can be used to look for multiple listings with the same ID
foundSearchString = false;
continue;
// If you only want the first found ID, uncomment this and comment out above
// return dataEntries.ToArray();
}
// If our previously read line is not empty, add it to the list of strings
if (lastLine.Trim().Length != 0)
dataEntries.Add(lastLine);
}
}
}
return dataEntries.ToArray();
}
Then to use this function, just call it like so:
string[] entries = GetDataLinesFromFile("input.txt", "Code Name");
To save these to a .csv file, you would just iterate through each of the strings in the string array and look for the tab marker as a divider or if the colums are at a set width then you would hard code those widths in.

How to use replace with tricky characters in C#?

I am trying to replace within a string
<?xml version="1.0" encoding="UTF-8"?>
<response success="true">
<output><![CDATA[
And
]]></output>
</response>
with nothing.
The problem I am running into is the characters <> and " characters are interacting within the replace. Meaning, it's not reading those lines as a full string all together as one but breaking the string when it comes to a <> or ". Here is what I have but I know this isn't right:
String responseString = reader.ReadToEnd();
responseString.Replace(#"<<?xml version=""1.0"" encoding=""UTF-8""?><response success=""true""><output><![CDATA[[", "");
responseString.Replace(#"]]\></output\></response\>", "");
What would be the correct code to get the replace to see these lines as just a string?
A string will never change. The Replace method works as follows:
string x = "AAA";
string y = x.Replace("A", "B");
//x == "AAA", y == "BBB"
However, the real problem is how you handle the XML response data.
You should reconsider your approach of handling incoming XML by string replacement. Just get the CDATA content using the standard XML library. It's as easy as this:
using System.Xml.Linq;
...
XDocument doc = XDocument.Load(reader);
var responseString = doc.Descendants("output").First().Value;
The CDATA will already be removed. This tutorial will teach more about working with XML documents in C#.
Given your document structure, you could simply say something like this:
string response = #"<?xml version=""1.0"" encoding=""UTF-8""?>"
+ #"<response success=""true"">"
+ #" <output><![CDATA["
+ #"The output is some arbitrary text and it may be found here."
+ "]]></output>"
+ "</response>"
;
XmlDocument document = new XmlDocument() ;
document.LoadXml( response ) ;
bool success ;
bool.TryParse( document.DocumentElement.GetAttribute("success"), out success) ;
string content = document.DocumentElement.InnerText ;
Console.WriteLine( "The response indicated {0}." , success ? "success" : "failure" ) ;
Console.WriteLine( "response content: {0}" , content ) ;
And see the expected results on the console:
The response indicated success.
response content: The output is some arbitrary text and it may be found here.
If your XML document is a wee bit more complex, you can easily select the desired node(s) using an XPath query, thus:
string content = document.SelectSingleNode( #"/response/output" ).InnerText;

How to convert windows-1250 to utf-16 using c#

I am new at c#, I am having a problem with loading XML document which is encoded in windows-1250, and when I want to print the string loaded from that document I dont get chars such as Č,Ć,Š etc. I found out that, before printing, it has to be converted from string to unicode or utf to be able to print it normaly. So my main problem is how to convert a string encoding(from widnows-1250 to utf-16) to be able to print all of the missing letters.
First XML line:
<?xml version="1.0" encoding="windows-1250"?>
Code for loading xml file:
XDocument doc = XDocument.Load(path);
var items = doc.Descendants("item");
foreach (var item in items)
{
for (i = 0; i < keyWords.Count; i++ )
{
if (item.Value.Contains(keyWords[i]))
{
vestiSaPodudaranjima.Add(item.Value);
Console.WriteLine(item.Value);
break;
}
}
}

text append to existing file

<namespace>
<root>
<node1>
<element 1>
<element 1>
</node1>
<node2>
<element 1>
<element 1>
</node2>
</root>
string stringContains = string.Empty;
foreach(string line in File.ReadLines(Path))
{
if(line.Contains("<Root>"))
{
stringContains = line.Replace("<Root>", "<Root>" + newelement.OuterXml);
}
}
File.AppendAllText(Path, stringContains);
I must replace root with other nodes,
so that i am appending text. However the above code appends existing text with stringContains
Try this.
string stringContains = string.Empty;
var lines = File.ReadLines(Path);
foreach (var line in lines)
{
if(line.Contains("<Root>"))
{
stringContains = line.Replace("<Root>", "<Root>" + newelement.OuterXml);
}
}
File.WriteAllLines(Path, lines);
but if your file size is huge then this is bad practise.
Note: You cannot change just one line in a file, you need to read all content, change desired part and write all content again.
According to your info about file size (GBs long) your only way to achive desired behaviour is to create new file and write content of you initial file changing only lines you need.
Procesing should be done line-by-line (as you showed in your sample) to achive minimum use of memory
However, this approach requieres 2X space on your HDD till operation is complete (assuming you will delete initial file after all is done)
Regarding details: this question provides complete sample of how to achive described approach

Categories