Reputation: 841
I have a collection of fixed width files with a varying number of columns and field sizes.
The top of the file starts with a line like:
AAAAABBCCCCCCCCCCDDD and so on
The change in character denotes the end of one field and the start of another. I am guessing this can someone be used to work out what the field sizes are with code and then apply the same values to the actual data lines below.
I then want to output all the read data into a XLS file or even a DataGrid, but my issue is I have no idea how to code this.
Any help would be greatly appreciated :)
/Edit:
I implemented Cuong's solution and although that worked fine for testing on my home PC, I had to compile it with c# v4 as our work PCs have Windows XP.
Anyways, when reading the input file I get the following error:
************** Exception Text **************
System.ObjectDisposedException: Cannot read from a closed TextReader.
at System.IO.__Error.ReaderClosed()
at System.IO.StreamReader.ReadLine()
at System.IO.File.<InternalReadLines>d__0.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.IO.File.InternalWriteAllLines(TextWriter writer, IEnumerable`1 contents)
at System.IO.File.WriteAllLines(String path, IEnumerable`1 contents)
at FixedWidthFiles.Main.buttonProcessFile_Click(Object sender, EventArgs e)
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
************** Loaded Assemblies **************
mscorlib
Assembly Version: 4.0.0.0
Win32 Version: 4.0.30319.1 (RTMRel.030319-0100)
CodeBase: file:///C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/mscorlib.dll
----------------------------------------
FixedWidthFiles
Assembly Version: 1.0.0.0
Win32 Version: 1.0.0.0
CodeBase: file:///C:/TEMP/FixedWidthFiles.exe
----------------------------------------
System.Windows.Forms
Assembly Version: 4.0.0.0
Win32 Version: 4.0.30319.1 built by: RTMRel
CodeBase: file:///C:/WINDOWS/Microsoft.Net/assembly/GAC_MSIL/System.Windows.Forms/v4.0_4.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
----------------------------------------
System.Drawing
Assembly Version: 4.0.0.0
Win32 Version: 4.0.30319.1 built by: RTMRel
CodeBase: file:///C:/WINDOWS/Microsoft.Net/assembly/GAC_MSIL/System.Drawing/v4.0_4.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
----------------------------------------
System
Assembly Version: 4.0.0.0
Win32 Version: 4.0.30319.1 built by: RTMRel
CodeBase: file:///C:/WINDOWS/Microsoft.Net/assembly/GAC_MSIL/System/v4.0_4.0.0.0__b77a5c561934e089/System.dll
----------------------------------------
System.Core
Assembly Version: 4.0.0.0
Win32 Version: 4.0.30319.1 built by: RTMRel
CodeBase: file:///C:/WINDOWS/Microsoft.Net/assembly/GAC_MSIL/System.Core/v4.0_4.0.0.0__b77a5c561934e089/System.Core.dll
----------------------------------------
Upvotes: 3
Views: 8977
Reputation: 137594
Use the class TextFieldParser type per this how-to for Visual Basic.
You'll need to tell it the widths of the fields. Given your first line, that's easy enough.
Upvotes: 1
Reputation: 75306
Below example how to write in csv file (excel type), the main point is you need to read the first line and calculate width:
var lines = File.ReadLines("C:\\input.txt");
var widthList = lines.First().GroupBy(c => c)
.Select(g => g.Count())
.ToList();
var list = new List<KeyValuePair<int, int>>();
int startIndex = 0;
for (int i = 0; i < widthList.Count(); i++)
{
var pair = new KeyValuePair<int, int>(startIndex, widthList[i]);
list.Add(pair);
startIndex += widthList[i];
}
var csvLines = lines.Select(line => string.Join(",",
list.Select(pair => line.Substring(pair.Key, pair.Value))));
File.WriteAllLines("C:\\test.csv", csvLines);
Upvotes: 1
Reputation: 14386
You can use TextReader.Read method. For example:
string input; // Test string
// Replace new StringReader with a StreamReader to read a file
using (TextReader textReader = new StringReader(input))
{
// Read first line to get structure
var groupings = textReader.ReadLine().GroupBy(x => x);
while (textReader.Peek() != -1)
{
// Convert to a string for easier handling than char[]
List<string> fields = new List<string>();
// Get the fields on each ling
foreach (IGrouping<char, char> grouping in groupings)
{
char[] field = new char[grouping.Count()];
textReader.Read(field, 0, field.Length);
fields.Add(new string(field));
}
// Do something with "fields". The name of each field is
// in grouping.Key at the same index.
// Move to next line
textReader.ReadLine();
}
}
Upvotes: 1