2017-05-29 90 views
-1

我必须编写一个字符串的实现,它将其值存储在硬盘驱动器而不是RAM(我知道它听起来多么愚蠢,但它的目的是教我们如何不同的排序算法工作RAM和硬盘驱动器)。这是我到目前为止已经写的:编辑一个文件的行编号

class HDDArray : IEnumerable<int> 
{ 
    private string filePath; 

    public int this[int index] 
    { 
     get 
     { 
      using (var reader = new StreamReader(filePath)) 
      { 
       string line = reader.ReadLine(); 

       for (int i = 0; i < index; i++) 
       { 
        line = reader.ReadLine(); 
       } 

       return Convert.ToInt32(line); 
      } 
     } 
     set 
     { 
      using (var fs = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite)) 
      { 
       var reader = new StreamReader(fs); 
       var writer = new StreamWriter(fs); 

       for (int i = 0; i < index; i++) 
       { 
        reader.ReadLine(); 
       } 

       writer.WriteLine(value); 
       writer.Dispose(); 
      } 
     } 
    } 

    public int Length 
    { 
     get 
     { 
      int length = 0; 

      using (var reader = new StreamReader(filePath)) 
      { 
       while (reader.ReadLine() != null) 
       { 
        length++; 
       } 
      } 

      return length; 
     } 
    } 

    public HDDArray(string file) 
    { 
     filePath = file; 

     if (File.Exists(file)) 
      File.WriteAllText(file, String.Empty); 
     else 
      File.Create(file).Dispose(); 
    } 

    public IEnumerator<int> GetEnumerator() 
    { 
     using (var reader = new StreamReader(filePath)) 
     { 
      string line; 
      while ((line = reader.ReadLine()) != null) 
      { 
       yield return Convert.ToInt32(line); 
      } 
     } 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

我面对试图在当编辑线(分度器的设定部分),我最终加入了新的生产线,而不是编辑的问题旧的(这很明显,为什么,我只是不知道如何解决它)。

回答

1

你的阵列设计与整数工作。这样的类很容易创建,因为所有数字的长度都是4个字节。

class HDDArray : IEnumerable<int>, IDisposable 
{ 
    readonly FileStream stream; 
    readonly BinaryWriter writer; 
    readonly BinaryReader reader; 

    public HDDArray(string file) 
    { 
     stream = new FileStream(file, FileMode.Create, FileAccess.ReadWrite); 
     writer = new BinaryWriter(stream); 
     reader = new BinaryReader(stream); 
    } 

    public int this[int index] 
    { 
     get 
     { 
      stream.Position = index * 4; 
      return reader.ReadInt32(); 
     } 
     set 
     { 
      stream.Position = index * 4; 
      writer.Write(value); 
     } 
    } 

    public int Length 
    { 
     get 
     { 
      return (int)stream.Length/4; 
     } 
    } 

    public IEnumerator<int> GetEnumerator() 
    { 
     stream.Position = 0; 
     while (reader.PeekChar() != -1) 
      yield return reader.ReadInt32(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 

    public void Dispose() 
    { 
     reader?.Dispose(); 
     writer?.Dispose(); 
     stream?.Dispose(); 
    } 
} 

由于每个阵列元件的大小是已知的,我们可以简单地移动通过改变其Position属性以流。

BinaryWriterBinaryReader对编写和读取数字非常舒服。

开放式流操作非常繁重。因此,在创建课程时做一次。工作结束后,您需要自行清理。所以我实现了IDisposable接口。

用法:

HDDArray arr = new HDDArray("test.dat"); 

Console.WriteLine("Length: " + arr.Length); 

for (int i = 0; i < 10; i++) 
    arr[i] = i; 

Console.WriteLine("Length: " + arr.Length); 

foreach (var n in arr) 
    Console.WriteLine(n); 

// Console.WriteLine(arr[20]); // Exception! 

arr.Dispose(); // release resources 
+0

我不得不将'Encoding.ASCII'添加到作家和阅读器中,以免崩溃。似乎工作正常,谢谢。 – PoVa

0

我坚持纠正,但我不认为有一个简单的方法来重新写一个特定的行,所以你可能会发现重写该文件更容易 - 修改该行。

如下你可以改变你一套代码:

set 
    { 
    var allLinesInFile = File.ReadAllLines(filepath); 
    allLinesInFile[index] = value; 
    File.WriteAllLines(filepath, allLinesInFile); 
    } 

不用说,应该有存在一定的安全检查,以检查文件是否存在以及index < allLinesInFile.Length

+0

当然,如果数据在磁盘上的原因是因为它并没有装入内存,这将是有点问题的。人们可以从一个文件流入第二个文件,然后将新文件重命名为旧文件。 –

+0

好点@BenVoigt,写入临时文件将是一个更好的解决方案,如果有问题的文件可能会非常大。 – Steveland83

0

我觉得功课的缘故排序算法,你不需要打扰自己的内存大小问题。

当然请添加检查文件现有的阅读。

注:例如线计数从0开始

string[] lines = File.ReadAllLines(filePath); 

using (StreamWriter writer = new StreamWriter(filePath)) 
{ 
    for (int currentLineNmb = 0; currentLineNmb < lines.Length; currentLineNmb++) 
    { 
     if (currentLineNmb == lineToEditNmb) 
     { 
      writer.WriteLine(lineToWrite); 
      continue; 
     } 
     writer.WriteLine(lines[currentLineNmb]);     
    } 
}