将大文本文件加载到字符串中

Nat*_*han 3 c# string file-handling

我想要将150 MB的文本文件加载到字符串中.该文件是UTF16编码的,因此它将生成一个内存大约150 MB的字符串.我尝试过的所有方法都会导致Out of Memory异常.

我知道这是一个巨大的字符串,当然不是我想做的事情.但是,目前我无能为力,没有对应用程序进行大量深刻更改即将出门.该文件中没有均匀分布的行集.一行可以包含整个文件大小的80%左右.

这是我尝试过的:

方法1

// Both of these throw Out of Memory exception
var s = File.ReadAllText(path)
var s = File.ReadAllText(path, Encoding.Unicode);
Run Code Online (Sandbox Code Playgroud)

方法2

var sb = new StringBuilder();

// I've also tried a few other iterations on this with other types of streams
using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (BufferedStream bs = new BufferedStream(fs))
using (StreamReader sr = new StreamReader(bs))
{
  string line;
  while ((line = sr.ReadLine()) != null)
  {
    sb.AppendLine(line);
  }
}

// This throws an exception
sb.ToString();
Run Code Online (Sandbox Code Playgroud)

方法3

using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (StreamReader sr = new StreamReader(fs, Encoding.Unicode))
{
  int initialSize = (int)fs.Length / 2;  // Comes to a value of 73285158 with my test file
  var sb = new StringBuilder(initialSize); // This throws an exception

  string line;
  while ((line = sr.ReadLine()) != null)
  {
    sb.AppendLine(line);
  }

  sb.ToString();
}
Run Code Online (Sandbox Code Playgroud)

那么,如何将此文件加载到字符串变量中呢?

编辑:添加了基于评论解决问题的其他尝试.

Jon*_*eet 5

到目前为止,您的两次尝试都将文件视为UTF-8.在最好的情况下,这将占用两倍的内存 - 而且很可能是无效数据(如UTF-8),基本上.您应该尝试指定编码:

var text = File.ReadAllText(path, Encoding.Unicode);
Run Code Online (Sandbox Code Playgroud)

如果这不起作用,你可以尝试第二个代码的变体,但是指定编码StreamReader(并且可能忽略了BufferedStream- 我认为它不会对你有所帮助),并且还指定了初始容量StringBuilder,等于文件大小的一半.

编辑:如果此行抛出异常:

var sb = new StringBuilder(initialSize);
Run Code Online (Sandbox Code Playgroud)

......那你就没有机会了.您无法分配足够的连续内存.

可能会发现你可以用一个List<string>代替:

var lines = File.ReadLines(path).ToList();
Run Code Online (Sandbox Code Playgroud)

...至少你有很多东西.这将需要更多的内存,但它不需要那么多的连续内存.这假设您确实需要一次在内存中的整个文件.如果你可以改为传输数据,那将是一个更好的选择.

在一个小型控制台应用程序中,我能够读取相同大小的文件,没有问题,使用File.ReadAllText32位和64位CLR ...所以它可能是你的物理内存和你还有什么问题正在做这个计划.