web-dev-qa-db-ja.com

c#ファイル内の文字列を置換する

HTMLファイルのコンテンツの一部を置き換える場合、String.Replaceが適切に機能しないようです。たとえば、String.Replaceは</body></html>blah blah blah </body></html> html>に置き換えます。2番目のHTML終了タグが適切に閉じられていないため、ユーザーがブラウザでページをレンダリングしたときに表示されます。

なぜそれが意図したように機能していないのか誰か知っていますか?

StreamReader sr = fi.OpenText;
String fileContents = sr.ReadToEnd();
sr.close();
fileContents = fileContents.Replace("<body>", "<body onload='jsFx();' />");
fileContents = fileContents.Replace("</body>","blah blah blah </body>");

StreamWriter sw = new StreamWriter(fi.OpenWrite());
sw.WriteLine(contents);
sw.close();
23
Joey

私はあなたのコードを次のように書き直すかもしれません:

var fileContents = System.IO.File.ReadAllText(@"C:\File.html");

fileContents = fileContents.Replace("<body>", "<body onload='jsFx();' />"); 
fileContents = fileContents.Replace("</body>","blah blah blah </body>"); 

System.IO.File.WriteAllText(@"C:\File.html", fileContents);

このソリューションは、妥当なサイズのファイルには問題ないことに注意してください。ハードウェアにもよりますが、数十MB未満のもの。内容全体をメモリにロードします。非常に大きなファイルがある場合は、OutOfMemoryExceptionを防ぐために、一度に数百KBをストリーミングする必要がある場合があります。検索文字列が分割されているかどうかを確認するには、各チャンク間の区切りも確認する必要があるため、状況は少し複雑になります。

56
Nate

ここで_string.Replace_に問題はありません。

が間違っているのはファイルを上書きしているのに切り捨てていないということです...したがって、コードを単に

_sw.WriteLine("Start");
_

「開始」が表示され、ファイルの残りの部分が表示されます。

代わりに _File.ReadAllText_ および _File.WriteAllText_ を使用することをお勧めします(FileInfoからパスを取得します)。そのように:

  • 単に上書きするのではなく、ファイルを完全に置き換えます
  • リーダー/ライター/ストリームを適切に閉じることを心配する必要はありません(これは現在行っていません-例外が発生した場合、リーダーまたはライターを開いたままにします)

本当にFileInfoメソッドを使用したい場合は、FileInfo.Open(FileMode.Create)を使用してファイルを切り捨てます。

14
Jon Skeet