如何在不读取整个文件的情况下找出文件中有多少个字符?

3
如果文件是文本文件,并且StreamReader可以确定它使用的Encoding,那么我如何在不读取整个文件的情况下找出它有多少个字符?
我正在阅读1GB的CSV文件,使用StreamReader至少需要4秒钟。 File.ReadAllText().Length会导致System.OutOfMemoryException
我想象一下,如果我有FileInfo(filename).LengthEncoding,那么我就可以计算字符数。

这取决于编码类型,length将给出字节数,在ASCII中它将是字符数,但对于UTF / Unicode,直到解码之后才能知道。 - Jodrell
5个回答

4
你无法知道文件的长度,因为某些编码(尤其是UTF-8)具有可变字符宽度:一些字符只占用1个字节(ASCII),许多字符占用2个字节,甚至有3个或更多字节的情况。因此,在不解码字符的情况下,无法知道编码下文件的长度。
另外,据我所知,C#字符串中的所有字符都表示为UTF-16,因此,除非您有一个非常奇怪的文本(即您使用了许多来自平面0之外的字符),否则您可以通过将字符数乘以2轻松地估计其内存需求量(反之亦然,通过加倍字节大小来估算字符数)。
现在,一个更好的问题是 - 为什么你需要字符计数?您将如何处理CSV文件,并且为什么知道其大小会有所帮助?

+1。然而,编写一个计算文件中UTF-8编码字符数量的方法应该比使用Encoding.UTF8的StreamReader更快。 - dtb
那么估计呢?文件的前几行可以给我一个关于文件剩余字符数量的估计吗? - Jader Dias
1
@Jader Dias:如果你只需要一个估计值,并且你的文件中没有太多的非ASCII字符,那么你可以直接使用FileInfo.Length。 - dtb
@dtb 但是所有编码都使用1个字节来表示ASCII字符吗? - Jader Dias
2
@Chris Haas:不是全部都这样。例如,UTF-16对于所有字符(包括范围在U+0000到U+007F之间的字符)使用两个字节(代理对的情况下为四个字节)。UTF-32对于所有字符使用四个字节。 - dtb
显示剩余4条评论

1

对于ASCII、CP-437、CP-1252、ISO-8859-1或类似这些的代码页,字符数将等于字节数。

如果文件是UTF-16编码,则无法从字节数计算出字符数,但它可能与字节数/2相似。无论如何,您可以精确地计算出在.NET字符串中保存文件所需的内存大小,因为它将是文件的大小(因为.NET在内部使用UTF-16)加上一个恒定的开销。这样的字符串长度将是字节数除以2。

如果文件是UTF-8(或任何其他可变宽度编码),则字符数可能是多个字节的几倍,也可能是每个字节一个字符。这取决于数据。

如果文件是UTF-32(这极不可能),则字符数将完全等于文件长度(以字节为单位)除以4。但即使这是确切的字符数,它也不能指示从该文件创建的.NET字符串的长度,因为这可能涉及使用代理代码点来表示高位面的字符,因此答案仍然取决于您打算如何使用信息。


如何检测文件编码呢? - Jader Dias
1
@Jader Dias - 除非文件以字节顺序标记开头,否则没有可靠的方法来检测编码。有一些启发式算法可以用来猜测,但那是一个完全不同的大问题。(如果您不知道文件的编码,“文件中有多少个字符?”这个问题是毫无意义的。即使读取文件也无法告诉您,如果您不能正确地读取文件。) - Jeffrey L Whitledge
但我敢打赌 StreamReader 使用编码检测,即使它不可靠。 - Jader Dias
1
@Jader Dias - 如果你信任它,那就使用它。StreamReader有一个CurrentEncoding属性。它不需要你读取整个文件。 - Jeffrey L Whitledge

0

我认为它实际上是不可能的 - 一些编码使用不同数量的字节来编码字符,因此您需要将字节转换为字符才能找到字符数。

例如,在UTF-8中,从\u0000到\u007F的字符仅用1个字节表示;在\u0080和\u07FF之间需要2个字节,依此类推。


那么估计呢?文件的前几行可以给我一个文件剩余字符数的估计吗? - Jader Dias
只要你对这个估计满意,那就去做吧。如果你从100字节中得到90个字符,那么你可以估计90%的字节将是字符。使用更多的样本数据,你的估计将会更准确。 - Chris Haas

0

对于某些编码(如ASCII、Window 1262、IBM-850等),这是有效的,但对于UTF8和UTF7则不行,因为它们将一些字符编码为1个字节,一些字符编码为2个字节(我相信还有一些字符编码为更多的字节)。


如何估算字符数量?我能否知道文件的前100行的字节数和字符数,然后计算出文件的大约字符数?如何做到这一点? - Jader Dias
1
取决于内容。假设您有一个包含英文文本的UTF-8文件,然后跟随其后的是日语翻译。英文通常每个字符占用1个字节,而日语每个字符占用2个字节。如果您根据文件顶部进行估算,将得到非常错误的结果。 - Amadan
@Jader Dias,这是一种很好的方式来预设缓冲区并最小化重新分配。你可以变得更加高级,并保持一个运行估计来改善你的调整大小。 - Jodrell
@Amadan,这不是我的情况,我有一个非常普通的CSV文件。 - Jader Dias
我不知道对你来说什么是很普通的。我住在日本,所以我的情况对我来说并不太难以想象 :) - Amadan

0

问题在于,如果文件采用UTF8编码,则每个字符可能占据1到4个字节,因此您无法在不以某种方式处理文件的情况下“计算”字符数。

其他编码方法可能会更加有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接