【问题标题】:C# Determine EOL Character in flat filesC# 确定平面文件中的 EOL 字符
【发布时间】:2014-09-15 17:25:27
【问题描述】:

我正在尝试从给定的 .txt 或 .csv 平面文件中识别 EOL 字符是什么。根据平面文件中第一行数据的 EOL 字符是什么,我想相应地处理该文件中的数据(我正在使用 Bulk Load 在 SQL Server 上创建表,需要将 EOL 传递给批量加载命令)。据我了解, Readline() 会自动处理 EOL,因此我无法解析 EOL 字符的 Readline() 字符串。下面的代码给出了我正在尝试做的一个例子:

int EOLChar_CRLF = 0;
int EOLChar_LF = 0;
int EOLChar_CR = 0;
int EOLChar_Hex = 0;

string eol_line = file2.ReadLine();
MessageBox.Show(eol_line);
EOLChar_CRLF = eol_line.IndexOf("\\r\\\n");
EOLChar_LF = eol_line.IndexOf("\\n");
EOLChar_CR = eol_line.IndexOf("\\r");
EOLChar_Hex = eol_line.IndexOf("\\0x0a");

MessageBox.Show("CRLF is line feed if " + EOLChar_CRLF.ToString() + " <> -1");
MessageBox.Show("LF is line feed if " + EOLChar_LF.ToString() + " <> -1");
MessageBox.Show("CR is line feed if " + EOLChar_CR.ToString() + " <> -1");
MessageBox.Show("0x0a is line feed if " + EOLChar_Hex.ToString() + " <> -1");

有人知道使用 StreamReader.ReadLine() 方法或任何其他方法来确定 EOL 的方法吗?我只想读取第一行数据并为 EOL 解析它,因为其中一些文件是 20+ 百万行。

【问题讨论】:

  • 如果不知道行终止符是什么,如何确定第一个“行”?对我来说,这听起来像是先有鸡还是先有蛋的问题。
  • 为什么你想知道(或)关心行分隔符是什么?它将是 \r\nboth(根据 MSDN)。 ReadLine() 方法会解决这个问题。
  • ReadLine() 自动处理终止符,这意味着无需确定 ReadLine 的 EOL 字符即可运行并提供第一行。我需要 ReadLine() 不显示的 EOL 字符,因为我必须将它作为参数传递到我的批量插入语句中。
  • 您的另一个选择是逐个字符地阅读,查找您预定义为 eol 类型的内容。

标签: c# eol


【解决方案1】:

确定文本文件的行尾约定的常用方法是从文件开始处插入足够大的缓冲区并检查它。当然,缓冲区的大小在某种程度上取决于预期的行长度。您想获取足够多的数据以获得合理数量的行。

除了 Windows (CR+LF)、Unix/Linux/OS X (LF) 或老式 MacOS (CR) 之外,您不太可能遇到行尾约定。就速度而言,很难击败这样的东西。

public enum EndOfLineStyle
{
  Unknown = 0     ,
  CR      = 1     ,
  LF      = 2     ,
  CRLF    = CR|LF ,
  Unix    = LF    ,
  MacOs   = CR    ,
  Windows = CRLF  ,
}

const int BUFFER_SIZE = 8192 ;
public EndOfLineStyle DetermineEndOfLineStyle( string pathToFile )
{
  int    bufl  = 0 ;
  char[] buf   = new char[BUFFER_SIZE] ;

  using ( StreamReader reader = File.OpenText( pathToFile ) )
  {
    bufl = reader.ReadBlock( buf , 0 , buf.Length ) ;
  }

  int crlfs = 0 ;
  int crs   = 0 ;
  int lfs   = 0 ;

  for ( int i = 0 ; i < bufl ; )
  {
    if      ( buf[i] == '\r' && i < bufl-1 && buf[i+1] == '\n' ) { ++crlfs ; i+=2 ; }
    else if ( buf[i] == '\r'                                   ) { ++crs   ; i+=1 ; }
    else if ( buf[i] == '\n' )                                   { ++lfs   ; i+=1 ; }
  }

  EndOfLineStyle style ;
  if      ( crlfs > crs   && crlfs > lfs ) style = EndOfLineStyle.Windows ;
  else if ( lfs   > crlfs && lfs   > crs ) style = EndOfLineStyle.Unix    ;
  else if ( crs   > crlfs && crs   > lfs ) style = EndOfLineStyle.MacOs   ;
  else                                     style = EndOfLineStyle.Unknown ;

  return style ;
}

【讨论】:

  • 非常感谢,尼古拉斯。这正是我一直在寻找的(一种允许我部分读取文件并获得 EOL 的解决方案)。
  • 以下代码似乎产生了一个无限循环,告诉我 EOL 没有落入 Windows、Unix 或 Mac。 for ( int i = 0 ; i
  • 是的,因为循环只检查 \r 和 \n 字符,索引变量不会增加。在循环中添加 else { i+=1;} 来解决这个问题。
猜你喜欢
  • 2019-10-10
  • 1970-01-01
  • 1970-01-01
  • 2010-09-14
  • 2011-03-20
  • 2017-07-25
  • 2014-10-16
  • 2010-12-23
  • 2018-12-06
相关资源
最近更新 更多