如何识别正确的子串长度

时间:2013-10-04 14:52:08

标签: c# io substring

我正在尝试从箭头位置开始读取此文件中的列值:

enter image description here

以下是我的错误:

enter image description here

我猜这是因为长度值是错误的。 说我有值的列:“狗” 用狗和后面的几个空格。我是否必须将长度参数设置为3(对于狗)或者我可以将其设置为6以容纳Dog之后的空格。这是因为每列长度都是固定的。你可以看到一些单词比其他单词小,为了保持一致,我只想将长度设置为最大列长度(例如:28是我文件第3列的长度,但不是每次都占用28个点 - 例如:单词client只有6个字符

2 个答案:

答案 0 :(得分:2)

该异常抱怨第一个参数,该参数表明您的文件包含一行< 18个字符

答案 1 :(得分:2)

Robert Levy对你所看到的问题的回答是正确的 - 你试图从一个字符串中拉出一个子字符串,其起始位置大于字符串的长度。

您正在解析一个固定长度的字段文件,其中每个字段都有一定数量的字符,无论它是否使用所有字符,poslen数组都打算用于定义用于Substring的字段长度。只要你正在阅读的行匹配预期的字段开始和长度,你就可以了。一旦你到达一条不匹配的行(例如,似乎是总计行 - 0TotalRecords: 3,390,315),你一直使用的字段长度定义将不起作用,因为格式已更改(并且线长可能不相同)。

我会改变一些事情来完成这项工作。首先,我会更改您的poslen数组,以便它们占据整个字段,而不是其中的一部分。您可以使用Trim()删除任何前导或尾随空白。根据定义,你的第一个字段只取Seq#的最后一个数字(pos 4,len 1),你的第二个字段只占用字段的前5个字符,即使它看起来有〜12个字符的空间

看看这个(从图片中很难准确地工作,但为了演示它会起作用):

          1         2         3         4 
01234567890123456789012345678901234567890
 Seq# Field       Description
    3 BELNR       ACCOUNTING DOCUMENT NBR

数字是该行中每个字符的位置。我将pos数组定义为字段的开头(第一个字段为0,然后是之后每个字段的字段标题的第一个字母的位置),因此您将拥有:

Seq# = 0
Field = 6
Description = 18

len数组将保持字段的长度,我将其定义为直到下一个字段开头的字符数量,如下所示:

Seq# = 6
Field = 12
Description = 28 (using what you have as it is hard to tell 

这将使您的数组初始化如下:

int[] pos = new int[3] { 0, 6, 18 };
int[] len = new int[3] { 6, 12, 28 };

如果你想要第四个字段,它将从第36个位置开始(位置18 + len 28 = 36)。

第二件事是我会检查循环以查看总记录行是否存在,并跳过该行(很可能是最后一行):

foreach (string line in textBox1.Lines)
{
    if (!line.Contains("Total Records"))
    {
        val[j] = line.Substring(pos[j], len[j]).Trim();
    }
}

另一种方法是修改原始查询并向其添加TakeWhile子句,直到您点击总记录数:

string[] lines = File.ReadAllLines(ofd.FileName).Skip(8)
                 .TakeWhile(l => !l.Contains("Total Records")).ToArray();

以上内容将跳过前8行,并将所有剩余的行最多但不包括第一行包含字符串中的“Total Records”。

然后你可以这样做:

string[] lines = File.ReadAllLines(ofd.FileName).Skip(8)
                 .TakeWhile(l => !l.Contains("Total Records")).ToArray();
textBox1.Lines = lines;

int[] vale = new int[3];
int[] pos = new int[3] { 0, 6, 18 };
int[] len = new int[3] { 6, 12, 28 };

foreach (string line in textBox1.Lines)
{
    val[j] = line.Substring(pos[j], len[j]).Trim();
}

现在您不必检查“总记录”行。

当然,如果您的文件中还有其他行,或者在“总记录”行之后有记录(我很怀疑),您也必须处理这些情况。

简而言之,拉出子串的代码仅适用于与特定格式相匹配的行(或者更具体地说,具有与这些位置/长度匹配的字段) - 除此之外的任何内容都会给您不正确的值或抛出错误(如果开始位置大于字符串的长度)。