•
•
•
•
What is DaniWeb IT Discussion Community?
You're currently browsing the C# section within the Software Development category of DaniWeb, a massive community of 429,790 software developers, web developers, Internet marketers, and tech gurus who are all enthusiastic about making contacts, networking, and learning from each other. In fact, there are 3,800 IT professionals currently interacting right now! Registration is free, only takes a minute and lets you enjoy all of the interactive features of the site.
Please support our C# advertiser: Programming Forums
Views: 3135 | Replies: 12
![]() |
For one of my customers, I have to develop applications that communicate with each other via fixed-width files. In other words, they have developed a file format that is "generic" to a lot of operations. If I write a new utility, it is expected that the utility will be able to read, write, and parse this generic file. The file is fixed-width, with each field taking up a "hard-coded' number of bytes.
Of course I'll write a reusable class to handle the file i/o. My question is, what is the best approach to handling fixed-width fields?
Each field will have to be a property. All data is essentially string data. I could define a string per field, but how do I force the strings to be a specific length? All strings will be right-padded with spaces...
For example, there is a 20-byte "account number" field. It starts at byte 56 in the record, and always takes up 20-bytes in the record. If I pass in a 12-byte value, the string should hold 12 bytes followed by 8 spaces.
In C#, you cannot "DIM" a string to a pre-defined length, can you?
Should I use StringBuilder to dynamically build the record, appending the fields/string, then appending spaces equal to the required length of the field minus the actual length of the string?
Is there an elegant way to store the field names/lengths?
I'm envisioning a class called "GenericIO", with the fields as properties:
GenericIO.account = "123456789ABC";
The "setter" for that property would look of the required length of "account", perhaps stored in a 2-dimensional array. It would then pad-out the string, adding the requisite number of spaces, and would return the final formatted string. If the string is too long, the class would generate an error.
Is this a good approach? Other suggestions?
Of course I'll write a reusable class to handle the file i/o. My question is, what is the best approach to handling fixed-width fields?
Each field will have to be a property. All data is essentially string data. I could define a string per field, but how do I force the strings to be a specific length? All strings will be right-padded with spaces...
For example, there is a 20-byte "account number" field. It starts at byte 56 in the record, and always takes up 20-bytes in the record. If I pass in a 12-byte value, the string should hold 12 bytes followed by 8 spaces.
In C#, you cannot "DIM" a string to a pre-defined length, can you?
Should I use StringBuilder to dynamically build the record, appending the fields/string, then appending spaces equal to the required length of the field minus the actual length of the string?
Is there an elegant way to store the field names/lengths?
I'm envisioning a class called "GenericIO", with the fields as properties:
GenericIO.account = "123456789ABC";
The "setter" for that property would look of the required length of "account", perhaps stored in a 2-dimensional array. It would then pad-out the string, adding the requisite number of spaces, and would return the final formatted string. If the string is too long, the class would generate an error.
Is this a good approach? Other suggestions?
•
•
Join Date: Jul 2005
Location: Dallas, TX
Posts: 481
Reputation:
Rep Power: 4
Solved Threads: 19
i would do this:
private string accountNumber;
private int accountNumberLength;
public string AccountNumber {
get
{
return accountNumber;
}
set
{
StringBuilder sb = new StringBuilder(value);
while(sb.Length < accountNumberLength)
sb.Add(" ");
accountNumber = sb.ToString();
}
} That's precisely what I hoped to avoid: a loop-based method of padding out strings.
I think I'll use a Dictionary (.NET Framework 2.0) to hold field names-to-lengths. I can create space-filled strings for each field/property in the constructor. Then when a value is passed into a particular field, I'll need a quick, efficient way to "insert" the value, leaving any trailing spaces. I definitely do NOT want a loop.
I think I'll use a Dictionary (.NET Framework 2.0) to hold field names-to-lengths. I can create space-filled strings for each field/property in the constructor. Then when a value is passed into a particular field, I'll need a quick, efficient way to "insert" the value, leaving any trailing spaces. I definitely do NOT want a loop.
•
•
Join Date: Jul 2005
Location: Dallas, TX
Posts: 481
Reputation:
Rep Power: 4
Solved Threads: 19
on second thought, what about
private string accountNumber, filler = " ";//make filler as long as the field is supposed to be
private int accountNumberLength;
public string AccountNumber {
get
{
return accountNumber;
}
set
{
accountNumber = ((string)(value + filler)).Substring(0,accountNumberLength);
}
} I don't like that approach because it isn't self-documenting. Hard-coding the spaces would work, but another programmer could come along, not understand the reason for the spaces, and delete them. Or even just one of the spaces, accidentally, introducing a hard to find error.
What I've done: make a private string for each field. Make a private dictionary with the fieldnames as keys, the lengths as values. The class constructor will use a foreach to get each kvp (key-value-pair), and then "fill" the string using the .PadRight method.
Next, create the public strings and code the get/set, with the "set" procedure doing error-checking and proper padding of shorter values.
What I've done: make a private string for each field. Make a private dictionary with the fieldnames as keys, the lengths as values. The class constructor will use a foreach to get each kvp (key-value-pair), and then "fill" the string using the .PadRight method.
Next, create the public strings and code the get/set, with the "set" procedure doing error-checking and proper padding of shorter values.
•
•
Join Date: Jul 2005
Location: Dallas, TX
Posts: 481
Reputation:
Rep Power: 4
Solved Threads: 19
don't have 2.0 so not familiar with Dictionary, but essentially you are doing this:
but instead of accountnumber and accountnumber length, you are using an array(Dictionary) for all the different fields. Do I have that right? Just trying to learn.
private string accountNumber;//make filler as long as the field is supposed to be
private int accountNumberLength;
public string AccountNumber {
get
{
return accountNumber;
}
set
{
accountNumber = value.PadLeft(accountNumberLength, ' ');
}
}but instead of accountnumber and accountnumber length, you are using an array(Dictionary) for all the different fields. Do I have that right? Just trying to learn.
Not quite. Something like this:
I'm not done, of course, coding the foreach loop. The constructor uses Reflection on itself, so that it can use the strings in the Dictionary (basically, an optimized 2-dimensional array), to actually get the correpsonding string and set its value.
I need a way to pass a string "field1" to get the string variable field1, and that's accomplished with reflection. Then I'll use PadRight to fill the string with the number of spaces it requires.
Yeah, I'm probably overcomplicating this... thanks for the discussion, though.
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
namespace tgreer
{
public class GenericIO
{
private string _field1; // 20 bytes
private string _field2; // 5 bytes
private string _field3; // 10 bytes
private Dictionary<string, int> _fieldLengths = new Dictionary<string, int>(3);
public GenericIO()
{
// class constructor
_fieldLengths.Add("_field1", 20);
_fieldLengths.Add("_field2", 5);
_fieldLengths.Add("_field3", 10);
Type _myTypeObject = Type.GetType("GenericIO");
MemberInfo[] _myMemberArray = _myTypeObject.GetMembers();
foreach (KeyValuePair<string, int> kvp in _fieldLengths)
{
// this loop "initializes" each field with the proper number of spaces
}
}
}
}I'm not done, of course, coding the foreach loop. The constructor uses Reflection on itself, so that it can use the strings in the Dictionary (basically, an optimized 2-dimensional array), to actually get the correpsonding string and set its value.
I need a way to pass a string "field1" to get the string variable field1, and that's accomplished with reflection. Then I'll use PadRight to fill the string with the number of spaces it requires.
Yeah, I'm probably overcomplicating this... thanks for the discussion, though.
Hi, for padding you can use this:
b is of length 20, containing "123" (padded to the left) and the rest is filled with spaces
Hope, this helped.
string a = "123";
string b = String.Format("{0,-20}", a);Hope, this helped.
Yes, it did. I can use that as I code the "get" procedures for each of the public properties, thanks.
Here's my solution so far. I'd like commments on this approach. Am I dramatically overcomplicating the issue? The goal again is for the class constructor to initiliaze certain public properties, filling them a certain amount of spaces.
The names of the properties, as well as the required "size" and/or length, are contained in a Dictionary.
If there is a more efficient and clear (self-documenting) way of doing this, I'd like to hear about it.
I know it would be more efficient simply to define the private variables as space-filled strings:
The problem is maintainability. What if a slip of the fingers causes one of those spaces to be deleted?
Next step is to rewrite the Public "getter" procedures to maintain the trailing spaces and to generate an error if the value is too long.
Here's my solution so far. I'd like commments on this approach. Am I dramatically overcomplicating the issue? The goal again is for the class constructor to initiliaze certain public properties, filling them a certain amount of spaces.
The names of the properties, as well as the required "size" and/or length, are contained in a Dictionary.
If there is a more efficient and clear (self-documenting) way of doing this, I'd like to hear about it.
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
namespace TGREER
{
public class GenericIO
{
// first all private/public fields
private string _field1 = "";
public string Field1
{
get { return _field1; }
set { _field1 = value; }
}
private string _field2 = "";
public string Field2
{
get { return _field2; }
set { _field2 = value; }
}
private string _field3 = "";
public string Field3
{
get { return _field3; }
set { _field3 = value; }
}
StringBuilder workString = new StringBuilder();
private Dictionary<string, int> _fieldLengths = new Dictionary<string, int>(3);
public GenericIO()
{
// class constructor
_fieldLengths.Add("Field1", 20);
_fieldLengths.Add("Field2", 5);
_fieldLengths.Add("Field3", 10);
// use Reflection to use the strings in the Dictionary to retrieve the actual string object
Type MyType = this.GetType();
workString.Append(" ");
foreach (KeyValuePair<string, int> kvp in _fieldLengths)
{
workString.Remove(0, workString.Length);
workString.Insert(0, " ", kvp.Value);
PropertyInfo Mypropertyinfo = MyType.GetProperty(kvp.Key.ToString());
Mypropertyinfo.SetValue(this, workString.ToString(), null);
}
}
}
}I know it would be more efficient simply to define the private variables as space-filled strings:
private _field1 = " ";
The problem is maintainability. What if a slip of the fingers causes one of those spaces to be deleted?
Next step is to rewrite the Public "getter" procedures to maintain the trailing spaces and to generate an error if the value is too long.
![]() |
•
•
•
•
•
•
•
•
DaniWeb C# Marketplace
•
•
•
•
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
Other Threads in the C# Forum
- Previous Thread: delegates
- Next Thread: Looking for Good C# book.



Linear Mode