2012-08-06 496 views
7

我正在通过FileStream更改文件(这是一个非常大的文件,我只需要在不重写整个文件的情况下更改标头)如何检测文件是否有Unix换行符( n)或Windows换行符( r n)?

该文件可以具有Unix或Windows换行符,对我来说很重要,以便我可以在更新文件时将正确的换行符写回文件中。

我可以编写一个简单的函数,使用FileStream以块的形式读取文件并检查换行字符

但是这个问题在之前必须解决,如果不是在C#那么在Win32 API中呢?

什么是检测文件的换行样式的最有效方法?

+0

不确定,因此评论,但它可能会使用正则表达式,如:'\ r \ n $'?这将检查换行以'\ r \ n'结尾。如果没有,那么它必须是Unix系列。 – npinti 2012-08-06 13:51:15

+0

不可能,因为使用.Net框架文件访问对象上的任何“ReadLine”方法去除换行符。如果你不关心一个文件使用的是什么样的换行样式,它们是很好的。如果我将文件作为流读取,我可以按照您的建议进行操作(基本上相当于我可能采取的方法..) – freshr 2012-08-06 14:03:30

+0

您能保证文件中的所有行结束符都是一致的吗?从技术上讲,在同一个文件中可能会有不同的混合行结束符。 – 2012-08-06 14:53:20

回答

2

非常感谢您的建议。我很惊讶没有找到容易重用的东西,所以我创建了一个简单的函数,我将它包含在这里。请注意,它只是找到第一个换行符(\ n或\ r \ n)并将其作为匹配返回。足够满足我的需求,但可能不够健壮。

public bool TryDetectNewLine(string path, out string newLine) 
    { 
     using (var fileStream = File.OpenRead(path)) 
     { 
      char prevChar = '\0'; 

      // Read the first 4000 characters to try and find a newline 
      for (int i = 0; i < 4000; i++) 
      { 
       int b; 
       if ((b = fileStream.ReadByte()) == -1) break; 

       char curChar = (char)b; 

       if (curChar == '\n') 
       { 
        newLine = prevChar == '\r' ? "\r\n" : "\n"; 
        return true; 
       } 

       prevChar = curChar; 
      } 

      // Returning false means could not determine linefeed convention 
      newLine = Environment.NewLine; 
      return false; 
     } 
    } 
2

不幸的是,如果是Unix或DOS文件,我不认为有一种方法可以100%确定,因为大多数编辑器在打开/保存时没有纠正错误结尾的文件。

我会读取该文件作为流和搜索的“\ r \ n”个出现的,只有“\ n”

使用一个简单的统计分析(即哪一个具有最高的命中计数)的搜索结果可能会给你正确的答案。如果文件很大,那么读取文件的第一个X%就足够了。

更简单的解决方案当然是只搜索“\ r \ n”,如果找到,则假定它是DOS文件。如果文件是机器生成的,这应该工作到100%。

至于.NET Framework/WinAPI中的任何现有代码,我还没有看到任何执行此操作的代码。

3

按照规定,如果不打开文本文件并通过字节流式传输,确实无法对文本文件的内容进行设置。如果您使用http下载文件,您可能会遇到麻烦,您可能会获得一种MIME类型来表示文件类型,但通常它只是“八位字节流”。当你可以蛮横强迫它,直到你找到一个换行符(“\ n”),然后备份一个字符,看看是否有回车符(“\ r”),我会采取更加平等的态度因为你必须以任何方式读取数据。

1)选择要读取的字节的样本大小,应该从文件中获取至少2或3条记录。

2)将每个字节的遭遇(我把这个单字节字符集设置在这里)存储为直方图。您可以通过将计数存储在由字节值索引的模式中来完成此操作,也可以使用字典。

3)看看回车和换行值计数。如果您有换行计数并且没有回车,那么它是一个unix文件。如果carraige返回和换行计数,那么它是一个Windows文件。

这种方法还允许您执行的操作是对入站文件进行质量检查。你有没有aplha数字直方图charcaters?然后有人向你传递了一个二进制文件。期待所有大写?然后在upercase字符外寻找计数。有很多检查可以避免处理非文本文件。

+1

你和@ Per的解决方案都假设所有的行结束符都是一致的,在野外,从技术上来说很可能有混合行结束标记。 – 2012-08-06 14:48:16

+2

没错,但是这里的练习是假设file is unix or windows。我假设入站文件是一种格式,或者是因为问题中提到的内容,如果一个预期的混合LF&CR/LF终止记录,那么它可能无关紧要行被终止。 – user957902 2012-08-06 14:58:46

相关问题