代码之家  ›  专栏  ›  技术社区  ›  Axarydax

带滑动缓冲区的文件查看器

  •  0
  • Axarydax  · 技术社区  · 14 年前

    我想做一个简单的文本文件查看器,我希望它能够处理大文件(可能比计算机的内存大)。

    我知道我需要实现一个类似滑动缓冲区的东西,它将包含文件当前可见的部分。主要问题是确定行和文件偏移之间的关系。如果我只需要能够通过线路导航,我只需要一个 行的链表

    所以我想知道的是,什么样的数据结构适合将这几行代码保存在内存中(这些代码将被绘制在屏幕上)。

    请记住,我不需要编辑文件,只需查看它们,所以我不需要关心所选编辑方法的效率。

    1 回复  |  直到 14 年前
        1
  •  0
  •   Jeff LaFay    14 年前

    如果通过文件流读取已定义的字节块,则可以跟踪最后读取的字节,以便知道下一步从何处读取文件中的更多数据块。FileStream公开Read(),允许您指定偏移字节(开始位置)以及一次读取多少字节。

    例如,在读入字节后,可以用解码器将它们解码为UTF8,然后用它检索char数组。所有这些都应该初始化您的初始数据。我会做什么,因为这将显示在某个地方是设置事件处理程序绑定到滚动。当您开始向下滚动时,您可以从内存中删除最上面的行(同时在删除前计算它们的字节数,这样您就可以动态读取下一组具有相同精确大小的字节)并将新行附加到最下面。向上滚动也是如此。

    下面是从文件中读取预定义字节数的方法。

    public static LastByteRead = 0; // keep it zero indexed
    
    public String[] GetFileChunk( String path, long chunkByteSize )
    {
        FileStream fStream;
        String[] FileTextLines;
        int SuccessBytes = 0;
        long StreamSize;
        byte[] FileBytes;
        char[] FileTextChars;
        Decoder UtfDecoder = Encoding.UTF8.GetDecoder();
        FileInfo TextFileInfo = new FileInfo(path);
    
        if( File.Exists(path) )
        {
            try {
                StreamSize = (TextFileInfo.Length >= chunkByteSize) ? chunkByteSize : TextFileInfo.Length;
                fStream = new FileStream( path, FileMode.Open, FileAccess.Read );
                FileBytes = new byte[ StreamSize ];
                FileTextChars = new char[ StreamSize ]; // this can be same size since it's UTF-8 (8bit chars)
    
                SuccessBytes = fStream.Read( FileBytes, 0, (Int32)StreamSize );
    
                if( SuccessBytes > 0 )
                {
                    UtfDecoder.GetChars( FileBytes, 0, StreamSize, FileTextChars, 0 );
                    LastByteRead = SuccessBytes - 1;
    
                    return 
                        String.Concat( fileTextChars.ToArray<char>() ).Split('\n');
                }
    
                else
                    return new String[1] {""};
            }
    
            catch {
                var errorException = "ERROR: " + ex.Message;
                Console.Writeline( errorException );
            }
    
            finally {
                fStream.Close();
            }   
        }   
    }