Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从文本文件';大小(以字节为单位)_C#_Character Encoding_Text Files - Fatal编程技术网

C# 从文本文件';大小(以字节为单位)

C# 从文本文件';大小(以字节为单位),c#,character-encoding,text-files,C#,Character Encoding,Text Files,好的,所以问题是:给定一个随机文本文件的FileInfo对象,并且知道该文件的编码(可以是ASCII、UTF7、UTF8、Unicode等),有没有一种方法可以在不读取文件的情况下获得该文件的准确字符数 您可以通过FileInfo.Length属性了解文件的字节大小,因此理论上了解编码的CharSize应该能够获得字符计数 使用某些编码(ASCII、Unicode)进行测试似乎是可行的,但其他编码则稍有偏差(例如UTF8) 这在一般情况下是可能的,还是必须读取整个文件才能始终获得可靠的字符计数?

好的,所以问题是:给定一个随机文本文件的
FileInfo
对象,并且知道该文件的编码(可以是ASCII、UTF7、UTF8、Unicode等),有没有一种方法可以在不读取文件的情况下获得该文件的准确字符数

您可以通过
FileInfo.Length
属性了解文件的字节大小,因此理论上了解编码的
CharSize
应该能够获得字符计数

使用某些编码(ASCII、Unicode)进行测试似乎是可行的,但其他编码则稍有偏差(例如UTF8)


这在一般情况下是可能的,还是必须读取整个文件才能始终获得可靠的字符计数?

在一般情况下,不读取整个内容是不可能的

原因是编码不能保证一个字符正好占用N个字节。例如,默认的C#编码Unicode,也称为UTF-16,允许一些字符为2或4字节(也可能是3字节-不确定,请参阅本主题)。其他一些编码可能允许您给出准确的数字,如ASCII,通常为7(填充为8)或8位

你可以得到一个很好的估计,但可能不是一个确切的数字

当你给用户一个估计值时,你可以提供一个解决方案,这将很快,因为你不需要阅读内容,如果用户想要得到准确的数字,你可以阅读内容并返回一个准确的数字,并且有一个明确的条件,这一过程可能需要一些时间。

问题 如前所述,由于以下原因,不读取所有字符是不可能的

您所做的是通过假设所有字符都适合最小的单位来近似字符数。当文件中只有
ASCII
字符时,这将完全适用于
UTF8
UTF16
等字符编码

更好的近似 如果您了解一种目标语言,则可以通过假设每个字符平均为一定数量的字节来更好地近似字符。例如,对于
UTF8
和英语,大多数字符都是1字节。您可以说一个字符平均占用
1.005
字节(每200个字符占用一个2字节字符),然后您可能会得到更好的近似值

更快的解码 因为读取整个文件的速度是个问题,所以我假设您处理的不是海量文件,就是大量文件。两者都有自己的问题。如果这两个都不是真的,那么无论如何尝试优化都没有意义

内存问题 两者都有各自的问题,在第一种情况下,内存可能一次无法装入内存(至少不是连续的,或者应用程序的其余部分正在运行)。解决方案是流式传输文件,而不是立即加载

缺点是C#没有提供一种有效的内置方法来计算流中的字符数。我能想到的唯一内置解决方案是中列出的解决方案。它确实考虑了代理项,您可以指定编码

速度问题 如果问题是文件数量过多,那么您可能已经花费了大量时间来查找每个文件的元数据。在这种情况下,我建议完全避免这个问题。如果您需要读取文件,您可能会从使用一个专门的函数中获得一些好处,在该函数中,您可以跨多个调用共享一个大型文件缓冲区。代码示例:

/// <summary>
/// Counts all the characters in a file sharing a reading buffer across multiple calls.
/// </summary>
/// <param name="filePath">The path to the file.</param>
/// <param name="encoding">Encoding to use.</param>
/// <param name="buffer">The buffer to share, will be recreated if it cannot contain the file.</param>
/// <returns>The amount of characters in the file.</returns>
public static int GetCharacterCount(string filePath, Encoding encoding, ref byte[] buffer)
{
    int fileLength;
    using (var fstream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        fileLength = (int)fstream.Length;
        // Expand the buffer if necessary
        if (buffer == null || buffer.Length < fileLength)
            buffer = new byte[fstream.Length];

        if (fstream.Read(buffer, 0, fileLength) != fileLength)
            throw new EndOfStreamException("Couldn't read all bytes from the file.");
    }

    return encoding.GetCharCount(buffer, 0, fileLength);
}
//
///统计多个调用中共享读取缓冲区的文件中的所有字符。
/// 
///文件的路径。
///要使用的编码。
///如果要共享的缓冲区不能包含文件,则将重新创建该缓冲区。
///文件中的字符数。
公共静态int GetCharacterCount(字符串文件路径、编码、引用字节[]缓冲区)
{
int文件长度;
使用(var fstream=newfilestream(filePath,FileMode.Open,FileAccess.Read,FileShare.Read))
{
fileLength=(int)fstream.Length;
//如有必要,展开缓冲区
if(buffer==null | | buffer.Length
回避问题 不必计算文件中的字符数,您可以尝试通过执行一次并存储来完全避免它。这样你甚至不需要解码文件,但你需要做一些簿记。如果经常使用查询,请刷新/创建几次,这可能是最好的方法。您可以使用文件名和字符数保留缓存,然后查询该缓存,而不是读取实际文件

这是否是一个有效的解决方案完全取决于您的用例

优化解码
如果您无法控制输入文件,并且这些文件可能过大或过多,那么通过编写专门的代码,您可以获得很大的收益。通过SIMD和缓存优化,您可以使用C语言。或者简单地在C#中使用更高效的文件访问模式。不管你选择哪条路,它都会很快变得毛茸茸的。一般来说,除非您的应用程序仅用于计算文件中的字符,否则我不会在这方面浪费时间。

谢谢!好消息。我们的问题是读取了很多文件。似乎没有办法解决这个问题,所以我们必须阅读文件并处理成本问题。