如何解析一个随机空格分隔的文本文件并转换为制表符分隔的文件

本文关键字:分隔 文件 文本 转换 制表符 空格 何解析 随机 一个 | 更新日期: 2023-09-27 17:59:44

我正在读取一个巨大的、机器生成的、以制表符分隔的文本文件。我在下面编写了以下代码来获取值,但只有当文本文件以制表符分隔的方式时,这才有效,而且外部软件在每个字段之间使用了随机的空格。

如何生成将随机空格分隔的文本文件读取为制表符分隔的文件的代码。我目前的工作是在Microsoft Excel中打开文件,然后重新保存为制表符分隔的文件。但这将无法正常工作,因为Excel无法正确识别随机数量的空格分隔符。以下是我为读取行-列格式的制表符分隔的文本文件所做的代码,但我需要帮助来获得机器生成文件的解决方案。

string filename = @"D:'EMS_DATA'firstfile.txt";
string[] lines = File.ReadAllLines(filename)
    .Where(arg => !string.IsNullOrWhiteSpace(arg)).ToArray();
string[] cols = lines[0].Trim()
    .Split(new[] {''t'}, StringSplitOptions.RemoveEmptyEntries);
int linesss = 1;
foreach (string line in lines.Skip(1))
{
    string[] cells = line.Trim()
        .Split(new[] {''t'}, StringSplitOptions.RemoveEmptyEntries);
    for (int counter = 0; counter < cols.Length; counter++)
    {
        string cellValue = "N/A";
        if(counter < cells.Length)
            cellValue = cells[counter];
        Console.WriteLine(
            "values at row {0} column {1} are {2} : {3}", 
            line, 
            counter, 
            cols[counter], 
            cellValue);
    }
    linesss++;
}

文本文件的格式为

firstname  lastname  salary  age
sasi   kiran    88000   32
ravi   kiran    92000   23
jafer  sharif   34000   45
kiran  bedi     45000   34

更新:生成的文本文件格式不正确。我目前的工作是在Microsoft Excel中打开该文件,然后将其重新保存为制表符分隔的文件。我需要代码方面的帮助,这些代码可以自动为我做到这一点。

如何解析一个随机空格分隔的文本文件并转换为制表符分隔的文件

更新的答案:

这里有一个潜在的问题。如果将制表符分隔的文件与使用空格的文件进行比较(使用您的示例,我认为与机器生成的文件完全相同),则没有明显的空格模式。见下文:

//These have spaces
firstname  lastname  salary  age
sasi   kiran    88000   32
ravi   kiran    92000   23
jafer  sharif   34000   45
kiran  bedi     45000   34
//These have tabs
firstname   lastname    salary  age
sasi    kiran   88000   32
ravi    kiran   92000   23
jafer   sharif  34000   45
kiran   bedi    45000   34

除非你能找到一个模式,否则这基本上意味着任何单元格都不能包含空格,否则你将无法拆分。我建议你试着在那里找到一个模式。

对于代码本身,我利用这个机会对您的代码进行了一些修改,并加入了Regex。在这种情况下使用regex更有意义。

代码:

        string filename = @"C:'firstfile.txt";
        //Regex objects to detect every range of spaces between 1-infinite, OR one tab.
        Regex regx = new Regex(@"['s]+|['t]", RegexOptions.Compiled);
        //Read all lines of a file, one line per index
        string[] lines = File.ReadAllLines(filename);
        //Create multi-dimensional List array
        List<List<string>> sheet = new List<List<string>>();
        //Split each line in lines by column, and you end up with a multi-dimensional array.
        //Makes it look like an excel sheet. [Row][Column]
        sheet.AddRange(lines.Select(x => new List<string>(regx.Split(x).ToList())));
        //Start from rowIndex = 1, as 0 contains the headers
        for (int rowIndex = 1; rowIndex < sheet.Count; rowIndex++)
        {
            for (int colIndex = 0; colIndex < sheet[rowIndex].Count; colIndex++)
            {
                Console.WriteLine("values at row {0} column {1} are {2} : {3}",
                    rowIndex,
                    colIndex,
                    sheet[0][colIndex],
                    sheet[rowIndex][colIndex]
                    );
            }
        }

输出

values at row 1 column 0 are firstname : sasi
values at row 1 column 1 are lastname : kiran
values at row 1 column 2 are salary : 88000
values at row 1 column 3 are age : 32
values at row 2 ...

如果您的机器生成的代码总是在每个字段之间放置最小的空格,并且大于1个空格,那么在实际的"单元格"中可以有任何小于该空格的空格。如果事实证明是这样的话,请修改regex模式,如下所示:

替换此:

Regex regx = new Regex(@"['s]+|['t]", RegexOptions.Compiled);

使用:

Regex regx = new Regex(@"['s]{2,}|['t]", RegexOptions.Compiled);

我还想提一下,这就是为什么CSV更受欢迎的原因,因为这些文件使用";"而不是空白。

要将这些内容写回一个适当的选项卡分隔文件,请使用以下命令:

    string filename_modified = @"C:'modifiedfile.txt";
    File.WriteAllText(filename_modified, String.Join(Environment.NewLine, sheet.Select(x => String.Join("'t", x))));