Как я избегаю чрезмерного Сетевого файла ввод-вывод при добавлении в большой файл с.NET?

У меня есть программа, которая открывает большой двоичный файл, добавляет небольшой объем данных к ним и закрывает файл.

FileStream fs = File.Open( "\\\\s1\\temp\\test.tmp", FileMode.Append, FileAccess.Write, FileShare.None );
fs.Write( data, 0, data.Length );
fs.Close();

Если test.tmp составит 5 МБ, прежде чем эта программа будет запущена, и массив данных составляет 100 байтов, эта программа заставит более чем 5 МБ данных быть переданными по сети. Я ожидал бы, что данные уже в файле не будут переданы по сети, так как я не читаю его или пишу его. Там какой-либо путь состоит в том, чтобы избежать этого поведения? Это заставляет его мучительно замедлиться для добавления в очень большие файлы.

7
задан John Saunders 30 June 2010 в 03:53
поделиться

7 ответов

0xA3 предоставил ответ в комментарии выше. Низкая производительность была вызвана сканированием на вирусы при доступе. Каждый раз, когда моя программа открывала файл, антивирусный сканер считывал все содержимое файла для проверки на вирусы, даже если моя программа не считывала какое-либо существующее содержимое. Отключение проверки на вирусы при доступе устранило чрезмерный сетевой ввод-вывод и низкую производительность.

Спасибо всем за ваши предложения.

2
ответ дан 8 December 2019 в 01:41
поделиться

Я нашел это в MSDN ( CreateFile вызывается внутренне):

Когда приложение создает файл в сети, лучше использовать GENERIC_READ | GENERIC_WRITE для dwDesiredAccess, чем использовать только GENERIC_WRITE. В результате код работает быстрее, потому что перенаправитель может использовать диспетчер кеша и отправлять меньшее количество SMB с большим объемом данных. Эта комбинация также позволяет избежать проблемы, когда запись в файл по сети может иногда возвращать ERROR_ACCESS_DENIED.

Используя Reflector, FileAccess сопоставляется с dwDesiredAccess , поэтому, похоже, предлагается использовать FileAccess.ReadWrite вместо только FileAccess.Write ].

Понятия не имею, поможет ли это :)

1
ответ дан 8 December 2019 в 01:41
поделиться

Вы можете кэшировать данные в локальный буфер и периодически (гораздо реже, чем сейчас) добавлять их в большой файл. Это сэкономило бы на кучу сетевых передач, но ... Это также увеличило бы риск потери этого кеша (и ваших данных) в случае сбоя вашего приложения.

Журналы (если это так) этого типа часто хранятся в базе данных. Использование достойной СУБД позволит вам публиковать эти 100 байтов данных очень часто с минимальными накладными расходами. Предостережение заключается в обслуживании СУБД.

0
ответ дан 8 December 2019 в 01:41
поделиться

Если у вас есть доступ к системе или, возможно, у вас есть дружелюбный администратор для машины, на которой фактически размещен файл, вы можете создать небольшую программу-слушатель, которая находится на другом конце.

Вы вызываете его, передавая только данные для записи, и он выполняет запись локально, избегая лишнего сетевого трафика.

0
ответ дан 8 December 2019 в 01:41
поделиться

Объект File в .NET имеет несколько статических методов для обработки такого рода вещей. Я бы посоветовал попробовать:

File file = File.AppendAllText("FilePath", "What to append", Encoding.UTF8);

Когда вы размышляете об этом методе, выясняется, что он использует:

  using (StreamWriter writer = new StreamWriter(path, true, encoding))
{
    writer.Write(contents);
}

Этот метод StreamWriter должен позволить вам просто добавить что-нибудь в конец (по крайней мере, это метод, который я видел, использованный в каждом экземпляр журнала, с которым я столкнулся до сих пор).

0
ответ дан 8 December 2019 в 01:41
поделиться

Записывайте данные в отдельные файлы, а затем объединяйте их (по возможности делайте это на хостинговой машине) только при необходимости.

0
ответ дан 8 December 2019 в 01:41
поделиться

Я погуглил и больше искал, как быстро читать слишком большие файлы, и нашел эту ссылку http://www.4guysfromrolla.com/webtech/010401-1.shtml

Самая интересная часть там будет часть о чтении байтов: Помимо более часто используемых методов ReadAll и ReadLine, объект TextStream также поддерживает метод Read (n), где n - количество байтов в рассматриваемом файле / текстовом потоке. Создавая экземпляр дополнительного объекта (файлового объекта), мы можем получить размер файла для чтения, а затем использовать метод Read (n) для обхода нашего файла. Как оказалось, метод "чтения байтов" по сравнению с ним чрезвычайно быстр:

const ForReading = 1
const TristateFalse = 0
dim strSearchThis
dim objFS
dim objFile
dim objTS
set objFS = Server.CreateObject("Scripting.FileSystemObject")
set objFile = objFS.GetFile(Server.MapPath("myfile.txt"))
set objTS = objFile.OpenAsTextStream(ForReading, TristateFalse)

strSearchThis = objTS.Read(objFile.Size)

if instr(strSearchThis, "keyword") > 0 then
Response.Write "Found it!"
end if

Этот метод затем может быть использован вами для перехода к концу файла и добавления его вручную вместо загрузки всего файла в режиме добавления с помощью файловый поток.

-3
ответ дан 8 December 2019 в 01:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: