使用回车行终止符读取/写入固定长度的文本记录

Posted

技术标签:

【中文标题】使用回车行终止符读取/写入固定长度的文本记录【英文标题】:Read/Write fixed length text records with carriage return row terminators 【发布时间】:2013-09-14 19:38:21 【问题描述】:

实现此伪代码而不会变成“非托管”的 C# 示例:

dataRec = dataRec.Key [5] + dataRec.Ptr [5] + CrLf [2];
recSize = sizeof (dataRec); // recSize = 12
aCrLf = CarriageReturn (ASCII 13) + LineFeed (ASCII 10); // define CrLf constant
fs = Open (textFile);
dataRec = "A    " + "00001" + aCrLf; // initialize 1st Row
Write (fs, dataRec, recSize * (1 - 1), recsize); // write 1st row at offset 0
dataRec = "AB   " + "00002" + aCrLf; // initialize 2nd Row
Write (fs, dataRec, recSize * (2 - 1), recsize); // write 2nd row at offset 12
dataRec = "ABC  " + "00003" + aCrLf; // initialize 3rd Row
Write (fs, dataRec, recSize * (3 - 1), recsize); // write 3rd row at offset 24
//
Read (fs, dataRec, recSize * (1 - 1), recsize); // Read 1st row at offset 0
sWork = dataRec;    // convert to string.
Console.WriteLine(sWork);   // show 1st row
Read (fs, dataRec, recSize * (2 - 1), recsize); // Read 2nd row at offset 12
sWork = dataRec;    // convert to string.
Console.WriteLine(sWork);   // show 2nd row
Read (fs, dataRec, recSize * (3 - 1), recsize); // Read 3rd row at offset 24
sWork = dataRec;    // convert to string.
Console.WriteLine(sWork);   // show 3rd row
Close (fs);

使用 DBL、C 或 VBA 在偏移处读取/写入固定长度的文本行(即随机访问)非常容易。但是我看到的二进制读/写的 C# 示例使用“非托管代码”,而我查看的读/写文本/平面文件中没有一个示例在偏移处使用 CrLf 行终止符。

【问题讨论】:

【参考方案1】:

您真的从未见过使用 StreamReader 或 File.ReadAllLines() 的代码吗?

    string path = @"d:\temp\testFile.txt";

    if (File.Exists(path))
    
         string[] loadedLines = File.ReadAllLines(path);
         if(loadedLines.Length >= 5)
         
              string line5 = loadedLines[4];
              if(line5.Length >= 10)
              
                  string key = line5.Substring(0,5);
                  string value = line5.Substring(5,5);
                  .....
              
         
    

写作部分可能是这样的

     List<string> lines = loadedLines.ToList();
     lines.Add("00009VAL09");
     lines[4] = "00008XXXXX";
     File.WriteAllLines(path, lines);

当然,当您有一个非常大的文件要读取或写入时,这些方法(ReadAllLines/WriteAllLines)不是最佳选择,但在 NET 中处理文本文件确实很容易

来自 MSDNFile.IO classCommon IO tasks

对文本文件使用随机访问有点不常见,但是可以使用 BinaryReader 和 BinaryWriter 类。 在此示例中,我尝试将文件指针定位在文件的第四条记录上。

// The 5+5+2 is the assumed lenght of a line
const int recLength = 12;

string path = @"d:\temp\DATA1.txt";

if (File.Exists(path))

    int recNum = 4;

    string key;
    string value;
    using(BinaryReader br = new BinaryReader(File.Open(path, FileMode.Open)))
    
        // The key point is the Position property that should be set using
        // some kind of simple math to the exact position needed
        br.BaseStream.Position = recNum * recLength;

        // Read the 5 bytes and build the key and value string, 
        // note that reading (or writing) advances the Position 
        key = new string(br.ReadChars(5));
        value = new string(br.ReadChars(5));
    
    Console.WriteLine(key)        ;
    Console.WriteLine(value)        ;

    key = "00009";
    value = "KKKKK";

    using(BinaryWriter bw = new BinaryWriter(File.Open(path, FileMode.Open)))
    
        // Again the math required to position for the write
        bw.BaseStream.Position = recNum * recLength;
        bw.Write(key.ToCharArray());
        bw.Write(value.ToCharArray());
    


【讨论】:

应用程序使用排序索引(伪代码建议排序索引)“指向”可以相对较宽(最多 1,000 个字节,最多 50 个字段/列)的固定位置数据记录)。这两个文件(索引和数据)可能非常大。 ReadAllLines 适用于行/行没有字段/列的较小文件。虽然大小可能不是问题,但每行/行最多可以有 50 个组件/字段/列。因此,我们需要能够处理(更改、显示)每个字段:recData.Field1 = "SomeValue"; COBOL、DIBOL 和 DBL(只是我部分熟悉的几种语言)专门使用文本文件。字母数字字段左对齐,数字字段右对齐。 BinaryReader/BinaryWriter 缺少的是自动提供偏移量的记录布局或文件描述。在我们的例子中,当我们有 50 个字段时,需要一些东西来自动知道每个字段的偏移量。 这个 C 语言中的 FDS(文件描述规范)可以很容易地说: Key = "ABC ";或 Ptr = "00002";typedef struct /* expr.fds 012 bytes / BYTE key[5]; / A05 - 唯一代码 / BYTE ptr[5]; / D05 - 指向数据记录的指针/CRLF txt_cl; / #02 - ASCII 13 + ASCII 10 */ EXP_R; #define EXPRSZ (sizeof(EXP_R)) 抱歉,我无法分离代码。 :-( 据我所知,NET 框架中没有任何东西可以直接减轻您的责任。当然,库中有大量类可以为此类工作提供构建块。例如看看Composite Formatting 和string.Format

以上是关于使用回车行终止符读取/写入固定长度的文本记录的主要内容,如果未能解决你的问题,请参考以下文章

使用固定宽度行写入/解析文本文件

如何读取和写入非固定长度的结构到二进制文件c++

Netty解码器

用于固定长度文本文件的 .NET 库

自定义分隔符解码器04

怎么固定多行EditText上每行文本的长度?